From d140e2449f8a510bc740492e44d9643cbbc3eae0 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 9 Aug 2018 16:14:35 +0200 Subject: [PATCH 01/18] Support authentication --- package-lock.json | 6 ++ package.json | 1 + .../framework/lib/bootstrap/TalkContext.tsx | 6 ++ .../framework/lib/bootstrap/createContext.tsx | 21 ++++- .../framework/lib/network/fetchQuery.ts | 23 +++-- .../client/framework/lib/network/index.ts | 2 +- .../lib/storage/InMemoryStorage.spec.ts | 25 ++++++ .../framework/lib/storage/InMemoryStorage.ts | 45 ++++++++++ .../framework/lib/storage/LocalStorage.ts | 5 ++ .../framework/lib/storage/SessionStorage.ts | 5 ++ .../client/framework/lib/storage/index.ts | 3 + .../lib/storage/prefixStorage.spec.ts | 86 +++++++++++++++++++ .../framework/lib/storage/prefixStorage.ts | 41 +++++++++ .../mutations/SetAuthTokenMutation.spec.ts | 34 ++++++++ .../mutations/SetAuthTokenMutation.ts | 34 ++++++++ src/core/client/framework/mutations/index.ts | 5 ++ src/core/client/stream/index.tsx | 2 +- .../__snapshots__/initLocalState.spec.ts.snap | 1 + .../stream/local/initLocalState.spec.ts | 16 +++- .../client/stream/local/initLocalState.ts | 9 +- src/core/client/stream/local/local.graphql | 1 + src/core/client/test/setup.ts | 1 + 22 files changed, 357 insertions(+), 15 deletions(-) create mode 100644 src/core/client/framework/lib/storage/InMemoryStorage.spec.ts create mode 100644 src/core/client/framework/lib/storage/InMemoryStorage.ts create mode 100644 src/core/client/framework/lib/storage/LocalStorage.ts create mode 100644 src/core/client/framework/lib/storage/SessionStorage.ts create mode 100644 src/core/client/framework/lib/storage/index.ts create mode 100644 src/core/client/framework/lib/storage/prefixStorage.spec.ts create mode 100644 src/core/client/framework/lib/storage/prefixStorage.ts create mode 100644 src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts create mode 100644 src/core/client/framework/mutations/SetAuthTokenMutation.ts create mode 100644 src/core/client/framework/mutations/index.ts diff --git a/package-lock.json b/package-lock.json index 100de84ee..c504d8d7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12988,6 +12988,12 @@ "pretty-format": "^23.2.0" } }, + "jest-localstorage-mock": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.2.0.tgz", + "integrity": "sha512-x+P0vcwr4540bCAYzTEpiD9rs+zh/QZzyiABV+MU6yM2OPwPlrrLyUx/6gValMyt6tg5lX6Z53o2rHWfUht5Xw==", + "dev": true + }, "jest-matcher-utils": { "version": "23.2.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.2.0.tgz", diff --git a/package.json b/package.json index d546b9c17..5e5d7b210 100644 --- a/package.json +++ b/package.json @@ -151,6 +151,7 @@ "html-webpack-plugin": "^3.2.0", "jest": "^23.4.1", "jest-junit": "^5.1.0", + "jest-localstorage-mock": "^2.2.0", "jsdom": "^11.11.0", "loader-utils": "^1.1.0", "material-design-icons": "^3.0.1", diff --git a/src/core/client/framework/lib/bootstrap/TalkContext.tsx b/src/core/client/framework/lib/bootstrap/TalkContext.tsx index 90ed10530..f7987877c 100644 --- a/src/core/client/framework/lib/bootstrap/TalkContext.tsx +++ b/src/core/client/framework/lib/bootstrap/TalkContext.tsx @@ -18,6 +18,12 @@ export interface TalkContext { /** formatter for timeago. */ timeagoFormatter?: Formatter; + /** Session Storage */ + localStorage: Storage; + + /** Session storage */ + sessionStorage: Storage; + /** * A way to listen for clicks that are e.g. outside of the * current frame for `ClickOutside` diff --git a/src/core/client/framework/lib/bootstrap/createContext.tsx b/src/core/client/framework/lib/bootstrap/createContext.tsx index 2e6bd2aff..5c71cb386 100644 --- a/src/core/client/framework/lib/bootstrap/createContext.tsx +++ b/src/core/client/framework/lib/bootstrap/createContext.tsx @@ -5,11 +5,16 @@ import { Child as PymChild } from "pym.js"; import React from "react"; import { Formatter } from "react-timeago"; import { Environment, Network, RecordSource, Store } from "relay-runtime"; +import { LOCAL_ID } from "talk-framework/lib/relay"; +import { + createLocalStorage, + createSessionStorage, +} from "talk-framework/lib/storage"; import { ClickFarAwayRegister } from "talk-ui/components/ClickOutside"; import { generateMessages, LocalesData, negotiateLanguages } from "../i18n"; -import { fetchQuery } from "../network"; +import { createFetch, TokenGetter } from "../network"; import { TalkContext } from "./TalkContext"; interface CreateContextArguments { @@ -61,9 +66,17 @@ export default async function createContext({ eventEmitter = new EventEmitter2({ wildcard: true }), }: CreateContextArguments): Promise { // Initialize Relay. + const source = new RecordSource(); + const tokenGetter: TokenGetter = () => { + const localState = source.get(LOCAL_ID); + if (localState) { + return localState.authToken || ""; + } + return ""; + }; const relayEnvironment = new Environment({ - network: Network.create(fetchQuery), - store: new Store(new RecordSource()), + network: Network.create(createFetch(tokenGetter)), + store: new Store(source), }); // Listen for outside clicks. @@ -99,6 +112,8 @@ export default async function createContext({ pym, eventEmitter, registerClickFarAway, + localStorage: createLocalStorage(), + sessionStorage: createSessionStorage(), }; // Run custom initializations. diff --git a/src/core/client/framework/lib/network/fetchQuery.ts b/src/core/client/framework/lib/network/fetchQuery.ts index 6a5d4bb82..bc6b734d3 100644 --- a/src/core/client/framework/lib/network/fetchQuery.ts +++ b/src/core/client/framework/lib/network/fetchQuery.ts @@ -26,17 +26,28 @@ function getError(errors: Error[]): Error { return new GraphQLError(errors as any); } +export type TokenGetter = () => string; +type CreateFetch = (token?: TokenGetter) => FetchFunction; + /** - * fetchQuery is a simple implementation of the `FetchFunction` + * createFetch returns a simple implementation of the `FetchFunction` * required by Relay. It'll return a `NetworkError` on failure. */ -const fetchQuery: FetchFunction = async (operation, variables) => { +const createFetch: CreateFetch = tokenGetter => async ( + operation, + variables +) => { + const token = tokenGetter && tokenGetter(); + const headers: Record = { + "Content-Type": "application/json", + }; + if (token) { + headers.Authorization = `Bearer ${token}`; + } try { const response = await fetch("/api/tenant/graphql", { method: "POST", - headers: { - "Content-Type": "application/json", - }, + headers, body: JSON.stringify({ query: operation.text, variables, @@ -58,4 +69,4 @@ const fetchQuery: FetchFunction = async (operation, variables) => { } }; -export default fetchQuery; +export default createFetch; diff --git a/src/core/client/framework/lib/network/index.ts b/src/core/client/framework/lib/network/index.ts index 57943dc38..75b935dce 100644 --- a/src/core/client/framework/lib/network/index.ts +++ b/src/core/client/framework/lib/network/index.ts @@ -1 +1 @@ -export { default as fetchQuery } from "./fetchQuery"; +export { default as createFetch, TokenGetter } from "./fetchQuery"; diff --git a/src/core/client/framework/lib/storage/InMemoryStorage.spec.ts b/src/core/client/framework/lib/storage/InMemoryStorage.spec.ts new file mode 100644 index 000000000..8c141ed61 --- /dev/null +++ b/src/core/client/framework/lib/storage/InMemoryStorage.spec.ts @@ -0,0 +1,25 @@ +import createInMemoryStorage from "./InMemoryStorage"; + +it("should set and unset values", () => { + const storage = createInMemoryStorage(); + storage.setItem("test", "value"); + expect(storage.getItem("test")).toBe("value"); + storage.removeItem("test"); + expect(storage.getItem("test")).toBeUndefined(); +}); + +it("should return length", () => { + const storage = createInMemoryStorage(); + storage.setItem("a", "value"); + storage.setItem("b", "value"); + storage.setItem("c", "value"); + expect(storage.length).toBe(3); +}); + +it("should nth value", () => { + const storage = createInMemoryStorage(); + storage.setItem("a", "a"); + storage.setItem("b", "b"); + storage.setItem("c", "c"); + expect(storage.key(2)).toBe("c"); +}); diff --git a/src/core/client/framework/lib/storage/InMemoryStorage.ts b/src/core/client/framework/lib/storage/InMemoryStorage.ts new file mode 100644 index 000000000..3c5b15d7c --- /dev/null +++ b/src/core/client/framework/lib/storage/InMemoryStorage.ts @@ -0,0 +1,45 @@ +/** + * InMemoryStorage is a dumb implementation of the Storage interface that will + * not persist the data at all. It implements the Storage interface found: + * + * https://developer.mozilla.org/en-US/docs/Web/API/Storage + */ +class InMemoryStorage implements Storage { + private storage: Record; + + constructor() { + this.storage = {}; + } + + get length() { + return Object.keys(this.storage).length; + } + + public clear() { + this.storage = {}; + } + + public key(n: number) { + if (this.length <= n) { + return null; + } + + return this.storage[Object.keys(this.storage)[n]]; + } + + public getItem(key: string) { + return this.storage[key]; + } + + public setItem(key: string, value: string) { + this.storage[key] = value; + } + + public removeItem(key: string) { + delete this.storage[key]; + } +} + +export default function createInMemoryStorage() { + return new InMemoryStorage(); +} diff --git a/src/core/client/framework/lib/storage/LocalStorage.ts b/src/core/client/framework/lib/storage/LocalStorage.ts new file mode 100644 index 000000000..72588d880 --- /dev/null +++ b/src/core/client/framework/lib/storage/LocalStorage.ts @@ -0,0 +1,5 @@ +import prefixStorage from "./prefixStorage"; + +export default function createLocalStorage(): Storage { + return prefixStorage(window.localStorage, "talk"); +} diff --git a/src/core/client/framework/lib/storage/SessionStorage.ts b/src/core/client/framework/lib/storage/SessionStorage.ts new file mode 100644 index 000000000..7b45e09a3 --- /dev/null +++ b/src/core/client/framework/lib/storage/SessionStorage.ts @@ -0,0 +1,5 @@ +import prefixStorage from "./prefixStorage"; + +export default function createSessionStorage(): Storage { + return prefixStorage(window.sessionStorage, "talk"); +} diff --git a/src/core/client/framework/lib/storage/index.ts b/src/core/client/framework/lib/storage/index.ts new file mode 100644 index 000000000..a558f693b --- /dev/null +++ b/src/core/client/framework/lib/storage/index.ts @@ -0,0 +1,3 @@ +export { default as createInMemoryStorage } from "./InMemoryStorage"; +export { default as createLocalStorage } from "./LocalStorage"; +export { default as createSessionStorage } from "./SessionStorage"; diff --git a/src/core/client/framework/lib/storage/prefixStorage.spec.ts b/src/core/client/framework/lib/storage/prefixStorage.spec.ts new file mode 100644 index 000000000..6e8e8088d --- /dev/null +++ b/src/core/client/framework/lib/storage/prefixStorage.spec.ts @@ -0,0 +1,86 @@ +import sinon from "sinon"; +import prefixStorage from "./prefixStorage"; + +it("should call clear", () => { + const storage = { + clear: sinon.mock().once(), + }; + + const prefixed = prefixStorage(storage as any, "talk"); + prefixed.clear(); + storage.clear.verify(); +}); + +it("should call length", () => { + const ret = 10; + const storage = { + get length() { + return ret; + }, + }; + + const prefixed = prefixStorage(storage as any, "talk"); + expect(prefixed.length).toBe(ret); +}); + +it("should call key", () => { + const ret = "value"; + const storage = { + key: sinon + .mock() + .withArgs(3) + .returns(ret), + }; + + const prefixed = prefixStorage(storage as any, "talk"); + expect(prefixed.key(3)).toBe(ret); + (storage.key as any).verify(); +}); + +it("should call key", () => { + const ret = "value"; + const storage = { + key: sinon + .mock() + .withArgs(3) + .returns(ret), + }; + + const prefixed = prefixStorage(storage as any, "talk"); + expect(prefixed.key(3)).toBe(ret); + (storage.key as any).verify(); +}); + +it("should prefix setItem", () => { + const storage = { + setItem: sinon.mock().withArgs("talk:key", "value"), + }; + + const prefixed = prefixStorage(storage as any, "talk"); + prefixed.setItem("key", "value"); + storage.setItem.verify(); +}); + +it("should prefix removeItem", () => { + const storage = { + removeItem: sinon.mock().withArgs("talk:key"), + }; + + const prefixed = prefixStorage(storage as any, "talk"); + prefixed.removeItem("key"); + storage.removeItem.verify(); +}); + +it("should prefix getItem", () => { + const ret = "value"; + const storage = { + getItem: sinon + .mock() + .withArgs("talk:key") + .returns(ret), + }; + + const prefixed = prefixStorage(storage as any, "talk"); + expect(prefixed.getItem("key")).toBe(ret); + (storage.getItem as any).verify(); +}); diff --git a/src/core/client/framework/lib/storage/prefixStorage.ts b/src/core/client/framework/lib/storage/prefixStorage.ts new file mode 100644 index 000000000..c44f7c364 --- /dev/null +++ b/src/core/client/framework/lib/storage/prefixStorage.ts @@ -0,0 +1,41 @@ +/** + * PrefixedStorage decorates a Storage and prefixes keys in + * getItem, setItem and removeItem with given prefix. + */ +class PrefixedStorage implements Storage { + private storage: Storage; + private prefix: string; + + constructor(storage: Storage, prefix: string) { + this.storage = storage; + this.prefix = prefix; + } + + get length() { + return this.storage.length; + } + + public clear() { + this.storage.clear(); + } + + public key(n: number) { + return this.storage.key(n); + } + + public getItem(key: string) { + return this.storage.getItem(`${this.prefix}:${key}`); + } + + public setItem(key: string, value: string) { + return this.storage.setItem(`${this.prefix}:${key}`, value); + } + + public removeItem(key: string) { + return this.storage.removeItem(`${this.prefix}:${key}`); + } +} + +export default function prefixStorage(storage: Storage, prefix: string) { + return new PrefixedStorage(storage, prefix); +} diff --git a/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts b/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts new file mode 100644 index 000000000..7440078ad --- /dev/null +++ b/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts @@ -0,0 +1,34 @@ +import { commitLocalUpdate, Environment, RecordSource } from "relay-runtime"; + +import { timeout } from "talk-common/utils"; +import { LOCAL_ID } from "talk-framework/lib/relay"; +import { createRelayEnvironment } from "talk-framework/testHelpers"; + +import { commit } from "./SetAuthTokenMutation"; + +let environment: Environment; +const source: RecordSource = new RecordSource(); + +beforeAll(() => { + environment = createRelayEnvironment({ + source, + }); +}); + +it("Sets auth token", async () => { + const authToken = "auth token"; + commit(environment, { authToken }); + expect(source.get(LOCAL_ID)!.authToken).toEqual(authToken); +}); + +it("Should call gc", async () => { + commitLocalUpdate(environment, store => { + store.create("should-disappear", "tmp"); + }); + const authToken = null; + expect(source.get("should-disappear")).not.toBeUndefined(); + commit(environment, { authToken }); + await timeout(); + expect(source.get(LOCAL_ID)!.authToken).toEqual(authToken); + expect(source.get("should-disappear")).toBeUndefined(); +}); diff --git a/src/core/client/framework/mutations/SetAuthTokenMutation.ts b/src/core/client/framework/mutations/SetAuthTokenMutation.ts new file mode 100644 index 000000000..38ecde460 --- /dev/null +++ b/src/core/client/framework/mutations/SetAuthTokenMutation.ts @@ -0,0 +1,34 @@ +import { commitLocalUpdate, Environment } from "relay-runtime"; + +import { createMutationContainer } from "talk-framework/lib/relay"; +import { LOCAL_ID } from "talk-framework/lib/relay/withLocalStateContainer"; + +export interface SetAuthTokenInput { + authToken: string | null; +} + +export type SetAuthTokenMutation = (input: SetAuthTokenInput) => Promise; + +export async function commit( + environment: Environment, + input: SetAuthTokenInput +) { + return commitLocalUpdate(environment, store => { + const record = store.get(LOCAL_ID)!; + record.setValue(input.authToken, "authToken"); + + // Force gc to trigger. + environment + .retain({ + dataID: "tmp", + node: { selections: [] }, + variables: {}, + }) + .dispose(); + }); +} + +export const withSetAuthTokenMutation = createMutationContainer( + "setCommentID", + commit +); diff --git a/src/core/client/framework/mutations/index.ts b/src/core/client/framework/mutations/index.ts new file mode 100644 index 000000000..21875e6d8 --- /dev/null +++ b/src/core/client/framework/mutations/index.ts @@ -0,0 +1,5 @@ +export { + withSetAuthTokenMutation, + SetAuthTokenMutation, + SetAuthTokenInput, +} from "./SetAuthTokenMutation"; diff --git a/src/core/client/stream/index.tsx b/src/core/client/stream/index.tsx index 6d622216e..d6619f706 100644 --- a/src/core/client/stream/index.tsx +++ b/src/core/client/stream/index.tsx @@ -18,7 +18,7 @@ const pymFeatures = [withSetCommentID]; // This is called when the context is first initialized. async function init(context: TalkContext) { - await initLocalState(context.relayEnvironment); + await initLocalState(context.relayEnvironment, context); pymFeatures.forEach(f => f(context)); } diff --git a/src/core/client/stream/local/__snapshots__/initLocalState.spec.ts.snap b/src/core/client/stream/local/__snapshots__/initLocalState.spec.ts.snap index 52ffec402..c8dda11c7 100644 --- a/src/core/client/stream/local/__snapshots__/initLocalState.spec.ts.snap +++ b/src/core/client/stream/local/__snapshots__/initLocalState.spec.ts.snap @@ -12,6 +12,7 @@ exports[`init local state 1`] = ` \\"client:root.local\\": { \\"__id\\": \\"client:root.local\\", \\"__typename\\": \\"Local\\", + \\"authToken\\": \\"\\", \\"network\\": { \\"__ref\\": \\"client:root.local.network\\" }, diff --git a/src/core/client/stream/local/initLocalState.spec.ts b/src/core/client/stream/local/initLocalState.spec.ts index d1842c9a5..2d2a3b486 100644 --- a/src/core/client/stream/local/initLocalState.spec.ts +++ b/src/core/client/stream/local/initLocalState.spec.ts @@ -2,6 +2,7 @@ import { Environment, RecordSource } from "relay-runtime"; import { timeout } from "talk-common/utils"; import { LOCAL_ID } from "talk-framework/lib/relay"; +import { createInMemoryStorage } from "talk-framework/lib/storage"; import { createRelayEnvironment } from "talk-framework/testHelpers"; import initLocalState from "./initLocalState"; @@ -18,7 +19,7 @@ beforeEach(() => { }); it("init local state", async () => { - initLocalState(environment); + initLocalState(environment, { localStorage: createInMemoryStorage() } as any); await timeout(); expect(JSON.stringify(source.toJSON(), null, 2)).toMatchSnapshot(); }); @@ -32,7 +33,7 @@ it("set assetID from query", () => { document.title, `http://localhost/?assetID=${assetID}` ); - initLocalState(environment); + initLocalState(environment, { localStorage: createInMemoryStorage() } as any); expect(source.get(LOCAL_ID)!.assetID).toBe(assetID); window.history.replaceState(previousState, document.title, previousLocation); }); @@ -46,7 +47,16 @@ it("set commentID from query", () => { document.title, `http://localhost/?commentID=${commentID}` ); - initLocalState(environment); + initLocalState(environment, { localStorage: createInMemoryStorage() } as any); expect(source.get(LOCAL_ID)!.commentID).toBe(commentID); window.history.replaceState(previousState, document.title, previousLocation); }); + +it("set authToken from localStorage", () => { + const authToken = "auth-token"; + const localStorage = createInMemoryStorage(); + localStorage.setItem("authToken", authToken); + initLocalState(environment, { localStorage } as any); + expect(source.get(LOCAL_ID)!.authToken).toBe(authToken); + localStorage.removeItem("authToken"); +}); diff --git a/src/core/client/stream/local/initLocalState.ts b/src/core/client/stream/local/initLocalState.ts index 827e90c50..dd021f756 100644 --- a/src/core/client/stream/local/initLocalState.ts +++ b/src/core/client/stream/local/initLocalState.ts @@ -1,6 +1,7 @@ import qs from "query-string"; import { commitLocalUpdate, Environment } from "relay-runtime"; +import { TalkContext } from "talk-framework/lib/bootstrap"; import { createAndRetain, LOCAL_ID, @@ -17,7 +18,10 @@ import { /** * Initializes the local state, before we start the App. */ -export default async function initLocalState(environment: Environment) { +export default async function initLocalState( + environment: Environment, + { localStorage }: TalkContext +) { commitLocalUpdate(environment, s => { const root = s.getRoot(); @@ -25,6 +29,9 @@ export default async function initLocalState(environment: Environment) { const localRecord = createAndRetain(environment, s, LOCAL_ID, LOCAL_TYPE); root.setLinkedRecord(localRecord, "local"); + // Set auth token + localRecord.setValue(localStorage.getItem("authToken") || "", "authToken"); + // Parse query params const query = qs.parse(location.search); diff --git a/src/core/client/stream/local/local.graphql b/src/core/client/stream/local/local.graphql index 52604d35b..37426b867 100644 --- a/src/core/client/stream/local/local.graphql +++ b/src/core/client/stream/local/local.graphql @@ -21,6 +21,7 @@ type Local { assetURL: String commentID: String authPopup: AuthPopup! + authToken: String } extend type Query { diff --git a/src/core/client/test/setup.ts b/src/core/client/test/setup.ts index 1609f2653..de1ba3c31 100644 --- a/src/core/client/test/setup.ts +++ b/src/core/client/test/setup.ts @@ -1,3 +1,4 @@ +import "jest-localstorage-mock"; import "./enzyme"; import "./jsdom"; From 2a0f9cd9359563a6f771fdce65823088a4d815b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Thu, 9 Aug 2018 15:46:56 -0300 Subject: [PATCH 02/18] NO NORMALS --- src/core/client/ui/shared/typography.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/client/ui/shared/typography.css b/src/core/client/ui/shared/typography.css index 06287c62a..a4083aa74 100644 --- a/src/core/client/ui/shared/typography.css +++ b/src/core/client/ui/shared/typography.css @@ -132,7 +132,7 @@ font-family: var(--font-family); font-weight: var(--font-weight-medium); font-size: calc(16rem / var(--rem-base)); - line-height: normal; + line-height: calc(16rem / var(--rem-base)); letter-spacing: calc(0.2em / 16); } From dbcf3c57567e77cc57c97d8b190a2c89cd460fb3 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 12:07:46 +0200 Subject: [PATCH 03/18] Fix linter --- package-lock.json | 23 +++++++++++++------ package.json | 4 ++-- .../framework/lib/bootstrap/TalkContext.tsx | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index d853f3b07..9d97aba8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22383,9 +22383,9 @@ "dev": true }, "tslint": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz", - "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", "dev": true, "requires": { "babel-code-frame": "^6.22.0", @@ -22399,7 +22399,7 @@ "resolve": "^1.3.2", "semver": "^5.3.0", "tslib": "^1.8.0", - "tsutils": "^2.12.1" + "tsutils": "^2.27.2" }, "dependencies": { "glob": { @@ -22415,13 +22415,22 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } } } }, "tslint-config-prettier": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.13.0.tgz", - "integrity": "sha512-assE77K7K8Q9j8CVIHiU3d1uoKc8N5v7UPpkQ9IE8BEPWkvSYR37lDuYekDlAMFqR1IpD6CrS+uOJLl6pw7Wdw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.14.0.tgz", + "integrity": "sha512-SomD+aLvAwoihMtyCfkhhWKt9wcpSY2ZpgDV6OuxLYi8+7uOwE2g03aa+jJLSmY0Ys8s3ZLM5Iwfuwu3giCSQQ==", "dev": true }, "tslint-loader": { diff --git a/package.json b/package.json index 7aae0f6cb..1c4d0b1ce 100644 --- a/package.json +++ b/package.json @@ -196,8 +196,8 @@ "ts-node": "^6.2.0", "tsconfig-paths": "^3.4.2", "tsconfig-paths-webpack-plugin": "^3.1.4", - "tslint": "^5.10.0", - "tslint-config-prettier": "^1.13.0", + "tslint": "^5.11.0", + "tslint-config-prettier": "^1.14.0", "tslint-loader": "^3.6.0", "tslint-plugin-prettier": "^1.3.0", "tslint-react": "^3.6.0", diff --git a/src/core/client/framework/lib/bootstrap/TalkContext.tsx b/src/core/client/framework/lib/bootstrap/TalkContext.tsx index 7567f9412..06726bcb2 100644 --- a/src/core/client/framework/lib/bootstrap/TalkContext.tsx +++ b/src/core/client/framework/lib/bootstrap/TalkContext.tsx @@ -24,7 +24,7 @@ export interface TalkContext { /** Session storage */ sessionStorage: Storage; - + /** media query values for testing purposes */ mediaQueryValues?: MediaQueryMatchers; From c2f6095868baf1f0ce2cfea38ad76f12e66b4f24 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 13:10:37 +0200 Subject: [PATCH 04/18] Adapt typography --- .../ui/components/TextField/TextField.css | 11 +-- .../ui/components/TextField/TextField.mdx | 2 - .../ui/components/TextField/TextField.tsx | 4 ++ src/core/client/ui/shared/typography.css | 70 +++++++++++-------- src/core/client/ui/theme/variables.ts | 4 +- 5 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/core/client/ui/components/TextField/TextField.css b/src/core/client/ui/components/TextField/TextField.css index 335fc3734..970a4ce29 100644 --- a/src/core/client/ui/components/TextField/TextField.css +++ b/src/core/client/ui/components/TextField/TextField.css @@ -1,5 +1,5 @@ .root { - composes: textField from "talk-ui/shared/typography.css"; + composes: inputText placeholderPseudo from "talk-ui/shared/typography.css"; position: relative; display: block; padding: calc(0.5 * var(--spacing-unit)); @@ -22,12 +22,3 @@ .fullWidth { width: 100%; } - -::placeholder { - font-family: var(--font-family); - font-style: normal; - font-weight: normal; - line-height: calc(16rem / var(--rem-base)); - font-size: calc(16rem / var(--rem-base)); - color: var(--palette-grey-lighter); -} diff --git a/src/core/client/ui/components/TextField/TextField.mdx b/src/core/client/ui/components/TextField/TextField.mdx index bbfceb20d..7fee8bea9 100644 --- a/src/core/client/ui/components/TextField/TextField.mdx +++ b/src/core/client/ui/components/TextField/TextField.mdx @@ -18,5 +18,3 @@ import Flex from '../Flex' - - diff --git a/src/core/client/ui/components/TextField/TextField.tsx b/src/core/client/ui/components/TextField/TextField.tsx index 0383192ce..1c7089c4a 100644 --- a/src/core/client/ui/components/TextField/TextField.tsx +++ b/src/core/client/ui/components/TextField/TextField.tsx @@ -33,6 +33,10 @@ export interface TextFieldProps { * Placeholder */ placeholder?: string; + /** + * Mark as readonly + */ + readOnly?: boolean; } const TextField: StatelessComponent = props => { diff --git a/src/core/client/ui/shared/typography.css b/src/core/client/ui/shared/typography.css index 97a45a67e..677b168d2 100644 --- a/src/core/client/ui/shared/typography.css +++ b/src/core/client/ui/shared/typography.css @@ -59,33 +59,34 @@ .heading1 { font-size: calc(24rem / var(--rem-base)); font-weight: var(--font-weight-medium); - font-family: "Manuale"; + font-family: var(--font-family-serif); line-height: calc(32em / 24); - letter-spacing: calc(0.2em / 16); + letter-spacing: calc(0.2em / 24); color: var(--palette-text-primary); } .heading2 { font-size: calc(20rem / var(--rem-base)); font-weight: var(--font-weight-medium); - font-family: "Manuale"; + font-family: var(--font-family-serif); line-height: calc(24em / 20); + letter-spacing: calc(0.2em / 20); color: var(--palette-text-primary); } .heading3 { font-size: calc(18rem / var(--rem-base)); font-weight: var(--font-weight-medium); - font-family: "Manuale"; + font-family: var(--font-family-serif); line-height: calc(20em / 18); - letter-spacing: calc(0.2em / 16); + letter-spacing: calc(0.2em / 18); color: var(--palette-text-primary); } .heading4 { font-size: calc(16rem / var(--rem-base)); font-weight: var(--font-weight-medium); - font-family: "Manuale"; + font-family: var(--font-family-serif); line-height: calc(18em / 16); letter-spacing: calc(0.2em / 16); color: var(--palette-text-primary); @@ -94,7 +95,7 @@ .bodyCopy { font-size: calc(16rem / var(--rem-base)); font-weight: var(--font-weight-regular); - font-family: "Source Sans Pro"; + font-family: var(--font-family-sans-serif); line-height: calc(18em / 16); letter-spacing: calc(0.2em / 16); color: var(--palette-text-primary); @@ -107,44 +108,44 @@ .button { color: var(--palette-text-secondary); - font-family: "Source Sans Pro"; + font-family: var(--font-family-sans-serif); font-weight: var(--font-weight-medium); - font-size: 14px; - line-height: calc(18em / 16); - letter-spacing: calc(0.57em / 16); + font-size: calc(14rem / var(--rem-base)); + line-height: calc(18em / 14); + letter-spacing: calc(0.57em / 14); } .buttonLarge { color: var(--palette-text-secondary); - font-family: "Source Sans Pro"; + font-family: var(--font-family-sans-serif); font-weight: var(--font-weight-medium); - font-size: 16px; + font-size: calc(16rem / var(--rem-base)); line-height: calc(20em / 16); letter-spacing: calc(0.57em / 16); } .timestamp { color: var(--palette-text-secondary); - font-family: "Source Sans Pro"; + font-family: var(--font-family-sans-serif); font-weight: var(--font-weight-medium); - font-size: 14px; - line-height: calc(18em / 16); - letter-spacing: calc(0.2em / 16); + font-size: calc(14rem / var(--rem-base)); + line-height: calc(18em / 14); + letter-spacing: 0; } .alertMessage { color: var(--palette-common-black); - font-family: var(--font-family); + font-family: var(--font-family-sans-serif); font-weight: var(--font-weight-medium); font-size: calc(16rem / var(--rem-base)); - line-height: calc(16rem / var(--rem-base)); - letter-spacing: calc(0.2em / 16); + line-height: calc(16em / 16); + letter-spacing: calc(-0.1em / 16); } -.textField { - font-size: calc(16rem / var(--rem-base)); +.inputText { font-weight: var(--font-weight-regular); - font-family: var(--font-family); + font-family: var(--font-family-sans-serif); + font-size: calc(16rem / var(--rem-base)); line-height: calc(18em / 16); letter-spacing: calc(0.2em / 16); color: var(--palette-text-primary); @@ -153,17 +154,26 @@ .inputLabel { font-size: calc(18rem / var(--rem-base)); font-weight: var(--font-weight-medium); - font-family: "Manuale"; - line-height: calc(18em / 16); - letter-spacing: calc(0.2em / 16); + font-family: var(--font-family-serif); + line-height: calc(18em / 18); + letter-spacing: calc(0.2em / 18); color: var(--palette-text-primary); } .placeholder { - font-family: var(--font-family); - font-style: normal; - font-weight: normal; - line-height: calc(16rem / var(--rem-base)); + font-family: var(--font-family-sans-serif); + font-weight: var(--font-weight-regular); font-size: calc(16rem / var(--rem-base)); + line-height: calc(20em / 16); + letter-spacing: 0; + color: var(--palette-grey-lighter); +} + +.placeholderPseudo::placeholder { + font-family: var(--font-family-sans-serif); + font-weight: var(--font-weight-regular); + font-size: calc(16rem / var(--rem-base)); + line-height: calc(20em / 16); + letter-spacing: 0; color: var(--palette-grey-lighter); } diff --git a/src/core/client/ui/theme/variables.ts b/src/core/client/ui/theme/variables.ts index a5ae14893..c6065ab2f 100644 --- a/src/core/client/ui/theme/variables.ts +++ b/src/core/client/ui/theme/variables.ts @@ -64,8 +64,8 @@ const variables = { roundCorners: "2px", /* Typography */ remBase: 16, - fontFamily: '"Source Sans Pro"', - fontSize: 16, + fontFamilySansSerif: '"Source Sans Pro"', + fontFamilySerif: '"Manuale"', fontWeightLight: 300, fontWeightRegular: 400, fontWeightMedium: 600, From ea02e47241eaa1f3d0af3def4f5fe559eae09707 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 15:57:07 +0200 Subject: [PATCH 05/18] Add PostMessage Service --- .../framework/lib/bootstrap/TalkContext.tsx | 4 ++ .../framework/lib/bootstrap/createContext.tsx | 2 + .../client/framework/lib/postMessage.spec.ts | 69 +++++++++++++++++++ src/core/client/framework/lib/postMessage.ts | 66 ++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 src/core/client/framework/lib/postMessage.spec.ts create mode 100644 src/core/client/framework/lib/postMessage.ts diff --git a/src/core/client/framework/lib/bootstrap/TalkContext.tsx b/src/core/client/framework/lib/bootstrap/TalkContext.tsx index 75ddc974c..f1d62c81c 100644 --- a/src/core/client/framework/lib/bootstrap/TalkContext.tsx +++ b/src/core/client/framework/lib/bootstrap/TalkContext.tsx @@ -6,6 +6,7 @@ import { MediaQueryMatchers } from "react-responsive"; import { Formatter } from "react-timeago"; import { Environment } from "relay-runtime"; +import { PostMessageService } from "talk-framework/lib/postMessage"; import { UIContext } from "talk-ui/components"; import { ClickFarAwayRegister } from "talk-ui/components/ClickOutside"; @@ -22,6 +23,9 @@ export interface TalkContext { /** media query values for testing purposes */ mediaQueryValues?: MediaQueryMatchers; + /** postMessage service */ + postMessage: PostMessageService; + /** * A way to listen for clicks that are e.g. outside of the * current frame for `ClickOutside` diff --git a/src/core/client/framework/lib/bootstrap/createContext.tsx b/src/core/client/framework/lib/bootstrap/createContext.tsx index 2e6bd2aff..91470277a 100644 --- a/src/core/client/framework/lib/bootstrap/createContext.tsx +++ b/src/core/client/framework/lib/bootstrap/createContext.tsx @@ -10,6 +10,7 @@ import { ClickFarAwayRegister } from "talk-ui/components/ClickOutside"; import { generateMessages, LocalesData, negotiateLanguages } from "../i18n"; import { fetchQuery } from "../network"; +import { PostMessageService } from "../postMessage"; import { TalkContext } from "./TalkContext"; interface CreateContextArguments { @@ -99,6 +100,7 @@ export default async function createContext({ pym, eventEmitter, registerClickFarAway, + postMessage: new PostMessageService(), }; // Run custom initializations. diff --git a/src/core/client/framework/lib/postMessage.spec.ts b/src/core/client/framework/lib/postMessage.spec.ts new file mode 100644 index 000000000..1c8a61a1f --- /dev/null +++ b/src/core/client/framework/lib/postMessage.spec.ts @@ -0,0 +1,69 @@ +import { PostMessageService } from "./postMessage"; + +it("post and subscribe to a message", done => { + const postMessage = new PostMessageService(); + const cancel = postMessage.on("test", value => { + expect(value).toBe("value"); + done(); + cancel(); + }); + postMessage.send("test", "value", window); +}); + +it("send to a different origin", done => { + const postMessage = new PostMessageService(); + const cancelA = postMessage.on("testA", value => { + throw new Error("Should not reach this"); + }); + const cancelB = postMessage.on("testB", value => { + done(); + cancelA(); + cancelB(); + }); + postMessage.send("testA", "value", window, "http://i-do-not-exist.de"); + postMessage.send("testB", "value", window); +}); + +it("should cancel", done => { + const postMessage = new PostMessageService(); + const cancelA = postMessage.on("testA", value => { + throw new Error("Should not reach this"); + }); + const cancelB = postMessage.on("testB", value => { + done(); + cancelB(); + }); + cancelA(); + postMessage.send("testA", "value", window); + postMessage.send("testB", "value", window); +}); + +it("different scopes are isolated", done => { + const postMessageA = new PostMessageService("scopeA"); + const postMessageB = new PostMessageService("scopeB"); + const cancelA = postMessageA.on("testA", value => { + throw new Error("Should not reach this"); + }); + const cancelB = postMessageA.on("testB", value => { + done(); + cancelA(); + cancelB(); + }); + postMessageB.send("testA", "value", window); + postMessageA.send("testB", "value", window); +}); + +it("different message names are isolated", done => { + const postMessage = new PostMessageService(); + const cancelA = postMessage.on("testA", value => { + expect(value).toBe("valueA"); + }); + const cancelB = postMessage.on("testB", value => { + expect(value).toBe("valueB"); + done(); + cancelA(); + cancelB(); + }); + postMessage.send("testA", "valueA", window); + postMessage.send("testB", "valueB", window); +}); diff --git a/src/core/client/framework/lib/postMessage.ts b/src/core/client/framework/lib/postMessage.ts new file mode 100644 index 000000000..70523cd5a --- /dev/null +++ b/src/core/client/framework/lib/postMessage.ts @@ -0,0 +1,66 @@ +type PostMessageHandler = (value: any, name: string) => void; + +/** + * Wrapper around the HTML postMessage API. + */ +export class PostMessageService { + private origin: string; + private scope: string; + + constructor( + scope = "talk", + origin: string = `${location.protocol}//${location.host}` + ) { + this.origin = origin; + this.scope = scope; + } + + /** + * Send a message over the postMessage API + * @param name string name of the message + * @param value string value of the message + * @param target Window target window, e.g. window.opener + * @param targetOrigin string origin of target + */ + public send(name: string, value: any, target: Window, targetOrigin?: string) { + if (!target) { + return; + } + + // Serialize the message to be sent via postMessage. + const msg = { name, value, scope: this.scope }; + + // Send the message. + target.postMessage(msg, targetOrigin || this.origin); + } + + /** + * Subscribe to messages + * @param name string Name of the message + * @param handler PostMessageHandler + */ + public on(name: string, handler: PostMessageHandler) { + const listener = (event: MessageEvent) => { + if (!event.origin) { + if (process.env.NODE_ENV !== "test") { + // tslint:disable-next-line:no-console + console.warn("empty origin received in postMessage", name); + } + } else if (event.origin !== this.origin) { + return; + } + if (event.data.scope !== this.scope) { + return; + } + if (event.data.name !== name) { + return; + } + handler(event.data.value, event.data.name); + }; + // Attach the listener to the target. + window.addEventListener("message", listener); + return () => { + window.removeEventListener("message", listener); + }; + } +} From 9510fbed57bc0de5210fa89b8c4d2ae5575016f8 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 16:05:50 +0200 Subject: [PATCH 06/18] Add complex value test --- src/core/client/framework/lib/postMessage.spec.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/client/framework/lib/postMessage.spec.ts b/src/core/client/framework/lib/postMessage.spec.ts index 1c8a61a1f..c5cc5a82a 100644 --- a/src/core/client/framework/lib/postMessage.spec.ts +++ b/src/core/client/framework/lib/postMessage.spec.ts @@ -10,6 +10,17 @@ it("post and subscribe to a message", done => { postMessage.send("test", "value", window); }); +it("should support complex value", done => { + const complex = { foo: "bar" }; + const postMessage = new PostMessageService(); + const cancel = postMessage.on("test", value => { + expect(value).toBe(complex); + done(); + cancel(); + }); + postMessage.send("test", complex, window); +}); + it("send to a different origin", done => { const postMessage = new PostMessageService(); const cancelA = postMessage.on("testA", value => { From 37f733dfa0c02ff891808ed1fe122d09c07062c4 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 16:12:08 +0200 Subject: [PATCH 07/18] Add post message listeners --- src/core/client/stream/index.tsx | 14 +++++++-- src/core/client/stream/listeners/index.ts | 5 ++++ .../listeners/onPostMessageAuthError.ts | 11 +++++++ .../onPostMessageSetAuthToken.spec.ts | 30 +++++++++++++++++++ .../listeners/onPostMessageSetAuthToken.ts | 16 ++++++++++ .../onPymSetCommentID.spec.ts} | 6 ++-- .../onPymSetCommentID.ts} | 2 +- src/core/client/stream/pym/index.ts | 1 - 8 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/core/client/stream/listeners/index.ts create mode 100644 src/core/client/stream/listeners/onPostMessageAuthError.ts create mode 100644 src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts create mode 100644 src/core/client/stream/listeners/onPostMessageSetAuthToken.ts rename src/core/client/stream/{pym/withSetCommentID.spec.ts => listeners/onPymSetCommentID.spec.ts} (88%) rename src/core/client/stream/{pym/withSetCommentID.ts => listeners/onPymSetCommentID.ts} (91%) delete mode 100644 src/core/client/stream/pym/index.ts diff --git a/src/core/client/stream/index.tsx b/src/core/client/stream/index.tsx index 4ac024d6d..dcd2af7e1 100644 --- a/src/core/client/stream/index.tsx +++ b/src/core/client/stream/index.tsx @@ -10,16 +10,24 @@ import { } from "talk-framework/lib/bootstrap"; import AppContainer from "./containers/AppContainer"; +import { + onPostMessageAuthError, + onPostMessageSetAuthToken, + onPymSetCommentID, +} from "./listeners"; import { initLocalState } from "./local"; import localesData from "./locales"; -import { withSetCommentID } from "./pym"; -const pymFeatures = [withSetCommentID]; +const listeners = [ + onPymSetCommentID, + onPostMessageSetAuthToken, + onPostMessageAuthError, +]; // This is called when the context is first initialized. async function init(context: TalkContext) { await initLocalState(context.relayEnvironment); - pymFeatures.forEach(f => f(context)); + listeners.forEach(f => f(context)); } async function main() { diff --git a/src/core/client/stream/listeners/index.ts b/src/core/client/stream/listeners/index.ts new file mode 100644 index 000000000..7901544e0 --- /dev/null +++ b/src/core/client/stream/listeners/index.ts @@ -0,0 +1,5 @@ +export { default as onPymSetCommentID } from "./onPymSetCommentID"; +export { + default as onPostMessageSetAuthToken, +} from "./onPostMessageSetAuthToken"; +export { default as onPostMessageAuthError } from "./onPostMessageAuthError"; diff --git a/src/core/client/stream/listeners/onPostMessageAuthError.ts b/src/core/client/stream/listeners/onPostMessageAuthError.ts new file mode 100644 index 000000000..668a4ba1f --- /dev/null +++ b/src/core/client/stream/listeners/onPostMessageAuthError.ts @@ -0,0 +1,11 @@ +import { TalkContext } from "talk-framework/lib/bootstrap"; + +export default function onPostMessageSetAuthToken({ + postMessage, +}: TalkContext) { + // Auth popup will use this to send back errors during login. + postMessage!.on("authError", error => { + // tslint:disable-next-line:no-console + console.error(error); + }); +} diff --git a/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts b/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts new file mode 100644 index 000000000..37ed034d6 --- /dev/null +++ b/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts @@ -0,0 +1,30 @@ +import { Environment, RecordSource } from "relay-runtime"; + +import { LOCAL_ID } from "talk-framework/lib/relay"; +import { createRelayEnvironment } from "talk-framework/testHelpers"; + +import onPostMessageSetAuthToken from "./onPostMessageSetAuthToken"; + +let relayEnvironment: Environment; +const source: RecordSource = new RecordSource(); + +beforeAll(() => { + relayEnvironment = createRelayEnvironment({ + source, + }); +}); + +it("Sets auth token", () => { + const token = "auth-token"; + const context = { + postMessage: { + on: (name: string, cb: (token: string) => void) => { + expect(name).toBe("setAuthToken"); + cb(token); + }, + }, + relayEnvironment, + }; + onPostMessageSetAuthToken(context as any); + expect(source.get(LOCAL_ID)!.authToken).toEqual(token); +}); diff --git a/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts b/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts new file mode 100644 index 000000000..9321e0395 --- /dev/null +++ b/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts @@ -0,0 +1,16 @@ +import { commitLocalUpdate } from "react-relay"; + +import { TalkContext } from "talk-framework/lib/bootstrap"; +import { LOCAL_ID } from "talk-framework/lib/relay"; + +export default function onPostMessageSetAuthToken({ + relayEnvironment, + postMessage, +}: TalkContext) { + // Auth popup will use this to handle a successful login. + postMessage!.on("setAuthToken", token => { + commitLocalUpdate(relayEnvironment, s => { + s.get(LOCAL_ID)!.setValue(token, "authToken"); + }); + }); +} diff --git a/src/core/client/stream/pym/withSetCommentID.spec.ts b/src/core/client/stream/listeners/onPymSetCommentID.spec.ts similarity index 88% rename from src/core/client/stream/pym/withSetCommentID.spec.ts rename to src/core/client/stream/listeners/onPymSetCommentID.spec.ts index 3403a0092..6b5e67ea2 100644 --- a/src/core/client/stream/pym/withSetCommentID.spec.ts +++ b/src/core/client/stream/listeners/onPymSetCommentID.spec.ts @@ -3,7 +3,7 @@ import { Environment, RecordSource } from "relay-runtime"; import { LOCAL_ID } from "talk-framework/lib/relay"; import { createRelayEnvironment } from "talk-framework/testHelpers"; -import withSetCommentID from "./withSetCommentID"; +import onPymSetCommentID from "./onPymSetCommentID"; let relayEnvironment: Environment; const source: RecordSource = new RecordSource(); @@ -25,7 +25,7 @@ it("Sets comment id", () => { }, relayEnvironment, }; - withSetCommentID(context as any); + onPymSetCommentID(context as any); expect(source.get(LOCAL_ID)!.commentID).toEqual(id); }); @@ -40,6 +40,6 @@ it("Sets comment id to null when empty", () => { }, relayEnvironment, }; - withSetCommentID(context as any); + onPymSetCommentID(context as any); expect(source.get(LOCAL_ID)!.commentID).toEqual(null); }); diff --git a/src/core/client/stream/pym/withSetCommentID.ts b/src/core/client/stream/listeners/onPymSetCommentID.ts similarity index 91% rename from src/core/client/stream/pym/withSetCommentID.ts rename to src/core/client/stream/listeners/onPymSetCommentID.ts index 903921d9b..4b5547173 100644 --- a/src/core/client/stream/pym/withSetCommentID.ts +++ b/src/core/client/stream/listeners/onPymSetCommentID.ts @@ -3,7 +3,7 @@ import { commitLocalUpdate } from "react-relay"; import { TalkContext } from "talk-framework/lib/bootstrap"; import { LOCAL_ID } from "talk-framework/lib/relay"; -export default function withSetCommentID({ +export default function onPymSetCommentID({ relayEnvironment, pym, }: TalkContext) { diff --git a/src/core/client/stream/pym/index.ts b/src/core/client/stream/pym/index.ts deleted file mode 100644 index 34ba3fc8f..000000000 --- a/src/core/client/stream/pym/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as withSetCommentID } from "./withSetCommentID"; From e1c60bc18dc7457df6ec2b44250adea01ca14804 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 16:18:29 +0200 Subject: [PATCH 08/18] Use setAuthToken mutation --- .../stream/listeners/onPostMessageSetAuthToken.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts b/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts index 9321e0395..77be702ad 100644 --- a/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts +++ b/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts @@ -1,16 +1,13 @@ -import { commitLocalUpdate } from "react-relay"; - import { TalkContext } from "talk-framework/lib/bootstrap"; -import { LOCAL_ID } from "talk-framework/lib/relay"; + +import { commit as setAuthToken } from "talk-framework/mutations/SetAuthTokenMutation"; export default function onPostMessageSetAuthToken({ relayEnvironment, postMessage, }: TalkContext) { // Auth popup will use this to handle a successful login. - postMessage!.on("setAuthToken", token => { - commitLocalUpdate(relayEnvironment, s => { - s.get(LOCAL_ID)!.setValue(token, "authToken"); - }); + postMessage!.on("setAuthToken", (authToken: string) => { + setAuthToken(relayEnvironment, { authToken }); }); } From bb39b4e8fad83872b2e5067588325bfc0bdfd554 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 17:19:01 +0200 Subject: [PATCH 09/18] Add rest client --- .../framework/lib/bootstrap/TalkContext.tsx | 4 ++ .../framework/lib/bootstrap/createContext.tsx | 2 + src/core/client/framework/lib/rest.ts | 57 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/core/client/framework/lib/rest.ts diff --git a/src/core/client/framework/lib/bootstrap/TalkContext.tsx b/src/core/client/framework/lib/bootstrap/TalkContext.tsx index 75ddc974c..e25746c52 100644 --- a/src/core/client/framework/lib/bootstrap/TalkContext.tsx +++ b/src/core/client/framework/lib/bootstrap/TalkContext.tsx @@ -6,6 +6,7 @@ import { MediaQueryMatchers } from "react-responsive"; import { Formatter } from "react-timeago"; import { Environment } from "relay-runtime"; +import { RestClient } from "talk-framework/lib/rest"; import { UIContext } from "talk-ui/components"; import { ClickFarAwayRegister } from "talk-ui/components/ClickOutside"; @@ -22,6 +23,9 @@ export interface TalkContext { /** media query values for testing purposes */ mediaQueryValues?: MediaQueryMatchers; + /** Rest client */ + rest: RestClient; + /** * A way to listen for clicks that are e.g. outside of the * current frame for `ClickOutside` diff --git a/src/core/client/framework/lib/bootstrap/createContext.tsx b/src/core/client/framework/lib/bootstrap/createContext.tsx index 2e6bd2aff..75c2dcc01 100644 --- a/src/core/client/framework/lib/bootstrap/createContext.tsx +++ b/src/core/client/framework/lib/bootstrap/createContext.tsx @@ -6,6 +6,7 @@ import React from "react"; import { Formatter } from "react-timeago"; import { Environment, Network, RecordSource, Store } from "relay-runtime"; +import { RestClient } from "talk-framework/lib/rest"; import { ClickFarAwayRegister } from "talk-ui/components/ClickOutside"; import { generateMessages, LocalesData, negotiateLanguages } from "../i18n"; @@ -99,6 +100,7 @@ export default async function createContext({ pym, eventEmitter, registerClickFarAway, + rest: new RestClient("/api"), }; // Run custom initializations. diff --git a/src/core/client/framework/lib/rest.ts b/src/core/client/framework/lib/rest.ts new file mode 100644 index 000000000..b8ccdccab --- /dev/null +++ b/src/core/client/framework/lib/rest.ts @@ -0,0 +1,57 @@ +import merge from "lodash/merge"; +import { Overwrite } from "talk-framework/types"; + +const buildOptions = (inputOptions: RequestInit = {}) => { + const defaultOptions: RequestInit = { + method: "GET", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + credentials: "same-origin", + }; + const options = merge({}, defaultOptions, inputOptions); + if (options.method!.toLowerCase() !== "get") { + options.body = JSON.stringify(options.body); + } + return options; +}; + +const handleResp = (res: Response) => { + if (res.status > 399) { + return res.json().then((err: any) => { + // TODO: sync error handling with server. + const message = err.message || res.status; + const error = new Error(message); + throw error; + }); + } else if (res.status === 204) { + return res.text(); + } else { + return res.json(); + } +}; + +type PartialRequestInit = Overwrite, { body: any }>; + +export class RestClient { + public readonly uri: string; + private tokenGetter?: () => string; + + constructor(uri: string, tokenGetter?: () => string) { + this.uri = uri; + this.tokenGetter = tokenGetter; + } + + public fetch(path: string, options: PartialRequestInit): Promise { + let opts = options; + if (this.tokenGetter) { + opts = merge({}, options, { + headers: { + Authorization: `Bearer ${this.tokenGetter()}`, + }, + }); + } + return fetch(`${this.uri}${path}`, buildOptions(opts)).then(handleResp); + } +} From 505bb48f8bfd79fafc03a3b01780cd578da08cf2 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 17:19:07 +0200 Subject: [PATCH 10/18] Add rest endpoints --- src/core/client/framework/rest/index.ts | 2 ++ src/core/client/framework/rest/signIn.ts | 13 +++++++++++++ src/core/client/framework/rest/signUp.ts | 14 ++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/core/client/framework/rest/index.ts create mode 100644 src/core/client/framework/rest/signIn.ts create mode 100644 src/core/client/framework/rest/signUp.ts diff --git a/src/core/client/framework/rest/index.ts b/src/core/client/framework/rest/index.ts new file mode 100644 index 000000000..0b3032bb5 --- /dev/null +++ b/src/core/client/framework/rest/index.ts @@ -0,0 +1,2 @@ +export { default as signIn, SignInInput } from "./signIn"; +export { default as signUp, SignUpInput } from "./signUp"; diff --git a/src/core/client/framework/rest/signIn.ts b/src/core/client/framework/rest/signIn.ts new file mode 100644 index 000000000..4b537b01c --- /dev/null +++ b/src/core/client/framework/rest/signIn.ts @@ -0,0 +1,13 @@ +import { RestClient } from "../lib/rest"; + +export interface SignInInput { + username: string; + password: string; +} + +export default function signIn(rest: RestClient, input: SignInInput) { + return rest.fetch("/tenant/auth/local", { + method: "POST", + body: input, + }); +} diff --git a/src/core/client/framework/rest/signUp.ts b/src/core/client/framework/rest/signUp.ts new file mode 100644 index 000000000..eece6271b --- /dev/null +++ b/src/core/client/framework/rest/signUp.ts @@ -0,0 +1,14 @@ +import { RestClient } from "../lib/rest"; + +export interface SignUpInput { + username: string; + password: string; + email: string; +} + +export default function signUp(rest: RestClient, input: SignUpInput) { + return rest.fetch("/tenant/auth/local/signup", { + method: "POST", + body: input, + }); +} From d2106b3de51d46fc6a8111cf1ed6bd817c1a6d97 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 10 Aug 2018 16:17:39 +0000 Subject: [PATCH 11/18] [next] Templates (#1760) * feat: initial support for synced tenants * fix: cleanup * fix: logger now respects logging level * fix: cache now ignores updates issued from itself * feat: print subscriber count * feat: initial nunjucks support * fix: support tenant cache for oidc strategy * fix: replace some constructor initializers with property initializers * fix: audit * [next] Comments and Moderation (#1759) * feat: initial moderation + validation for new comments * fix: added Promiseable type * feat: initial actions impl * feat: more moderation phases * fix: handle settings inheritence * fix: moved settings into new file * fix: defaults and documentation * fix: replace merge with object spread * feat: added integration with akismet * fix: fixed compile * fix: import ordering * fix: merge issue causing build to fail * feat: added gulp, static templates * fix: added compile step back * Fix extract css + remove cross-env --- DESIGN.md | 36 + config/watcher.ts | 2 +- gulpfile.js | 72 + package-lock.json | 2011 ++++++++++++++--- package.json | 23 +- scripts/generateSchemaTypes.js | 26 +- src/core/build/createWebpackConfig.ts | 68 +- src/core/server/app/handlers/auth/local.ts | 1 - src/core/server/app/handlers/embed/stream.ts | 5 + src/core/server/app/index.ts | 40 +- src/core/server/app/middleware/notFound.ts | 1 + src/core/server/app/middleware/serveStatic.ts | 6 +- src/core/server/app/middleware/tenant.ts | 3 + src/core/server/app/router.ts | 4 + 14 files changed, 1955 insertions(+), 343 deletions(-) create mode 100644 gulpfile.js create mode 100644 src/core/server/app/handlers/embed/stream.ts diff --git a/DESIGN.md b/DESIGN.md index 1481e7f4b..3929c98a1 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -30,3 +30,39 @@ 2. Tenant RedisPubSub Publisher 3. Management RedisPubSub Subscriber 4. Management RedisPubSub Publisher + +## Scripts + +### Embed + +Embed Script - Renders the iFrame <-- does not have a html page in production (should be on server?) + +/dist/static/assets/embed.js /static/embed.js + +### Stream + +Stream - Renders the comment stream <-- data + +/dist/static/assets/stream..css /static/assets/stream..css +/dist/static/assets/stream..js /static/assets/stream..js +/dist/static/stream.html /embed/stream + +### Admin + +Admin - Renders the Admin page <-- data + +/dist/static/assets/admin..css /static/assets/admin..css +/dist/static/assets/admin..js /static/assets/admin..js +/dist/static/admin.html /admin + +## Development Routes + + +localhost:3000 + / -> /admin + /dev <-- server side html for dev/iframe integration + +localhost:8080 + / -> localhost:3000/dev + /embed/stream <-- stream html (now is at /) + /admin <-- stream html (now is not there) \ No newline at end of file diff --git a/config/watcher.ts b/config/watcher.ts index a05f22b0c..b0def88eb 100644 --- a/config/watcher.ts +++ b/config/watcher.ts @@ -10,7 +10,7 @@ const config: Config = { watchers: { compileSchema: { paths: ["core/server/**/*.graphql"], - executor: new CommandExecutor("npm run compile:schema", { + executor: new CommandExecutor("npx gulp server:schema", { runOnInit: true, }), }, diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 000000000..d53fcf0f5 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,72 @@ +const path = require("path"); +const json = require("comment-json"); +const fs = require("fs"); +const del = require("del"); +const gulp = require("gulp"); +const ts = require("gulp-typescript"); +const sourcemaps = require("gulp-sourcemaps"); +const babel = require("gulp-babel"); +const generateTypescriptTypes = require("./scripts/generateSchemaTypes"); +const _ = require("lodash"); + +// Parse the tsconfig.json file (which contains comments). +const tsconfig = json.parse(fs.readFileSync("./src/tsconfig.json").toString()); + +// Create the typescript project. +const tsProject = ts.createProject("./src/tsconfig.json"); + +const resolveDistFolder = (...paths) => "./" + path.join("dist", ...paths); + +gulp.task("clean", () => del([resolveDistFolder()])); + +gulp.task("server:schema", () => generateTypescriptTypes()); + +gulp.task("server:scripts", () => + gulp + .src([ + "./src/**/*.ts", + "./src/**/.*.ts", + // Exclude client files from this, that's for webpack. + "!./src/core/client/**/*.ts", + "!./src/core/client/**/.*.ts", + ]) + .pipe(sourcemaps.init()) + .pipe(tsProject()) + .pipe( + babel({ + plugins: [ + [ + "module-resolver", + { + root: [resolveDistFolder()], + alias: _.reduce( + tsconfig.compilerOptions.paths, + (alias, [pathGlob], prefixBlob) => ({ + ...alias, + [prefixBlob.replace(/\/\*/g, "")]: pathGlob + .replace(/\/\*/g, "") + .replace(/^\./g, resolveDistFolder()), + }), + {} + ), + }, + ], + ], + }) + ) + .pipe(sourcemaps.write(".")) + .pipe(gulp.dest(resolveDistFolder())) +); + +gulp.task("server:static", () => + gulp + .src(["./src/core/server/**/*", "!./src/core/server/**/*.ts"]) + .pipe(gulp.dest(resolveDistFolder() + "/core/server")) +); + +gulp.task( + "server", + gulp.series("server:schema", gulp.parallel("server:scripts", "server:static")) +); + +gulp.task("default", gulp.series("clean", "server")); diff --git a/package-lock.json b/package-lock.json index f89274a76..ee06575e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1410,6 +1410,37 @@ "integrity": "sha512-1bGqG9IYJETOOqQEjWinGx1deLlAW/Fcew4GyrzZx0dJIgAjivZTmwzjrhB+Vhj7TgjMr0aTyj5byHmZezisZQ==", "dev": true }, + "@gulp-sourcemaps/identity-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } + }, "@mdx-js/loader": { "version": "0.13.1-1", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-0.13.1-1.tgz", @@ -1631,6 +1662,16 @@ "@types/node": "*" } }, + "@types/consolidate": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@types/consolidate/-/consolidate-0.0.34.tgz", + "integrity": "sha512-qpr8xIkywhjyaQUwTjdb8QuhRD1EIf55ExcyK1KdUtxysb/47Em+cJze7OXLkGmmuXa+PrfCNM25bJ/h472r4Q==", + "dev": true, + "requires": { + "@types/bluebird": "*", + "@types/node": "*" + } + }, "@types/convict": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@types/convict/-/convict-4.2.0.tgz", @@ -1725,15 +1766,6 @@ "@types/express": "*" } }, - "@types/extract-text-webpack-plugin": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.3.tgz", - "integrity": "sha512-KvRd5e5k+BVwWBlCm4uZFcV+M2mikKhORahruKxPkriFIDhG6b0fZ8PIYyiok+pk6W5bqFCsQmRk5D86pTmNpA==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, "@types/fs-extra": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", @@ -1859,6 +1891,15 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" }, + "@types/mini-css-extract-plugin": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.2.0.tgz", + "integrity": "sha512-oHec+Vasp+K3C1Hb9HpwbA9Iw8ywqDgo9edWQJdBqxu05JH2AQsR56Zo5THpYbu1ieh/xJCvMRIHRdvrUBDmcA==", + "dev": true, + "requires": { + "@types/webpack": "*" + } + }, "@types/mongodb": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.1.1.tgz", @@ -1875,6 +1916,12 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==" }, + "@types/nunjucks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.0.0.tgz", + "integrity": "sha512-Msxi0MEZbsQlqx9oscKWwe6N2d4QerzXgGEzgMop4+RNFlO0PvhGpwJHXdTLUWz6GaZEOrNUsBBDNNYwKTgMJw==", + "dev": true + }, "@types/oauth": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.0.tgz", @@ -2509,6 +2556,11 @@ } } }, + "a-sync-waterfall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.0.tgz", + "integrity": "sha1-OOgxnXk3niRiiEW1O5ZyKyng5Hw=" + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -2630,12 +2682,30 @@ "string-width": "^2.0.0" } }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, "ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", @@ -2645,8 +2715,7 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", @@ -2654,6 +2723,12 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -2664,7 +2739,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" @@ -2741,6 +2815,15 @@ "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", "dev": true }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, "append-transform": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", @@ -2762,6 +2845,12 @@ "integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==", "dev": true }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2773,19 +2862,40 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, "array-equal": { @@ -2821,6 +2931,41 @@ "es-abstract": "^1.7.0" } }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -2833,6 +2978,31 @@ "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", "dev": true }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -2851,8 +3021,7 @@ "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "arrify": { "version": "1.0.1", @@ -2880,8 +3049,7 @@ "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, "asn1": { "version": "0.2.3", @@ -2933,8 +3101,7 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, "ast-types": { "version": "0.11.5", @@ -2957,17 +3124,45 @@ "lodash": "^4.17.10" } }, + "async-done": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", + "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^1.0.7", + "stream-exhaust": "^1.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + } + } + }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2976,8 +3171,7 @@ "atob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", - "dev": true + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" }, "autoprefixer": { "version": "8.6.5", @@ -3366,6 +3560,35 @@ "cosmiconfig": "3.1.0" } }, + "babel-plugin-module-resolver": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.1.1.tgz", + "integrity": "sha512-1Q77Al4ydp6nYApJ7sQ2fmgz30WuQgJZegIYuyOdbdpxenB/bSezQ3hDPsumIXGlUS4vUIv+EwFjzzXZNWtARw==", + "dev": true, + "requires": { + "find-babel-config": "^1.1.0", + "glob": "^7.1.2", + "pkg-up": "^2.0.0", + "reselect": "^3.0.1", + "resolve": "^1.4.0" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "babel-plugin-react-docgen": { "version": "2.0.0-rc.1", "resolved": "https://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-2.0.0-rc.1.tgz", @@ -4836,6 +5059,23 @@ "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==", "dev": true }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -4856,7 +5096,6 @@ "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -4871,7 +5110,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -4880,7 +5118,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -4889,7 +5126,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -4898,7 +5134,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -4942,8 +5177,7 @@ "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" }, "bluebird": { "version": "3.5.1", @@ -5066,7 +5300,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -5084,7 +5317,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -5234,6 +5466,12 @@ "isarray": "^1.0.0" } }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -5334,7 +5572,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -5599,7 +5836,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, "requires": { "anymatch": "^2.0.0", "async-each": "^1.0.0", @@ -5675,7 +5911,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -5687,7 +5922,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -5861,6 +6095,29 @@ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, "cluster-key-slot": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.12.tgz", @@ -5883,8 +6140,7 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "collapse-white-space": { "version": "1.0.4", @@ -5892,11 +6148,32 @@ "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", "dev": true }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -5937,6 +6214,12 @@ "color-name": "^1.0.0" } }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "colormin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", @@ -6006,6 +6289,15 @@ "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", "dev": true }, + "comment-json": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-1.1.3.tgz", + "integrity": "sha1-aYbDMw/uDEyeAMI5jNYa+l2PI54=", + "dev": true, + "requires": { + "json-parser": "^1.0.0" + } + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -6113,6 +6405,14 @@ "date-now": "^0.1.4" } }, + "consolidate": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.0.tgz", + "integrity": "sha1-sDrNVmolZcqW6Z9E/RQXSGtN+I0=", + "requires": { + "bluebird": "^3.1.1" + } + }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -6215,8 +6515,17 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } }, "copy-to-clipboard": { "version": "3.0.8", @@ -6561,16 +6870,6 @@ "gud": "^1.0.0" } }, - "cross-env": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", - "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.5", - "is-windows": "^1.0.0" - } - }, "cross-fetch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.0.0.tgz", @@ -6625,6 +6924,29 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, + "css": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", + "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "source-map": "^0.1.38", + "source-map-resolve": "^0.5.1", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -7063,11 +7385,32 @@ "ms": "2.0.0" } }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decamelize-keys": { "version": "1.1.0", @@ -7090,8 +7433,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "deep-equal": { "version": "1.0.1", @@ -7117,6 +7459,23 @@ "integrity": "sha512-urQxA1smbLZ2cBbXbaYObM1dJ82aJ2H57A1C/Kklfh/ZN1bgH4G/n5KWhdNfOK11W98gqZfyYj7W4frJJRwA2w==", "dev": true }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "default-require-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", @@ -7126,6 +7485,12 @@ "strip-bom": "^3.0.0" } }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, "define-properties": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", @@ -7140,7 +7505,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -7150,7 +7514,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -7159,7 +7522,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -7168,7 +7530,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -7291,6 +7652,12 @@ "repeat-string": "^1.5.4" } }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -8324,6 +8691,16 @@ "stream-shift": "^1.0.0" } }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -8613,6 +8990,18 @@ "es5-ext": "~0.10.14" } }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -8709,6 +9098,16 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "event-stream": { "version": "3.3.4", "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", @@ -8807,7 +9206,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -8822,7 +9220,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -8831,7 +9228,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -8977,7 +9373,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -8987,7 +9382,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -9009,7 +9403,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -9025,7 +9418,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -9034,7 +9426,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -9043,7 +9434,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -9052,7 +9442,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -9061,7 +9450,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -9070,18 +9458,6 @@ } } }, - "extract-text-webpack-plugin": { - "version": "4.0.0-beta.0", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz", - "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==", - "dev": true, - "requires": { - "async": "^2.4.1", - "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5", - "webpack-sources": "^1.1.0" - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -9093,6 +9469,17 @@ "integrity": "sha512-oNvBekbhsm/0PNSOWca5raHNAi6dG960Bx6LJgxDPNF59WpuspgQ17bN5MKwOr7JcFdQYc7StW3VZ28DBZLavQ==", "dev": true }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + } + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -9259,7 +9646,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -9271,7 +9657,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -9298,6 +9683,24 @@ "unpipe": "~1.0.0" } }, + "find-babel-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.1.0.tgz", + "integrity": "sha1-rMAQQ6Z0n+w0Qpvmtk9ULrtdY1U=", + "dev": true, + "requires": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + } + } + }, "find-cache-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", @@ -9348,6 +9751,48 @@ "locate-path": "^2.0.0" } }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, "flat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", @@ -9447,8 +9892,7 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "0.1.5", @@ -9500,7 +9944,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, "requires": { "map-cache": "^0.2.2" } @@ -9562,6 +10005,16 @@ "universalify": "^0.1.0" } }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -9584,7 +10037,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, "optional": true, "requires": { "nan": "^2.9.2", @@ -9595,27 +10047,23 @@ "version": "1.1.1", "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", "resolved": "", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { "version": "1.2.0", "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", "resolved": "", "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "dev": true, "optional": true, "requires": { "delegates": "^1.0.0", @@ -9625,14 +10073,12 @@ "balanced-match": { "version": "1.0.0", "resolved": "", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "brace-expansion": { "version": "1.1.11", "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -9642,39 +10088,33 @@ "version": "1.0.1", "resolved": "", "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", "resolved": "", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "concat-map": { "version": "0.0.1", "resolved": "", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-control-strings": { "version": "1.1.0", "resolved": "", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, "optional": true }, "debug": { "version": "2.6.9", "resolved": "", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "optional": true, "requires": { "ms": "2.0.0" @@ -9684,28 +10124,24 @@ "version": "0.5.1", "resolved": "", "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", - "dev": true, "optional": true }, "delegates": { "version": "1.0.0", "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", - "dev": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -9715,14 +10151,12 @@ "version": "1.0.0", "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true, "optional": true }, "gauge": { "version": "2.7.4", "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, "optional": true, "requires": { "aproba": "^1.0.3", @@ -9739,7 +10173,6 @@ "version": "7.1.2", "resolved": "", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "optional": true, "requires": { "fs.realpath": "^1.0.0", @@ -9754,14 +10187,12 @@ "version": "2.0.1", "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.21", "resolved": "", "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", - "dev": true, "optional": true, "requires": { "safer-buffer": "^2.1.0" @@ -9771,7 +10202,6 @@ "version": "3.0.1", "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "dev": true, "optional": true, "requires": { "minimatch": "^3.0.4" @@ -9781,7 +10211,6 @@ "version": "1.0.6", "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "optional": true, "requires": { "once": "^1.3.0", @@ -9791,21 +10220,18 @@ "inherits": { "version": "2.0.3", "resolved": "", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -9814,14 +10240,12 @@ "version": "1.0.0", "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -9829,14 +10253,12 @@ "minimist": { "version": "0.0.8", "resolved": "", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { "version": "2.2.4", "resolved": "", "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", - "dev": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -9846,7 +10268,6 @@ "version": "1.1.0", "resolved": "", "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", - "dev": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -9856,7 +10277,6 @@ "version": "0.5.1", "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -9865,14 +10285,12 @@ "version": "2.0.0", "resolved": "", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, "optional": true }, "needle": { "version": "2.2.0", "resolved": "", "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", - "dev": true, "optional": true, "requires": { "debug": "^2.1.2", @@ -9884,7 +10302,6 @@ "version": "0.10.0", "resolved": "", "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", - "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -9903,7 +10320,6 @@ "version": "4.0.1", "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, "optional": true, "requires": { "abbrev": "1", @@ -9914,14 +10330,12 @@ "version": "1.0.3", "resolved": "", "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", - "dev": true, "optional": true }, "npm-packlist": { "version": "1.1.10", "resolved": "", "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", - "dev": true, "optional": true, "requires": { "ignore-walk": "^3.0.1", @@ -9932,7 +10346,6 @@ "version": "4.1.2", "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -9944,21 +10357,18 @@ "number-is-nan": { "version": "1.0.1", "resolved": "", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "object-assign": { "version": "4.1.1", "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, "optional": true }, "once": { "version": "1.4.0", "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -9967,21 +10377,18 @@ "version": "1.0.2", "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, "optional": true }, "osenv": { "version": "0.1.5", "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, "optional": true, "requires": { "os-homedir": "^1.0.0", @@ -9992,21 +10399,18 @@ "version": "1.0.1", "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true, "optional": true }, "rc": { "version": "1.2.7", "resolved": "", "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", - "dev": true, "optional": true, "requires": { "deep-extend": "^0.5.1", @@ -10019,7 +10423,6 @@ "version": "1.2.0", "resolved": "", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, "optional": true } } @@ -10028,7 +10431,6 @@ "version": "2.3.6", "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "optional": true, "requires": { "core-util-is": "~1.0.0", @@ -10044,7 +10446,6 @@ "version": "2.6.2", "resolved": "", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "optional": true, "requires": { "glob": "^7.0.5" @@ -10053,49 +10454,42 @@ "safe-buffer": { "version": "5.1.1", "resolved": "", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safer-buffer": { "version": "2.1.2", "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "optional": true }, "sax": { "version": "1.2.4", "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, "optional": true }, "semver": { "version": "5.5.0", "resolved": "", "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, "optional": true }, "string-width": { "version": "1.0.2", "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -10106,7 +10500,6 @@ "version": "1.1.1", "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "optional": true, "requires": { "safe-buffer": "~5.1.0" @@ -10116,7 +10509,6 @@ "version": "3.0.1", "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -10125,14 +10517,12 @@ "version": "2.0.1", "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, "optional": true }, "tar": { "version": "4.4.1", "resolved": "", "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", - "dev": true, "optional": true, "requires": { "chownr": "^1.0.1", @@ -10148,14 +10538,12 @@ "version": "1.0.2", "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, "optional": true }, "wide-align": { "version": "1.1.2", "resolved": "", "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "dev": true, "optional": true, "requires": { "string-width": "^1.0.2" @@ -10164,14 +10552,12 @@ "wrappy": { "version": "1.0.2", "resolved": "", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "yallist": { "version": "3.0.2", "resolved": "", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", - "dev": true + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" } } }, @@ -10225,8 +10611,7 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, "getpass": { "version": "0.1.7", @@ -10297,7 +10682,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -10307,19 +10691,64 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, "requires": { "is-extglob": "^2.1.0" } } } }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "glob-to-regexp": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, + "glob-watcher": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz", + "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==", + "dev": true, + "requires": { + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } + }, "glob2base": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", @@ -10414,6 +10843,15 @@ } } }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, "good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", @@ -10614,6 +11052,419 @@ "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==", "dev": true }, + "gulp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", + "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", + "dev": true, + "requires": { + "glob-watcher": "^5.0.0", + "gulp-cli": "^2.0.0", + "undertaker": "^1.0.0", + "vinyl-fs": "^3.0.0" + } + }, + "gulp-babel": { + "version": "8.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0-beta.2.tgz", + "integrity": "sha512-GTC2PxAXWkp6u1fP+C5+kn5biQ0dKGhkOSSXvKAf3ykF0+R3tevmLm/zSIkc1+S7U1JwH3XTvuMwRL6LD+sEiw==", + "dev": true, + "requires": { + "plugin-error": "^1.0.1", + "replace-ext": "^1.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "gulp-cli": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", + "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^2.5.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "v8flags": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", + "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "gulp-sourcemaps": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "gulp-typescript": { + "version": "5.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-5.0.0-alpha.3.tgz", + "integrity": "sha512-6iSBjqBXAUqRsLUh/9XtlOnSzpPMbLrr5rqGj4UPLtGpDwFHW/fVTuRgv6LAWiKesLIUDDM0ourxvcpu2trecQ==", + "dev": true, + "requires": { + "ansi-colors": "^2.0.2", + "plugin-error": "^1.0.1", + "source-map": "^0.7.3", + "through2": "^2.0.3", + "vinyl": "^2.1.0", + "vinyl-fs": "^3.0.3" + }, + "dependencies": { + "ansi-colors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", + "dev": true + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, "gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", @@ -10809,7 +11660,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -10820,7 +11670,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -10830,7 +11679,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11537,8 +12385,7 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ioredis": { "version": "3.2.2", @@ -11581,6 +12428,16 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, "is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", @@ -11591,7 +12448,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -11600,7 +12456,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11633,7 +12488,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, "requires": { "binary-extensions": "^1.0.0" } @@ -11647,8 +12501,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -11678,7 +12531,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -11687,7 +12539,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11710,7 +12561,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -11720,8 +12570,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -11755,14 +12604,12 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { "version": "1.0.2", @@ -11795,7 +12642,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -11822,6 +12668,12 @@ "integrity": "sha1-rDDc81tnH0snsX9ctXI1EmAhEy0=", "dev": true }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -11832,7 +12684,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -11841,7 +12692,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11864,7 +12714,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, "requires": { "is-number": "^4.0.0" }, @@ -11872,8 +12721,7 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" } } }, @@ -11920,7 +12768,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -11958,6 +12805,15 @@ "has": "^1.0.1" } }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -12023,12 +12879,27 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, "is-whitespace-character": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", @@ -12038,8 +12909,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "is-woff": { "version": "1.0.3", @@ -12087,8 +12957,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isomorphic-fetch": { "version": "2.2.1", @@ -14068,6 +14937,23 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parser": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/json-parser/-/json-parser-1.1.5.tgz", + "integrity": "sha1-5i7FJh0aal/CDoEqMgdAxtkAVnc=", + "dev": true, + "requires": { + "esprima": "^2.7.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + } + } + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -14079,6 +14965,15 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -14146,6 +15041,12 @@ "verror": "1.10.0" } }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, "just-extend": { "version": "1.1.27", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", @@ -14199,8 +15100,7 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" }, "klaw": { "version": "1.3.1", @@ -14381,6 +15281,16 @@ "colornames": "^1.1.1" } }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, "latest-version": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", @@ -14397,15 +15307,32 @@ "dev": true, "optional": true }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "^1.0.0" } }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, "leb": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/leb/-/leb-0.3.0.tgz", @@ -14434,6 +15361,22 @@ "type-check": "~0.3.2" } }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, "limiter": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.3.tgz", @@ -14617,8 +15560,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "lodash.deburr": { "version": "4.1.0", @@ -14926,6 +15868,15 @@ } } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "luxon": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.3.1.tgz", @@ -14946,6 +15897,15 @@ "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", "dev": true }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -14964,8 +15924,7 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, "map-obj": { "version": "2.0.0", @@ -14983,7 +15942,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, "requires": { "object-visit": "^1.0.0" } @@ -15000,6 +15958,18 @@ "integrity": "sha1-iQwsGzv+g/sA5BKbjkz+ZFJw+dE=", "dev": true }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + } + }, "matchmediaquery": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.0.tgz", @@ -15106,6 +16076,22 @@ "mimic-fn": "^1.0.0" } }, + "memoizee": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.13.tgz", + "integrity": "sha512-OVDg4OBcDOaNnTKbVYZPf+N6ON4oon2V0fBVJ1QkIGnfjdusLoUISUptQTY5kP5+zmnAr6k5V/zLc8nKNmVrcg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -15200,7 +16186,6 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -15260,6 +16245,17 @@ "dom-walk": "^0.1.0" } }, + "mini-css-extract-plugin": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.1.tgz", + "integrity": "sha512-XWuB3G61Rtasq/gLe7cp5cuozehE6hN+E4sxCamRR/WDiHTg+f7ZIAS024r8UJQffY+e2gGELXQZgQoFDfNDCg==", + "dev": true, + "requires": { + "@webpack-contrib/schema-utils": "^1.0.0-beta.0", + "loader-utils": "^1.1.0", + "webpack-sources": "^1.1.0" + } + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -15317,7 +16313,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -15327,7 +16322,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -15432,6 +16426,12 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=", + "dev": true + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -15486,7 +16486,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -15745,7 +16744,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -15780,6 +16778,15 @@ } } }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, "npm-run-all": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.3.tgz", @@ -15848,8 +16855,95 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "nunjucks": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.1.3.tgz", + "integrity": "sha512-UtlKKAzg9vdtvURdNy9DjGhiB7qYf2R7Ez+hsucOQG5gYJexSggXSSZ+9IpSDyKOlWu/4rMVPH2oVoANOSqNKA==", + "requires": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "chokidar": "^2.0.0", + "postinstall-build": "^5.0.1", + "yargs": "^3.32.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } }, "nwsapi": { "version": "2.0.4", @@ -15877,7 +16971,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -15888,7 +16981,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -15897,7 +16989,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -15926,7 +17017,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, "requires": { "isobject": "^3.0.0" } @@ -15943,6 +17033,29 @@ "object-keys": "^1.0.11" } }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "object.entries": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", @@ -15965,6 +17078,27 @@ "es-abstract": "^1.5.1" } }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -15979,11 +17113,31 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, "requires": { "isobject": "^3.0.1" } }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "object.values": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", @@ -16092,6 +17246,15 @@ "wordwrap": "~1.0.0" } }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, "original": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz", @@ -16259,6 +17422,17 @@ "is-hexadecimal": "^1.0.0" } }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -16317,8 +17491,7 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, "passport": { "version": "0.4.0", @@ -16362,8 +17535,7 @@ "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" }, "path-exists": { "version": "3.0.0", @@ -16394,6 +17566,21 @@ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -16489,6 +17676,18 @@ "find-up": "^2.1.0" } }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, "pn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", @@ -16523,8 +17722,7 @@ "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { "version": "6.0.23", @@ -18744,6 +19942,11 @@ } } }, + "postinstall-build": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.1.tgz", + "integrity": "sha1-uRepB5smF42aJK9aXNjLSpkdEbk=" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -18805,6 +20008,12 @@ } } }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, "pretty-time": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", @@ -19746,7 +20955,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "minimatch": "^3.0.2", @@ -19783,6 +20991,15 @@ } } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, "recompose": { "version": "0.27.1", "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.27.1.tgz", @@ -19916,7 +21133,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -20402,11 +21618,31 @@ "integrity": "sha1-B79CyzMvTPboXq2DteToltIyayE=", "dev": true }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "renderkid": { "version": "2.0.1", @@ -20432,14 +21668,12 @@ "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -20456,6 +21690,17 @@ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "dev": true }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, "request": { "version": "2.87.0", "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", @@ -20551,6 +21796,12 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "dev": true + }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -20592,6 +21843,15 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, "resolve-path": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", @@ -20611,8 +21871,7 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "restore-cursor": { "version": "2.0.0", @@ -20627,8 +21886,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "right-align": { "version": "0.1.3", @@ -20739,7 +21997,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, "requires": { "ret": "~0.1.10" } @@ -20830,6 +22087,15 @@ "semver": "^5.0.3" } }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", @@ -20897,14 +22163,12 @@ "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -20916,7 +22180,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -21081,7 +22344,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -21097,7 +22359,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -21106,7 +22367,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -21117,7 +22377,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -21128,7 +22387,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -21137,7 +22395,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -21146,7 +22403,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -21155,7 +22411,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -21168,7 +22423,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, "requires": { "kind-of": "^3.2.0" }, @@ -21177,7 +22431,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -21237,8 +22490,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-loader": { "version": "0.2.3", @@ -21281,7 +22533,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -21309,7 +22560,12 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", "dev": true }, "spdx-correct": { @@ -21386,7 +22642,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -21449,7 +22704,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -21459,7 +22713,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -21515,6 +22768,12 @@ "stream-shift": "^1.0.0" } }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", @@ -21629,7 +22888,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -21640,6 +22898,12 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -21734,6 +22998,16 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "svgo": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", @@ -21968,6 +23242,16 @@ "xtend": "~4.0.1" } }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, "thunky": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", @@ -21980,6 +23264,12 @@ "integrity": "sha512-5StGdiXCiBsq2+RdBQ0NrunFeKqVX0f2Myn8s1YqOxRS+kmuiHcdpPm27ucbM6FYawBKGTOOYxPnqxIBZyiqEg==", "dev": true }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -21995,6 +23285,16 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", + "dev": true, + "requires": { + "es5-ext": "~0.10.14", + "next-tick": "1" + } + }, "tiny-emitter": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", @@ -22028,6 +23328,16 @@ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", "dev": true }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -22044,7 +23354,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -22053,7 +23362,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -22064,7 +23372,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -22076,12 +23383,20 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, "to-vfile": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-5.0.0.tgz", @@ -22807,12 +24122,41 @@ "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", "dev": true }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, "underscore": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", "dev": true }, + "undertaker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", + "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, "unherit": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", @@ -22889,7 +24233,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -22901,7 +24244,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -22910,7 +24252,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -22950,6 +24291,16 @@ "imurmurhash": "^0.1.4" } }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -23053,7 +24404,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -23063,7 +24413,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -23074,7 +24423,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -23084,8 +24432,7 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" } } }, @@ -23098,8 +24445,7 @@ "upath": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" }, "update-notifier": { "version": "2.5.0", @@ -23137,8 +24483,7 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { "version": "0.11.0", @@ -23206,7 +24551,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true, "requires": { "kind-of": "^6.0.2" } @@ -23278,6 +24622,12 @@ "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==", "dev": true }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -23331,6 +24681,105 @@ "unist-util-stringify-position": "^1.1.1" } }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + } + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + } + }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", diff --git a/package.json b/package.json index 9283410b5..ec4f1a241 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "npm-run-all compile --parallel build:*", "build:client": "ts-node ./scripts/build.ts", - "build:server": "tsc -p ./src/tsconfig.json", + "build:server": "gulp server", "compile": "npm-run-all --parallel compile:*", "compile:css-types": "tcm src/core/client/", "compile:relay-stream": "ts-node ./scripts/compileRelay --src ./src/core/client/stream --schema tenant", @@ -13,7 +13,7 @@ "compile:schema": "node ./scripts/generateSchemaTypes.js", "docz": "docz", "start": "node dist/index.js", - "start:development": "cross-env NODE_ENV=development ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts", + "start:development": "NODE_ENV=development ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts", "start:webpackDevServer": "ts-node ./scripts/start.ts", "lint": "npm-run-all --parallel lint:*", "lint:server": "tslint --project ./src/tsconfig.json", @@ -27,7 +27,7 @@ "tscheck:client": "tsc --project ./src/core/client/tsconfig.json --noEmit", "tscheck:client-embed": "tsc --project ./src/core/client/embed/tsconfig.json --noEmit", "tscheck:scripts": "tsc --project ./tsconfig.json --noEmit", - "watch": "cross-env NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts --config ./config/watcher.ts" + "watch": "NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts --config ./config/watcher.ts" }, "author": "", "license": "Apache-2.0", @@ -36,6 +36,7 @@ "apollo-server-express": "^1.3.6", "bcryptjs": "^2.4.3", "bunyan": "^1.8.12", + "consolidate": "0.14.0", "convict": "^4.3.1", "dataloader": "^1.4.0", "dotenv": "^6.0.0", @@ -56,6 +57,7 @@ "lodash": "^4.17.10", "luxon": "^1.3.1", "mongodb": "^3.1.1", + "nunjucks": "^3.1.3", "passport": "^0.4.0", "passport-local": "^1.0.0", "passport-oauth2": "^1.4.0", @@ -78,6 +80,7 @@ "@types/chokidar": "^1.7.5", "@types/classnames": "^2.2.4", "@types/commander": "^2.12.2", + "@types/consolidate": "0.0.34", "@types/convict": "^4.2.0", "@types/cross-spawn": "^6.0.0", "@types/dotenv": "^4.0.3", @@ -85,7 +88,6 @@ "@types/enzyme-adapter-react-16": "^1.0.2", "@types/eventemitter2": "^4.1.0", "@types/express": "^4.16.0", - "@types/extract-text-webpack-plugin": "^3.0.3", "@types/fs-extra": "^5.0.4", "@types/graphql": "^0.13.3", "@types/html-webpack-plugin": "^2.30.4", @@ -97,8 +99,10 @@ "@types/linkify-it": "^2.0.3", "@types/lodash": "^4.14.111", "@types/luxon": "^0.5.3", + "@types/mini-css-extract-plugin": "^0.2.0", "@types/mongodb": "^3.1.1", "@types/node": "^10.5.2", + "@types/nunjucks": "^3.0.0", "@types/passport": "^0.4.6", "@types/passport-local": "^1.0.33", "@types/passport-oauth2": "^1.4.5", @@ -123,6 +127,7 @@ "autoprefixer": "^8.6.5", "babel-core": "^7.0.0-bridge.0", "babel-loader": "^8.0.0-beta", + "babel-plugin-module-resolver": "^3.1.1", "babel-plugin-relay": "github:coralproject/patched#babel-plugin-relay", "babel-preset-react-optimize": "^1.0.1", "case-sensitive-paths-webpack-plugin": "^2.1.2", @@ -130,16 +135,16 @@ "chokidar": "^2.0.4", "classnames": "^2.2.5", "commander": "^2.16.0", + "comment-json": "^1.1.3", "copy-webpack-plugin": "^4.5.1", - "cross-env": "^5.2.0", "cross-spawn": "^6.0.5", "css-loader": "^0.28.11", + "del": "^3.0.0", "docz": "^0.5.8", "enzyme": "^3.3.0", "enzyme-adapter-react-16": "^1.1.1", "enzyme-to-json": "^3.3.4", "eventemitter2": "^5.0.1", - "extract-text-webpack-plugin": "^4.0.0-beta.0", "final-form": "^4.8.1", "flat": "^4.1.0", "fluent": "^0.6.4", @@ -148,12 +153,18 @@ "fluent-react": "^0.7.0", "graphql-playground-middleware-express": "^1.7.2", "graphql-schema-typescript": "^1.2.1", + "gulp": "^4.0.0", + "gulp-babel": "^8.0.0-beta.2", + "gulp-cli": "^2.0.1", + "gulp-sourcemaps": "^2.6.4", + "gulp-typescript": "^5.0.0-alpha.3", "html-webpack-plugin": "^3.2.0", "jest": "^23.4.1", "jest-junit": "^5.1.0", "jsdom": "^11.11.0", "loader-utils": "^1.1.0", "material-design-icons": "^3.0.1", + "mini-css-extract-plugin": "^0.4.1", "npm-run-all": "^4.1.3", "postcss-advanced-variables": "^2.3.3", "postcss-css-variables": "^0.9.0", diff --git a/scripts/generateSchemaTypes.js b/scripts/generateSchemaTypes.js index 3344eb33f..f2c52a705 100644 --- a/scripts/generateSchemaTypes.js +++ b/scripts/generateSchemaTypes.js @@ -77,14 +77,20 @@ async function main() { return files; } -main() - .then(files => { - for (const { fileName } of files) { +module.exports = main; + +if (require.main === module) { + // Only run the main module on file load if this is the main module (we're + // executing this file directly). + main() + .then(files => { + for (const { fileName } of files) { + // tslint:disable-next-line:no-console + console.log(`Generated ${fileName}`); + } + }) + .catch(err => { // tslint:disable-next-line:no-console - console.log(`Generated ${fileName}`); - } - }) - .catch(err => { - // tslint:disable-next-line:no-console - console.error(err); - }); + console.error(err); + }); +} diff --git a/src/core/build/createWebpackConfig.ts b/src/core/build/createWebpackConfig.ts index ea6d4b196..cd2924338 100644 --- a/src/core/build/createWebpackConfig.ts +++ b/src/core/build/createWebpackConfig.ts @@ -1,6 +1,6 @@ import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin"; -import ExtractTextPlugin from "extract-text-webpack-plugin"; import HtmlWebpackPlugin, { Options } from "html-webpack-plugin"; +import MiniCssExtractPlugin from "mini-css-extract-plugin"; import path from "path"; import InterpolateHtmlPlugin from "react-dev-utils/InterpolateHtmlPlugin"; import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin"; @@ -8,6 +8,7 @@ import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin"; import UglifyJsPlugin from "uglifyjs-webpack-plugin"; import webpack, { Configuration } from "webpack"; import ManifestPlugin from "webpack-manifest-plugin"; + import paths from "./paths"; interface CreateWebpackConfig { @@ -59,27 +60,6 @@ export default function createWebpackConfig({ }, }; - const cssLoaders = [ - { - loader: require.resolve("css-loader"), - options: { - modules: true, - importLoaders: 1, - localIdentName: "[name]-[local]-[hash:base64:5]", - minimize: isProduction, - sourceMap: isProduction && !disableSourcemaps, - }, - }, - { - loader: require.resolve("postcss-loader"), - options: { - config: { - path: paths.appPostCssConfig, - }, - }, - }, - ]; - const localesOptions = { pathToLocales: paths.appLocales, @@ -127,13 +107,9 @@ export default function createWebpackConfig({ }, sourceMap: !disableSourcemaps, }), - // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`. - new ExtractTextPlugin({ - // We use [md5:contenthash:hex:20] instead of [contenthash:8] - // because of this bug https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/763. - // TODO: Repalce with mini-css-extract-plugin once it supports HMR. - // https://github.com/webpack-contrib/mini-css-extract-plugin - filename: "assets/css/[name].[md5:contenthash:hex:20].css", + new MiniCssExtractPlugin({ + filename: "assets/css/[name].[hash].css", + chunkFilename: "assets/css/[id].[hash].css", }), ] : [ @@ -316,19 +292,27 @@ export default function createWebpackConfig({ // in development "style" loader enables hot editing of CSS. { test: /\.css$/, - loader: - (isProduction && - ExtractTextPlugin.extract({ - fallback: styleLoader, - use: cssLoaders, - })) || - undefined, - use: - (!isProduction && [ - require.resolve("style-loader"), - ...cssLoaders, - ]) || - undefined, + use: [ + isProduction ? MiniCssExtractPlugin.loader : styleLoader, + { + loader: require.resolve("css-loader"), + options: { + modules: true, + importLoaders: 1, + localIdentName: "[name]-[local]-[hash:base64:5]", + minimize: isProduction, + sourceMap: isProduction && !disableSourcemaps, + }, + }, + { + loader: require.resolve("postcss-loader"), + options: { + config: { + path: paths.appPostCssConfig, + }, + }, + }, + ], }, // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. diff --git a/src/core/server/app/handlers/auth/local.ts b/src/core/server/app/handlers/auth/local.ts index 0c438ccf3..48daf4c32 100644 --- a/src/core/server/app/handlers/auth/local.ts +++ b/src/core/server/app/handlers/auth/local.ts @@ -14,7 +14,6 @@ export interface SignupBody { username: string; password: string; email: string; - displayName?: string; } const SignupBodySchema = Joi.object().keys({ diff --git a/src/core/server/app/handlers/embed/stream.ts b/src/core/server/app/handlers/embed/stream.ts new file mode 100644 index 000000000..73b7d0ea4 --- /dev/null +++ b/src/core/server/app/handlers/embed/stream.ts @@ -0,0 +1,5 @@ +import { RequestHandler } from "express"; + +export const streamHandler: RequestHandler = (req, res) => { + res.render("stream"); +}; diff --git a/src/core/server/app/index.ts b/src/core/server/app/index.ts index 3be153164..5f7ba22e6 100644 --- a/src/core/server/app/index.ts +++ b/src/core/server/app/index.ts @@ -1,7 +1,10 @@ +import cons from "consolidate"; import { Express } from "express"; import http from "http"; import { Redis } from "ioredis"; import { Db } from "mongodb"; +import nunjucks from "nunjucks"; +import path from "path"; import { Config } from "talk-common/config"; import { notFoundMiddleware } from "talk-server/app/middleware/notFound"; @@ -29,6 +32,9 @@ export interface AppOptions { * createApp will create a Talk Express app that can be used to handle requests. */ export async function createApp(options: AppOptions): Promise { + // Configure the application. + configureApplication(options); + // Pull the parent out of the options. const { parent } = options; @@ -46,7 +52,7 @@ export async function createApp(options: AppOptions): Promise { ); // Static Files - parent.use(serveStatic); + parent.use("/assets", serveStatic); // Error Handling parent.use(notFoundMiddleware); @@ -70,6 +76,38 @@ export const listenAndServe = ( const httpServer = app.listen(port, () => resolve(httpServer)); }); +function configureApplication(options: AppOptions) { + const { parent } = options; + + // Trust the first proxy in front of us, this will enable us to trust the fact + // that SSL was terminated correctly. + parent.set("trust proxy", 1); + + // Setup the view config. + setupViews(options); +} + +function setupViews(options: AppOptions) { + const { parent } = options; + + // configure the default views directory. + const views = path.join(__dirname, "..", "..", "..", "static"); + parent.set("views", views); + + // Reconfigure nunjucks. + (cons.requires as any).nunjucks = nunjucks.configure(views, { + // In development, we should enable file watch mode. + watch: options.config.get("env") === "development", + }); + + // assign the nunjucks engine to .njk and .html files. + parent.engine("njk", cons.nunjucks); + parent.engine("html", cons.nunjucks); + + // set .html as the default extension. + parent.set("view engine", "html"); +} + /** * attachSubscriptionHandlers attaches all the handlers to the http.Server to * handle websocket traffic by upgrading their http connections to websocket. diff --git a/src/core/server/app/middleware/notFound.ts b/src/core/server/app/middleware/notFound.ts index 1d5dbde5c..026d93549 100644 --- a/src/core/server/app/middleware/notFound.ts +++ b/src/core/server/app/middleware/notFound.ts @@ -1,5 +1,6 @@ import { RequestHandler } from "express"; export const notFoundMiddleware: RequestHandler = (req, res, next) => { + // FIXME: (wyattjoh) send an error that won't log as crazily as this one does. next(new Error("not found")); }; diff --git a/src/core/server/app/middleware/serveStatic.ts b/src/core/server/app/middleware/serveStatic.ts index c69e599bb..ed21e62a2 100644 --- a/src/core/server/app/middleware/serveStatic.ts +++ b/src/core/server/app/middleware/serveStatic.ts @@ -1,4 +1,8 @@ import serveStatic from "express-static-gzip"; import path from "path"; -export default serveStatic(path.join(__dirname, "..", "..", "dist"), {}); +const staticPath = path.resolve( + path.join(__dirname, "..", "..", "..", "..", "static", "assets") +); + +export default serveStatic(staticPath, { index: false }); diff --git a/src/core/server/app/middleware/tenant.ts b/src/core/server/app/middleware/tenant.ts index 00ff11c07..4b81d1175 100644 --- a/src/core/server/app/middleware/tenant.ts +++ b/src/core/server/app/middleware/tenant.ts @@ -28,6 +28,9 @@ export default (options: MiddlewareOptions) => async ( // Attach the tenant to the request. req.tenant = tenant; + // Attach the tenant to the view locals. + res.locals.tenant = tenant; + next(); } catch (err) { next(err); diff --git a/src/core/server/app/router.ts b/src/core/server/app/router.ts index 059a1c39a..6c06f8848 100644 --- a/src/core/server/app/router.ts +++ b/src/core/server/app/router.ts @@ -2,6 +2,7 @@ import express from "express"; import passport from "passport"; import { signupHandler } from "talk-server/app/handlers/auth/local"; +import { streamHandler } from "talk-server/app/handlers/embed/stream"; import { apiErrorHandler } from "talk-server/app/middleware/error"; import { errorLogger } from "talk-server/app/middleware/logging"; import { wrapAuthn } from "talk-server/app/middleware/passport"; @@ -134,5 +135,8 @@ export async function createRouter(app: AppOptions, options: RouterOptions) { ); } + // Handle the stream handler. + router.get("/embed/stream", streamHandler); + return router; } From 1dec622e64907f5058bf089d6966cf3cf14617fe Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 10 Aug 2018 19:07:41 +0200 Subject: [PATCH 12/18] Support rest and implement SignIn and SignUp Rest + Mutations --- package.json | 2 +- .../client/auth/mutations/SignInMutation.ts | 23 +++++++++++++++++++ .../client/auth/mutations/SignUpMutation.ts | 23 +++++++++++++++++++ src/core/client/auth/mutations/index.ts | 2 ++ src/core/client/framework/lib/rest.ts | 4 ++-- .../mutations/SetAuthTokenMutation.spec.ts | 21 +++++++++++++++-- .../mutations/SetAuthTokenMutation.ts | 9 +++++++- src/core/client/framework/rest/signIn.ts | 8 +++++-- src/core/client/framework/rest/signUp.ts | 6 ++++- .../onPostMessageSetAuthToken.spec.ts | 2 ++ .../listeners/onPostMessageSetAuthToken.ts | 8 +++---- .../client/stream/local/initLocalState.ts | 1 + 12 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 src/core/client/auth/mutations/SignInMutation.ts create mode 100644 src/core/client/auth/mutations/SignUpMutation.ts diff --git a/package.json b/package.json index 635a15066..d2ca86843 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "compile:schema": "node ./scripts/generateSchemaTypes.js", "docz": "docz", "start": "node dist/index.js", - "start:development": "cross-env NODE_ENV=development ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts", + "start:development": "ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts", "start:webpackDevServer": "ts-node ./scripts/start.ts", "lint": "npm-run-all --parallel lint:*", "lint:server": "tslint --project ./src/tsconfig.json", diff --git a/src/core/client/auth/mutations/SignInMutation.ts b/src/core/client/auth/mutations/SignInMutation.ts new file mode 100644 index 000000000..6a88b9313 --- /dev/null +++ b/src/core/client/auth/mutations/SignInMutation.ts @@ -0,0 +1,23 @@ +import { Environment } from "relay-runtime"; + +import { TalkContext } from "talk-framework/lib/bootstrap"; +import { createMutationContainer } from "talk-framework/lib/relay"; +import { signIn, SignInInput } from "talk-framework/rest"; + +export type SignInMutation = (input: SignInInput) => Promise; + +export async function commit( + environment: Environment, + input: SignInInput, + { rest, postMessage }: TalkContext +) { + try { + const result = await signIn(rest, input); + postMessage.send("setAuthToken", result.token, window.opener); + window.close(); + } catch (err) { + postMessage.send("authError", err.toString(), window.opener); + } +} + +export const withSignInMutation = createMutationContainer("signIn", commit); diff --git a/src/core/client/auth/mutations/SignUpMutation.ts b/src/core/client/auth/mutations/SignUpMutation.ts new file mode 100644 index 000000000..68beaeae2 --- /dev/null +++ b/src/core/client/auth/mutations/SignUpMutation.ts @@ -0,0 +1,23 @@ +import { Environment } from "relay-runtime"; + +import { TalkContext } from "talk-framework/lib/bootstrap"; +import { createMutationContainer } from "talk-framework/lib/relay"; +import { signUp, SignUpInput } from "talk-framework/rest"; + +export type SignUpMutation = (input: SignUpInput) => Promise; + +export async function commit( + environment: Environment, + input: SignUpInput, + { rest, postMessage }: TalkContext +) { + try { + const result = await signUp(rest, input); + postMessage.send("setAuthToken", result.token, window.opener); + window.close(); + } catch (err) { + postMessage.send("authError", err.toString(), window.opener); + } +} + +export const withSignUpMutation = createMutationContainer("signUp", commit); diff --git a/src/core/client/auth/mutations/index.ts b/src/core/client/auth/mutations/index.ts index 50d8d059b..46e02df95 100644 --- a/src/core/client/auth/mutations/index.ts +++ b/src/core/client/auth/mutations/index.ts @@ -1 +1,3 @@ export { withSetViewMutation, SetViewMutation } from "./SetViewMutation"; +export { withSignInMutation, SignInMutation } from "./SignInMutation"; +export { withSignUpMutation, SignUpMutation } from "./SignUpMutation"; diff --git a/src/core/client/framework/lib/rest.ts b/src/core/client/framework/lib/rest.ts index b8ccdccab..6ba52b958 100644 --- a/src/core/client/framework/lib/rest.ts +++ b/src/core/client/framework/lib/rest.ts @@ -21,7 +21,7 @@ const handleResp = (res: Response) => { if (res.status > 399) { return res.json().then((err: any) => { // TODO: sync error handling with server. - const message = err.message || res.status; + const message = err.message || err.error || res.status; const error = new Error(message); throw error; }); @@ -43,7 +43,7 @@ export class RestClient { this.tokenGetter = tokenGetter; } - public fetch(path: string, options: PartialRequestInit): Promise { + public fetch(path: string, options: PartialRequestInit): Promise { let opts = options; if (this.tokenGetter) { opts = merge({}, options, { diff --git a/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts b/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts index 7440078ad..587ddc2d5 100644 --- a/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts +++ b/src/core/client/framework/mutations/SetAuthTokenMutation.spec.ts @@ -2,6 +2,7 @@ import { commitLocalUpdate, Environment, RecordSource } from "relay-runtime"; import { timeout } from "talk-common/utils"; import { LOCAL_ID } from "talk-framework/lib/relay"; +import { createInMemoryStorage } from "talk-framework/lib/storage"; import { createRelayEnvironment } from "talk-framework/testHelpers"; import { commit } from "./SetAuthTokenMutation"; @@ -16,18 +17,34 @@ beforeAll(() => { }); it("Sets auth token", async () => { + const context = { + localStorage: createInMemoryStorage(), + }; const authToken = "auth token"; - commit(environment, { authToken }); + commit(environment, { authToken }, context as any); expect(source.get(LOCAL_ID)!.authToken).toEqual(authToken); + expect(context.localStorage.getItem("authToken")).toEqual(authToken); +}); + +it("Removes auth token from localStorage", async () => { + const context = { + localStorage: createInMemoryStorage(), + }; + localStorage.setItem("authToken", "tmp"); + commit(environment, { authToken: null }, context as any); + expect(context.localStorage.getItem("authToken")).toBeUndefined(); }); it("Should call gc", async () => { + const context = { + localStorage: createInMemoryStorage(), + }; commitLocalUpdate(environment, store => { store.create("should-disappear", "tmp"); }); const authToken = null; expect(source.get("should-disappear")).not.toBeUndefined(); - commit(environment, { authToken }); + commit(environment, { authToken }, context as any); await timeout(); expect(source.get(LOCAL_ID)!.authToken).toEqual(authToken); expect(source.get("should-disappear")).toBeUndefined(); diff --git a/src/core/client/framework/mutations/SetAuthTokenMutation.ts b/src/core/client/framework/mutations/SetAuthTokenMutation.ts index 38ecde460..223bc4054 100644 --- a/src/core/client/framework/mutations/SetAuthTokenMutation.ts +++ b/src/core/client/framework/mutations/SetAuthTokenMutation.ts @@ -1,5 +1,6 @@ import { commitLocalUpdate, Environment } from "relay-runtime"; +import { TalkContext } from "talk-framework/lib/bootstrap"; import { createMutationContainer } from "talk-framework/lib/relay"; import { LOCAL_ID } from "talk-framework/lib/relay/withLocalStateContainer"; @@ -11,11 +12,17 @@ export type SetAuthTokenMutation = (input: SetAuthTokenInput) => Promise; export async function commit( environment: Environment, - input: SetAuthTokenInput + input: SetAuthTokenInput, + { localStorage }: TalkContext ) { return commitLocalUpdate(environment, store => { const record = store.get(LOCAL_ID)!; record.setValue(input.authToken, "authToken"); + if (input.authToken) { + localStorage.setItem("authToken", input.authToken); + } else { + localStorage.removeItem("authToken"); + } // Force gc to trigger. environment diff --git a/src/core/client/framework/rest/signIn.ts b/src/core/client/framework/rest/signIn.ts index 4b537b01c..9f357df02 100644 --- a/src/core/client/framework/rest/signIn.ts +++ b/src/core/client/framework/rest/signIn.ts @@ -1,12 +1,16 @@ import { RestClient } from "../lib/rest"; export interface SignInInput { - username: string; + email: string; password: string; } +export interface SignInResponse { + token: string; +} + export default function signIn(rest: RestClient, input: SignInInput) { - return rest.fetch("/tenant/auth/local", { + return rest.fetch("/tenant/auth/local", { method: "POST", body: input, }); diff --git a/src/core/client/framework/rest/signUp.ts b/src/core/client/framework/rest/signUp.ts index eece6271b..a6aa87d76 100644 --- a/src/core/client/framework/rest/signUp.ts +++ b/src/core/client/framework/rest/signUp.ts @@ -6,8 +6,12 @@ export interface SignUpInput { email: string; } +export interface SignUpResponse { + token: string; +} + export default function signUp(rest: RestClient, input: SignUpInput) { - return rest.fetch("/tenant/auth/local/signup", { + return rest.fetch("/tenant/auth/local/signup", { method: "POST", body: input, }); diff --git a/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts b/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts index 37ed034d6..c35823c8a 100644 --- a/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts +++ b/src/core/client/stream/listeners/onPostMessageSetAuthToken.spec.ts @@ -1,6 +1,7 @@ import { Environment, RecordSource } from "relay-runtime"; import { LOCAL_ID } from "talk-framework/lib/relay"; +import { createInMemoryStorage } from "talk-framework/lib/storage"; import { createRelayEnvironment } from "talk-framework/testHelpers"; import onPostMessageSetAuthToken from "./onPostMessageSetAuthToken"; @@ -24,6 +25,7 @@ it("Sets auth token", () => { }, }, relayEnvironment, + localStorage: createInMemoryStorage(), }; onPostMessageSetAuthToken(context as any); expect(source.get(LOCAL_ID)!.authToken).toEqual(token); diff --git a/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts b/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts index 77be702ad..767af51f7 100644 --- a/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts +++ b/src/core/client/stream/listeners/onPostMessageSetAuthToken.ts @@ -2,12 +2,10 @@ import { TalkContext } from "talk-framework/lib/bootstrap"; import { commit as setAuthToken } from "talk-framework/mutations/SetAuthTokenMutation"; -export default function onPostMessageSetAuthToken({ - relayEnvironment, - postMessage, -}: TalkContext) { +export default function onPostMessageSetAuthToken(ctx: TalkContext) { + const { relayEnvironment, postMessage } = ctx; // Auth popup will use this to handle a successful login. postMessage!.on("setAuthToken", (authToken: string) => { - setAuthToken(relayEnvironment, { authToken }); + setAuthToken(relayEnvironment, { authToken }, ctx); }); } diff --git a/src/core/client/stream/local/initLocalState.ts b/src/core/client/stream/local/initLocalState.ts index dd021f756..171c52294 100644 --- a/src/core/client/stream/local/initLocalState.ts +++ b/src/core/client/stream/local/initLocalState.ts @@ -23,6 +23,7 @@ export default async function initLocalState( { localStorage }: TalkContext ) { commitLocalUpdate(environment, s => { + // TODO: (cvle) move local, auth token and network initialization to framework. const root = s.getRoot(); // Create the Local Record which is the Root for the client states. From de5c37ebcf79290178714e45680a4b87bfbd057f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Sun, 12 Aug 2018 19:22:50 -0300 Subject: [PATCH 13/18] Stream Styling --- src/core/client/auth/components/SignUp.tsx | 4 +- src/core/client/stream/components/App.tsx | 1 - .../stream/components/PostCommentForm.css | 7 ++- .../stream/components/PostCommentForm.tsx | 22 ++++++++-- .../components/UserBoxUnauthenticated.tsx | 2 +- .../containers/PostCommentFormContainer.tsx | 2 +- .../InputDescription/InputDescription.css | 2 + .../InputDescription/InputDescription.mdx | 36 ++++++++++++++++ .../InputDescription/InputDescription.tsx | 43 +++++++++++++++++++ .../ui/components/InputDescription/index.ts | 1 + src/core/client/ui/shared/typography.css | 2 +- src/locales/de/stream.ftl | 2 +- src/locales/en-US/stream.ftl | 2 +- 13 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 src/core/client/ui/components/InputDescription/InputDescription.css create mode 100644 src/core/client/ui/components/InputDescription/InputDescription.mdx create mode 100644 src/core/client/ui/components/InputDescription/InputDescription.tsx create mode 100644 src/core/client/ui/components/InputDescription/index.ts diff --git a/src/core/client/auth/components/SignUp.tsx b/src/core/client/auth/components/SignUp.tsx index 44eaaf70f..49cce2aa1 100644 --- a/src/core/client/auth/components/SignUp.tsx +++ b/src/core/client/auth/components/SignUp.tsx @@ -32,7 +32,9 @@ const SignUp: StatelessComponent = props => { Password - Must be at least 8 characters + + Must be at least 8 characters + diff --git a/src/core/client/stream/components/App.tsx b/src/core/client/stream/components/App.tsx index f5f4262f7..a09c49149 100644 --- a/src/core/client/stream/components/App.tsx +++ b/src/core/client/stream/components/App.tsx @@ -22,7 +22,6 @@ const App: StatelessComponent = props => { {view} ); - // return
{view}
; }; export default App; diff --git a/src/core/client/stream/components/PostCommentForm.css b/src/core/client/stream/components/PostCommentForm.css index e813f4ea7..7a8ffebee 100644 --- a/src/core/client/stream/components/PostCommentForm.css +++ b/src/core/client/stream/components/PostCommentForm.css @@ -1,15 +1,18 @@ .root { width: 100%; + padding-bottom: var(--spacing-unit); } .textarea { composes: bodyCopy from "talk-ui/shared/typography.css"; - display: block; - height: 100px; + height: 150px; width: 100%; box-sizing: border-box; margin-bottom: var(--spacing-unit); + padding: var(--spacing-unit); + border-radius: var(--round-corners); + resize: vertical; } .postButtonContainer { diff --git a/src/core/client/stream/components/PostCommentForm.tsx b/src/core/client/stream/components/PostCommentForm.tsx index 72bc0ad70..c90c56b96 100644 --- a/src/core/client/stream/components/PostCommentForm.tsx +++ b/src/core/client/stream/components/PostCommentForm.tsx @@ -15,6 +15,7 @@ interface FormProps { export interface PostCommentFormProps { onSubmit: OnSubmit; + signedIn: boolean; } const PostCommentForm: StatelessComponent = props => ( @@ -29,6 +30,7 @@ const PostCommentForm: StatelessComponent = props => ( name={input.name} onChange={input.onChange} value={input.value} + placeholder="Post a comment" /> {meta.touched && (meta.error || meta.submitError) && ( @@ -40,11 +42,23 @@ const PostCommentForm: StatelessComponent = props => ( )}
- - + + ) : ( + - + )}
)} diff --git a/src/core/client/stream/components/UserBoxUnauthenticated.tsx b/src/core/client/stream/components/UserBoxUnauthenticated.tsx index 323b0acf5..f1a8716ee 100644 --- a/src/core/client/stream/components/UserBoxUnauthenticated.tsx +++ b/src/core/client/stream/components/UserBoxUnauthenticated.tsx @@ -15,7 +15,7 @@ const UserBoxUnauthenticated: StatelessComponent< UserBoxUnauthenticatedProps > = props => { return ( - + { return undefined; }; public render() { - return ; + return ; } } diff --git a/src/core/client/ui/components/InputDescription/InputDescription.css b/src/core/client/ui/components/InputDescription/InputDescription.css new file mode 100644 index 000000000..c3a2af639 --- /dev/null +++ b/src/core/client/ui/components/InputDescription/InputDescription.css @@ -0,0 +1,2 @@ +.root { +} diff --git a/src/core/client/ui/components/InputDescription/InputDescription.mdx b/src/core/client/ui/components/InputDescription/InputDescription.mdx new file mode 100644 index 000000000..3dc055085 --- /dev/null +++ b/src/core/client/ui/components/InputDescription/InputDescription.mdx @@ -0,0 +1,36 @@ +--- +name: FormField +menu: UI Kit +--- + +import { Playground, PropsTable } from 'docz' +import FormField from './FormField' +import { InputLabel, ValidationMessage, TextField, Typography, Flex, Button} from '../core/client/ui/components' + +# Flex + +`FormField` is to be used with Form Components `flexbox`. + +## Justify content + + + + + +## Align items + + + + + + + + +## Direction + + + + + + + diff --git a/src/core/client/ui/components/InputDescription/InputDescription.tsx b/src/core/client/ui/components/InputDescription/InputDescription.tsx new file mode 100644 index 000000000..fe5b6dd7b --- /dev/null +++ b/src/core/client/ui/components/InputDescription/InputDescription.tsx @@ -0,0 +1,43 @@ +import cn from "classnames"; +import React, { ReactNode } from "react"; +import { StatelessComponent } from "react"; + +import { withStyles } from "talk-ui/hocs"; + +import * as styles from "./FormField.css"; + +interface InnerProps { + children: ReactNode; + classes: typeof styles; + id?: string; + className?: string; + itemGutter?: boolean | "half"; +} + +const FormField: StatelessComponent = props => { + const { classes, className, children, itemGutter, ...rest } = props; + + // TODO (bc): Use flex component once the extra div issue is solved. + return ( +
+ {children} +
+ ); +}; + +FormField.defaultProps = { + itemGutter: true, +}; + +const enhanced = withStyles(styles)(FormField); +export default enhanced; diff --git a/src/core/client/ui/components/InputDescription/index.ts b/src/core/client/ui/components/InputDescription/index.ts new file mode 100644 index 000000000..6fd0949a5 --- /dev/null +++ b/src/core/client/ui/components/InputDescription/index.ts @@ -0,0 +1 @@ +export { default } from "./InputDescription"; diff --git a/src/core/client/ui/shared/typography.css b/src/core/client/ui/shared/typography.css index a4abd6426..c688bdf1a 100644 --- a/src/core/client/ui/shared/typography.css +++ b/src/core/client/ui/shared/typography.css @@ -161,7 +161,7 @@ .inputDescription { font-size: calc(14rem / var(--rem-base)); - font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-regular); font-family: var(--font-family); line-height: calc(18em / 16); letter-spacing: calc(0.2em / 16); diff --git a/src/locales/de/stream.ftl b/src/locales/de/stream.ftl index c4eb3040a..6031e6c5d 100644 --- a/src/locales/de/stream.ftl +++ b/src/locales/de/stream.ftl @@ -2,6 +2,6 @@ ## Comments Tab -comments-postCommentForm-post = Posten +comments-postCommentForm-submit = Posten comments-stream-loadMore = Mehr laden comments-replyList-showAll = Alle anzeigen diff --git a/src/locales/en-US/stream.ftl b/src/locales/en-US/stream.ftl index 01a2ed331..6e04fcc54 100644 --- a/src/locales/en-US/stream.ftl +++ b/src/locales/en-US/stream.ftl @@ -2,7 +2,7 @@ ## Comments Tab -comments-postCommentForm-post = Post +comments-postCommentForm-submit = Submit comments-stream-loadMore = Load more comments-replyList-showAll = Show all From 9e39a093fdb0990546a56999524d86420028d3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Sun, 12 Aug 2018 22:12:23 -0300 Subject: [PATCH 14/18] Adding UserBoxAuthenticated and using correct properties for the Flex Component --- .../components/UserBoxAuthenticated.css | 3 ++ .../components/UserBoxAuthenticated.tsx | 51 +++++++++++++++++++ .../UserBoxUnauthenticated.spec.1.tsx | 16 ++++++ .../stream/containers/UserBoxContainer.tsx | 10 ++-- src/core/client/ui/components/Flex/Flex.css | 4 +- 5 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 src/core/client/stream/components/UserBoxAuthenticated.css create mode 100644 src/core/client/stream/components/UserBoxAuthenticated.tsx create mode 100644 src/core/client/stream/components/UserBoxUnauthenticated.spec.1.tsx diff --git a/src/core/client/stream/components/UserBoxAuthenticated.css b/src/core/client/stream/components/UserBoxAuthenticated.css new file mode 100644 index 000000000..272b33bdb --- /dev/null +++ b/src/core/client/stream/components/UserBoxAuthenticated.css @@ -0,0 +1,3 @@ +.joinText { + margin-right: var(--spacing-unit); +} diff --git a/src/core/client/stream/components/UserBoxAuthenticated.tsx b/src/core/client/stream/components/UserBoxAuthenticated.tsx new file mode 100644 index 000000000..d897dd205 --- /dev/null +++ b/src/core/client/stream/components/UserBoxAuthenticated.tsx @@ -0,0 +1,51 @@ +import { Localized } from "fluent-react/compat"; +import React, { StatelessComponent } from "react"; + +import { Button, Flex, Typography } from "talk-ui/components"; + +import MatchMedia from "talk-ui/components/MatchMedia"; +// import * as styles from "./UserBoxUnauthenticated.css"; + +export interface UserBoxUnauthenticatedProps { + onSignOut: () => void; +} + +const UserBoxAuthenticated: StatelessComponent< + UserBoxUnauthenticatedProps +> = props => { + return ( + + + + + + Signed in as + + + + okbel + + + + + + + Not you? + + + + + + + + ); +}; + +export default UserBoxAuthenticated; diff --git a/src/core/client/stream/components/UserBoxUnauthenticated.spec.1.tsx b/src/core/client/stream/components/UserBoxUnauthenticated.spec.1.tsx new file mode 100644 index 000000000..f9683c1e8 --- /dev/null +++ b/src/core/client/stream/components/UserBoxUnauthenticated.spec.1.tsx @@ -0,0 +1,16 @@ +import { shallow } from "enzyme"; +import { noop } from "lodash"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import UserBoxUnauthenticated from "./UserBoxUnauthenticated"; + +it("renders correctly", () => { + const props: PropTypesOf = { + onSignIn: noop, + onRegister: noop, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/containers/UserBoxContainer.tsx b/src/core/client/stream/containers/UserBoxContainer.tsx index fca219660..db68f5cb6 100644 --- a/src/core/client/stream/containers/UserBoxContainer.tsx +++ b/src/core/client/stream/containers/UserBoxContainer.tsx @@ -11,7 +11,8 @@ import { } from "talk-stream/mutations"; import { Popup } from "talk-ui/components"; -import UserBoxUnauthenticated from "../components/UserBoxUnauthenticated"; +import UserBoxAuthenticated from "../components/UserBoxAuthenticated"; +// import UserBoxUnauthenticated from "../components/UserBoxUnauthenticated"; interface InnerProps { local: Local; @@ -23,7 +24,7 @@ export class UserBoxContainer extends Component { private handleFocus = () => this.props.setAuthPopupState({ focus: true }); private handleBlur = () => this.props.setAuthPopupState({ focus: false }); private handleClose = () => this.props.setAuthPopupState({ open: false }); - private handleSignIn = () => this.props.showAuthPopup({ view: "SIGN_IN" }); + // private handleSignIn = () => this.props.showAuthPopup({ view: "SIGN_IN" }); private handleRegister = () => this.props.showAuthPopup({ view: "SIGN_UP" }); public render() { @@ -44,10 +45,11 @@ export class UserBoxContainer extends Component { onBlur={this.handleBlur} onClose={this.handleClose} /> - + {/* + /> */} ); } diff --git a/src/core/client/ui/components/Flex/Flex.css b/src/core/client/ui/components/Flex/Flex.css index 2e6914c7f..ea5bf810d 100644 --- a/src/core/client/ui/components/Flex/Flex.css +++ b/src/core/client/ui/components/Flex/Flex.css @@ -1,10 +1,10 @@ .root { - width: 100%; + flex-grow: 1; } .flex { display: flex; - width: 100%; + flex-grow: 1; } .halfItemGutter { From 5c2ac9ee751ebe17b7dda5f22d6480d0aa86e98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Sun, 12 Aug 2018 22:17:05 -0300 Subject: [PATCH 15/18] Using correct properties for the Flex Component to support nexting Flex components --- src/core/client/ui/components/Flex/Flex.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/client/ui/components/Flex/Flex.css b/src/core/client/ui/components/Flex/Flex.css index ea5bf810d..9fed320d3 100644 --- a/src/core/client/ui/components/Flex/Flex.css +++ b/src/core/client/ui/components/Flex/Flex.css @@ -1,10 +1,12 @@ .root { flex-grow: 1; + max-width: 100%; } .flex { display: flex; flex-grow: 1; + max-width: 100%; } .halfItemGutter { From ab4ca7f24c65f4f2823c9228906067e737206abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Sun, 12 Aug 2018 22:52:03 -0300 Subject: [PATCH 16/18] Adding PoweredBy and more --- .../stream/components/PostCommentForm.css | 9 +++++- .../stream/components/PostCommentForm.tsx | 31 ++++++++++--------- .../client/stream/components/PoweredBy.css | 0 .../client/stream/components/PoweredBy.tsx | 13 ++++++++ .../components/UserBoxAuthenticated.css | 4 +-- .../components/UserBoxAuthenticated.tsx | 10 +++--- .../stream/containers/UserBoxContainer.tsx | 12 +++---- src/core/client/ui/components/Flex/Flex.css | 6 ++-- 8 files changed, 52 insertions(+), 33 deletions(-) create mode 100644 src/core/client/stream/components/PoweredBy.css create mode 100644 src/core/client/stream/components/PoweredBy.tsx diff --git a/src/core/client/stream/components/PostCommentForm.css b/src/core/client/stream/components/PostCommentForm.css index 7a8ffebee..954a4de74 100644 --- a/src/core/client/stream/components/PostCommentForm.css +++ b/src/core/client/stream/components/PostCommentForm.css @@ -17,5 +17,12 @@ .postButtonContainer { display: flex; - justify-content: flex-end; + + &:first-child { + flex-grow: 1; + } + + &:last-child { + flex-grow: 0; + } } diff --git a/src/core/client/stream/components/PostCommentForm.tsx b/src/core/client/stream/components/PostCommentForm.tsx index c90c56b96..1f57246a7 100644 --- a/src/core/client/stream/components/PostCommentForm.tsx +++ b/src/core/client/stream/components/PostCommentForm.tsx @@ -5,8 +5,8 @@ import { Field, Form } from "react-final-form"; import { OnSubmit } from "talk-framework/lib/form"; import { required } from "talk-framework/lib/validation"; +import PoweredBy from "talk-stream/components/PoweredBy"; import { Button, Typography } from "talk-ui/components"; - import * as styles from "./PostCommentForm.css"; interface FormProps { @@ -41,25 +41,26 @@ const PostCommentForm: StatelessComponent = props => ( )} -
- {props.signedIn ? ( + {props.signedIn ? ( +
+ - ) : ( - - )} -
+
+ ) : ( + + )} )} diff --git a/src/core/client/stream/components/PoweredBy.css b/src/core/client/stream/components/PoweredBy.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/client/stream/components/PoweredBy.tsx b/src/core/client/stream/components/PoweredBy.tsx new file mode 100644 index 000000000..5991c837a --- /dev/null +++ b/src/core/client/stream/components/PoweredBy.tsx @@ -0,0 +1,13 @@ +import React, { StatelessComponent } from "react"; +import { Flex, Typography } from "talk-ui/components"; + +const PoweredBy: StatelessComponent = () => { + return ( + + Powered by + The Coral Project + + ); +}; + +export default PoweredBy; diff --git a/src/core/client/stream/components/UserBoxAuthenticated.css b/src/core/client/stream/components/UserBoxAuthenticated.css index 272b33bdb..a98581e23 100644 --- a/src/core/client/stream/components/UserBoxAuthenticated.css +++ b/src/core/client/stream/components/UserBoxAuthenticated.css @@ -1,3 +1,3 @@ -.joinText { - margin-right: var(--spacing-unit); +.child { + width: initial; } diff --git a/src/core/client/stream/components/UserBoxAuthenticated.tsx b/src/core/client/stream/components/UserBoxAuthenticated.tsx index d897dd205..1b692ba9b 100644 --- a/src/core/client/stream/components/UserBoxAuthenticated.tsx +++ b/src/core/client/stream/components/UserBoxAuthenticated.tsx @@ -4,7 +4,7 @@ import React, { StatelessComponent } from "react"; import { Button, Flex, Typography } from "talk-ui/components"; import MatchMedia from "talk-ui/components/MatchMedia"; -// import * as styles from "./UserBoxUnauthenticated.css"; +import * as styles from "./UserBoxAuthenticated.css"; export interface UserBoxUnauthenticatedProps { onSignOut: () => void; @@ -15,7 +15,7 @@ const UserBoxAuthenticated: StatelessComponent< > = props => { return ( - + @@ -27,13 +27,13 @@ const UserBoxAuthenticated: StatelessComponent< - - + + Not you? - + - - Already have an account? - - - - +
+ {({ handleSubmit, submitting }) => ( + + + + + Sign up to join the conversation + + + + {({ input, meta }) => ( + + Email Address + + + )} + + + + Username + + A unique identifier displayed on your comments. You may use + “_” and “.” + + + + + Password + + Must be at least 8 characters + + + + + Confirm Password + + + +
+ + + Already have an account? + + +
+
+
+ )} + ); }; diff --git a/src/core/client/auth/containers/SignUpContainer.tsx b/src/core/client/auth/containers/SignUpContainer.tsx index 9db82383a..eac0f8d14 100644 --- a/src/core/client/auth/containers/SignUpContainer.tsx +++ b/src/core/client/auth/containers/SignUpContainer.tsx @@ -1,10 +1,31 @@ -import * as React from "react"; -import { StatelessComponent } from "react"; +import { BadUserInputError } from "talk-framework/lib/errors"; +import SignUp, { SignUpForm } from "../components/SignUp"; -import SignUp from "../components/SignUp"; +import React, { Component } from "react"; +import { SignUpMutation, withSignUpMutation } from "../mutations"; -const SignUpContainer: StatelessComponent = () => { - return ; -}; +interface SignUpContainerProps { + signUp: SignUpMutation; +} -export default SignUpContainer; +class SignUpContainer extends Component { + private onSubmit: SignUpForm["onSubmit"] = async (input, form) => { + try { + await this.props.signUp(input); + form.reset(); + } catch (error) { + if (error instanceof BadUserInputError) { + return error.invalidArgsLocalized; + } + // tslint:disable-next-line:no-console + console.error(error); + } + return undefined; + }; + public render() { + return ; + } +} + +const enhanced = withSignUpMutation(SignUpContainer); +export default enhanced; diff --git a/src/core/client/ui/components/TextField/TextField.tsx b/src/core/client/ui/components/TextField/TextField.tsx index 391b3759a..756242ec3 100644 --- a/src/core/client/ui/components/TextField/TextField.tsx +++ b/src/core/client/ui/components/TextField/TextField.tsx @@ -37,6 +37,14 @@ export interface TextFieldProps { * Mark as readonly */ readOnly?: boolean; + /** + * Name + */ + name?: string; + /** + * onChange + */ + onChange?: (event: any) => void; } const TextField: StatelessComponent = props => { From 7e081bbf078f7e4ad1717ccf6218209af780d220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Sun, 12 Aug 2018 23:48:49 -0300 Subject: [PATCH 18/18] Sign Up Form, Cross Validations for Username, Email, Password, and more added. --- src/core/client/auth/components/SignUp.tsx | 124 +++++++++++++++--- src/core/client/framework/lib/messages.tsx | 24 ++++ src/core/client/framework/lib/validation.tsx | 40 +++++- .../ui/components/TextField/TextField.tsx | 4 + 4 files changed, 170 insertions(+), 22 deletions(-) diff --git a/src/core/client/auth/components/SignUp.tsx b/src/core/client/auth/components/SignUp.tsx index 4428a8467..d4c8a7d55 100644 --- a/src/core/client/auth/components/SignUp.tsx +++ b/src/core/client/auth/components/SignUp.tsx @@ -2,7 +2,14 @@ import * as React from "react"; import { StatelessComponent } from "react"; import { Field, Form } from "react-final-form"; import { OnSubmit } from "talk-framework/lib/form"; -import { required } from "talk-framework/lib/validation"; +import { + composeValidators, + required, + validateEmail, + validateEqualPasswords, + validatePassword, + validateUsername, +} from "talk-framework/lib/validation"; import * as styles from "./SignUp.css"; import { @@ -12,6 +19,7 @@ import { InputLabel, TextField, Typography, + ValidationMessage, } from "talk-ui/components"; interface FormProps { @@ -36,7 +44,10 @@ const SignUp: StatelessComponent = props => { Sign up to join the conversation
- + {({ input, meta }) => ( Email Address @@ -46,29 +57,100 @@ const SignUp: StatelessComponent = props => { value={input.value} placeholder="Email Address" /> + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} )} - - Username - - A unique identifier displayed on your comments. You may use - “_” and “.” - - - - - Password - - Must be at least 8 characters - - - - - Confirm Password - - + + {({ input, meta }) => ( + + Username + + A unique identifier displayed on your comments. You may + use “_” and “.” + + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} + + + + {({ input, meta }) => ( + + Password + + Must be at least 8 characters + + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} + + + + {({ input, meta }) => ( + + Confirm Password + + Must be at least 8 characters + + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} +