<commit_before>import React from "react";
import ReactTestUtils from "react-addons-test-utils";
import Prefetch from "../../index.js"; // eslint-disable-line import/default

import Hello from "./fixtures/Hello.js";
import HelloES7 from "./fixtures/HelloES7.js";
import World from "./fixtures/World.js";

import * as stubs from "./fixtures/stubData.js";

/* eslint-disable max-nested-callbacks, react/no-multi-comp */
describe("react-wildcat-prefetch", () => {
    context("@prefetch", () => {
        context("plain React component", () => {
            it("has two properties", () => {
                const Component = ReactTestUtils.renderIntoDocument(<Hello title={"Test Title"}/>);
                expect(Object.keys(Component.props).length).to.equal(2);
            });

            it("has a static method", () => {
                expect(Hello.staticMethod).to.be.a("function");
                expect(Hello.staticMethod()).to.equal(42);
            });
        });

        context("higher-order component", () => {
            let WrappedPrefetch;

            context("es5", () => {
                beforeEach(() => {
                    WrappedPrefetch = Prefetch(stubs.fetchPromise)(World);
                });

                it("adds static methods to the component", () => {
                    expect(WrappedPrefetch.prefetch).to.exist;

                    expect(WrappedPrefetch.prefetch).to.respondTo("run");
                    expect(WrappedPrefetch.prefetch).to.respondTo("getKey");

                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("asyncData");

                    WrappedPrefetch = Prefetch(stubs.fetchPromise, "newkey")(World);
                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("newkey");
                });

                it("inherits static members", () => {
                    expect(WrappedPrefetch)
                        .itself.to.respondTo("staticMethod");

                    expect(WrappedPrefetch.staticMethod)
                        .to.be.a("function");

                    expect(WrappedPrefetch.staticMethod())
                        .to.equal(42);
                });
            });

            context("es6", () => {
                beforeEach(() => {
                    WrappedPrefetch = Prefetch(stubs.fetchPromise)(Hello);
                });

                it("adds static methods to the component", () => {
                    expect(WrappedPrefetch.prefetch).to.exist;

                    expect(WrappedPrefetch.prefetch).to.respondTo("run");
                    expect(WrappedPrefetch.prefetch).to.respondTo("getKey");

                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("asyncData");

                    WrappedPrefetch = Prefetch(stubs.fetchPromise, "newkey")(Hello);
                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("newkey");
                });

                it("inherits static members", () => {
                    expect(WrappedPrefetch)
                        .itself.to.respondTo("staticMethod");

                    expect(WrappedPrefetch.staticMethod)
                        .to.be.a("function");

                    expect(WrappedPrefetch.staticMethod())
                        .to.equal(42);
                });
            });

            context("es7", () => {
                beforeEach(() => {
                    WrappedPrefetch = Prefetch(stubs.fetchPromise)(HelloES7);
                });

                it("adds static methods to the component", () => {
                    expect(WrappedPrefetch.prefetch).to.exist;

                    expect(WrappedPrefetch.prefetch).to.respondTo("run");
                    expect(WrappedPrefetch.prefetch).to.respondTo("getKey");

                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("asyncData");

                    WrappedPrefetch = Prefetch(stubs.fetchPromise, "newkey")(Hello);
                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("newkey");
                });

                it("inherits static members", () => {
                    expect(WrappedPrefetch)
                        .itself.to.respondTo("staticMethod");

                    expect(WrappedPrefetch.staticMethod)
                        .to.be.a("function");

                    expect(WrappedPrefetch.staticMethod())
                        .to.equal(42);
                });
            });
        });
    });

    context("data fetching", () => {
        let WrappedPrefetch;

        beforeEach(() => {
            WrappedPrefetch = Prefetch(stubs.fetchPromise)(World);
        });

        context("happy path", () => {
            beforeEach(() => {
                sinon.stub(window, "fetch");

                var res = new window.Response(JSON.stringify(stubs.prefetchedData), {
                    status: 200,
                    headers: {
                        "Content-Type": "application/json"
                    }
                });

                window.fetch.returns(Promise.resolve(res));
            });

            it("fetches data using a Promise", (done) => {
                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                const runner = WrappedPrefetch.prefetch.run()
                    .then((response) => {
                        expect(response)
                            .to.be.an("object")
                            .that.equals(stubs.prefetchedData);

                        done();
                    });

                expect(runner)
                    .to.be.an.instanceof(Promise);
            });

            it("fetches data from a url", (done) => {
                WrappedPrefetch = Prefetch(stubs.prefetchUrl)(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                const runner = WrappedPrefetch.prefetch.run()
                    .then((response) => {
                        expect(response)
                            .to.be.an("object")
                            .that.has.keys(stubs.prefetchedData);

                        done();
                    });

                expect(runner)
                    .to.be.an.instanceof(Promise);
            });

            afterEach(() => {
                window.fetch.restore();
            });
        });

        context("sad path", () => {
            it("returns error payload on an invalid url", (done) => {
                WrappedPrefetch = Prefetch(stubs.prefetchInvalidUrl)(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                const runner = WrappedPrefetch.prefetch.run()
                    .then((response) => {
                        expect(response)
                            .to.be.an("object")
                            .that.has.property("error");

                        done();
                    });

                expect(runner)
                    .to.be.an.instanceof(Promise);
            });

            it("throws an invariant on an invalid configuration", () => {
                const stubErrorHandler = () => Prefetch(null)(World);
                expect(stubErrorHandler).to.throw(Error, /Invariant Violation/);
            });
        });

        it("exposes run static method", (done) => {
            expect(WrappedPrefetch.prefetch)
                .to.exist;

            expect(WrappedPrefetch.prefetch)
                .to.respondTo("run");

            const runner = WrappedPrefetch.prefetch.run()
                .then((response) => {
                    expect(response)
                        .to.be.an("object")
                        .that.equals(stubs.prefetchedData);

                    done();
                });

            expect(runner)
                .to.be.an.instanceof(Promise);
        });

        it("exposes getKey static method", () => {
            expect(WrappedPrefetch.prefetch)
                .to.exist;

            expect(WrappedPrefetch.prefetch)
                .to.respondTo("getKey");

            const key = WrappedPrefetch.prefetch.getKey();

            expect(key)
                .to.equal("asyncData");
        });

        context("unique key", () => {
            it("as string", () => {
                WrappedPrefetch = Prefetch(stubs.fetchPromise, stubs.prefetchedDataKey)(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("getKey");

                const key = WrappedPrefetch.prefetch.getKey();

                expect(key)
                    .to.equal(stubs.prefetchedDataKey);
            });

            it("as key / value", () => {
                WrappedPrefetch = Prefetch(stubs.fetchPromise, {
                    key: stubs.prefetchedDataKey
                })(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("getKey");

                const key = WrappedPrefetch.prefetch.getKey();

                expect(key)
                    .to.equal(stubs.prefetchedDataKey);
            });
        });
    });

    context("data hydration", () => {
        context("hydration", () => {
            before(() => {
                document.body.innerHTML = stubs.defaultTemplate({
                    data: stubs.prefetchedData,
                    head: {
                        title: "<title></title>",
                        meta: "",
                        link: ""
                    },
                    html: "",
                    wildcatConfig: stubs.wildcatConfig
                });

                window[stubs.__REACT_ROOT_ID__] = stubs.wildcatConfig.clientSettings.reactRootElementID;
                window[stubs.__INITIAL_DATA__] = stubs.prefetchedData;
            });

            it("hydrates React components with server data", (done) => {
                class WindowHydrationTest extends React.Component {
                    static propTypes = {
                        asyncData: React.PropTypes.object
                    }

                    static defaultProps = {
                        asyncData: {}
                    }

                    render() {
                        expect(this.props.asyncData)
                            .to.equal(stubs.prefetchedData.asyncData);

                        done();

                        return
{Object.keys(this.props)}
;
                    }
                }

                const WrappedPrefetch = Prefetch(stubs.fetchPromise)(WindowHydrationTest);
                ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
            });

            context("setting a custom key", () => {
                beforeEach(() => {
                    document.body.innerHTML = stubs.defaultTemplate({
                        data: stubs.prefetchedData,
                        head: {
                            title: "<title></title>",
                            meta: "",
                            link: ""
                        },
                        html: "",
                        wildcatConfig: stubs.wildcatConfig
                    });

                    window[stubs.__REACT_ROOT_ID__] = stubs.wildcatConfig.clientSettings.reactRootElementID;
                    window[stubs.__INITIAL_DATA__] = stubs.prefetchedDataCustomKey;
                });

                it("using a custom key as hash", (done) => {
                    class CustomKeyHydrationTest extends React.Component {
                        static propTypes = {
                            [stubs.prefetchedDataKey]: React.PropTypes.object
                        }

                        static defaultProps = {
                            [stubs.prefetchedDataKey]: {}
                        }

                        render() {
                            expect(this.props[stubs.prefetchedDataKey])
                                .to.equal(stubs.prefetchedDataCustomKey[stubs.prefetchedDataKey]);

                            done();

                            return
{Object.keys(this.props)}
;
                        }
                    }

                    const WrappedPrefetch = Prefetch(stubs.fetchPromiseCustomKey, {
                        key: stubs.prefetchedDataKey
                    })(CustomKeyHydrationTest);
                    ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
                });

                it("using a custom key as string", (done) => {
                    class CustomKeyHydrationTest extends React.Component {
                        static propTypes = {
                            [stubs.prefetchedDataKey]: React.PropTypes.object
                        }

                        static defaultProps = {
                            [stubs.prefetchedDataKey]: {}
                        }

                        render() {
                            expect(this.props[stubs.prefetchedDataKey])
                                .to.equal(stubs.prefetchedDataCustomKey[stubs.prefetchedDataKey]);

                            done();

                            return
{Object.keys(this.props)}
;
                        }
                    }

                    const WrappedPrefetch = Prefetch(stubs.fetchPromiseCustomKey, stubs.prefetchedDataKey)(CustomKeyHydrationTest);
                    ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
                });
            });

            it("hydrates React components with memory data", (done) => {
                class MemoryHydrationTest extends React.Component {
                    static propTypes = {
                        asyncData: React.PropTypes.object
                    }

                    static defaultProps = {
                        asyncData: {}
                    }

                    render() {
                        expect(this.props.asyncData)
                            .to.equal(stubs.prefetchedData.asyncData);

                        done();

                        return
{Object.keys(this.props)}
;
                    }
                }

                const WrappedPrefetch = Prefetch(stubs.fetchPromise)(MemoryHydrationTest);

                expect(WrappedPrefetch)
                    .to.have.property("prefetch");

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                WrappedPrefetch.prefetch.run()
                    .then(props => {
                        expect(WrappedPrefetch.prefetch)
                            .to.respondTo("getKey");

                        const key = WrappedPrefetch.prefetch.getKey();
                        WrappedPrefetch.prefetch[key] = props;

                        ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
                    });
            });

            after(() => {
                window[stubs.__INITIAL_DATA__] = null;
                delete window[stubs.__INITIAL_DATA__];
            });
        });

        context("rehydration", () => {
            it("rehydrates React components", (done) => {
                let renderCount = 1;

                class RehydrationTest extends React.Component {
                    static propTypes = {
                        asyncData: React.PropTypes.object
                    }

                    render() {
                        if (renderCount === 1) {
                            expect(this.props.asyncData)
                                .to.be.undefined;

                            renderCount += 1;
                        } else {
                            expect(this.props.asyncData)
                                .to.equal(stubs.prefetchedData.asyncData);

                            done();
                        }

                        return
{Object.keys(this.props)}
;
                    }
                }

                const WrappedPrefetch = Prefetch(stubs.fetchPromise)(RehydrationTest);
                ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
            });
        });
    });
});
<commit_msg>test(react-wildcat-prefetch): fix expectation<commit_after>import React from "react";
import ReactTestUtils from "react-addons-test-utils";
import Prefetch from "../../index.js"; // eslint-disable-line import/default

import Hello from "./fixtures/Hello.js";
import HelloES7 from "./fixtures/HelloES7.js";
import World from "./fixtures/World.js";

import * as stubs from "./fixtures/stubData.js";

/* eslint-disable max-nested-callbacks, react/no-multi-comp */
describe("react-wildcat-prefetch", () => {
    context("@prefetch", () => {
        context("plain React component", () => {
            it("has two properties", () => {
                const Component = ReactTestUtils.renderIntoDocument(<Hello title={"Test Title"}/>);
                expect(Object.keys(Component.props).length).to.equal(2);
            });

            it("has a static method", () => {
                expect(Hello.staticMethod).to.be.a("function");
                expect(Hello.staticMethod()).to.equal(42);
            });
        });

        context("higher-order component", () => {
            let WrappedPrefetch;

            context("es5", () => {
                beforeEach(() => {
                    WrappedPrefetch = Prefetch(stubs.fetchPromise)(World);
                });

                it("adds static methods to the component", () => {
                    expect(WrappedPrefetch.prefetch).to.exist;

                    expect(WrappedPrefetch.prefetch).to.respondTo("run");
                    expect(WrappedPrefetch.prefetch).to.respondTo("getKey");

                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("asyncData");

                    WrappedPrefetch = Prefetch(stubs.fetchPromise, "newkey")(World);
                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("newkey");
                });

                it("inherits static members", () => {
                    expect(WrappedPrefetch)
                        .itself.to.respondTo("staticMethod");

                    expect(WrappedPrefetch.staticMethod)
                        .to.be.a("function");

                    expect(WrappedPrefetch.staticMethod())
                        .to.equal(42);
                });
            });

            context("es6", () => {
                beforeEach(() => {
                    WrappedPrefetch = Prefetch(stubs.fetchPromise)(Hello);
                });

                it("adds static methods to the component", () => {
                    expect(WrappedPrefetch.prefetch).to.exist;

                    expect(WrappedPrefetch.prefetch).to.respondTo("run");
                    expect(WrappedPrefetch.prefetch).to.respondTo("getKey");

                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("asyncData");

                    WrappedPrefetch = Prefetch(stubs.fetchPromise, "newkey")(Hello);
                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("newkey");
                });

                it("inherits static members", () => {
                    expect(WrappedPrefetch)
                        .itself.to.respondTo("staticMethod");

                    expect(WrappedPrefetch.staticMethod)
                        .to.be.a("function");

                    expect(WrappedPrefetch.staticMethod())
                        .to.equal(42);
                });
            });

            context("es7", () => {
                beforeEach(() => {
                    WrappedPrefetch = Prefetch(stubs.fetchPromise)(HelloES7);
                });

                it("adds static methods to the component", () => {
                    expect(WrappedPrefetch.prefetch).to.exist;

                    expect(WrappedPrefetch.prefetch).to.respondTo("run");
                    expect(WrappedPrefetch.prefetch).to.respondTo("getKey");

                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("asyncData");

                    WrappedPrefetch = Prefetch(stubs.fetchPromise, "newkey")(Hello);
                    expect(WrappedPrefetch.prefetch.getKey()).to.equal("newkey");
                });

                it("inherits static members", () => {
                    expect(WrappedPrefetch)
                        .itself.to.respondTo("staticMethod");

                    expect(WrappedPrefetch.staticMethod)
                        .to.be.a("function");

                    expect(WrappedPrefetch.staticMethod())
                        .to.equal(42);
                });
            });
        });
    });

    context("data fetching", () => {
        let WrappedPrefetch;

        beforeEach(() => {
            WrappedPrefetch = Prefetch(stubs.fetchPromise)(World);
        });

        context("happy path", () => {
            beforeEach(() => {
                sinon.stub(window, "fetch");

                var res = new window.Response(JSON.stringify(stubs.prefetchedData), {
                    status: 200,
                    headers: {
                        "Content-Type": "application/json"
                    }
                });

                window.fetch.returns(Promise.resolve(res));
            });

            it("fetches data using a Promise", (done) => {
                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                const runner = WrappedPrefetch.prefetch.run()
                    .then((response) => {
                        expect(response)
                            .to.be.an("object")
                            .that.equals(stubs.prefetchedData);

                        done();
                    });

                expect(runner)
                    .to.be.an.instanceof(Promise);
            });

            it("fetches data from a url", (done) => {
                WrappedPrefetch = Prefetch(stubs.prefetchUrl)(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                const runner = WrappedPrefetch.prefetch.run()
                    .then((response) => {
                        expect(response)
                            .to.be.an("object")
                            .that.has.keys(stubs.prefetchedData);

                        done();
                    });

                expect(runner)
                    .to.be.an.instanceof(Promise);
            });

            afterEach(() => {
                window.fetch.restore();
            });
        });

        context("sad path", () => {
            it("returns error payload on an invalid url", (done) => {
                WrappedPrefetch = Prefetch(stubs.prefetchInvalidUrl)(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                const runner = WrappedPrefetch.prefetch.run()
                    .then((response) => {
                        expect(response)
                            .to.be.an("object")
                            .that.has.property("error");

                        done();
                    });

                expect(runner)
                    .to.be.an.instanceof(Promise);
            });

            it("throws an invariant on an invalid configuration", () => {
                const stubErrorHandler = () => Prefetch(null)(World);
                expect(stubErrorHandler).to.throw(Error, /Action must be typeof function or a string/);
            });
        });

        it("exposes run static method", (done) => {
            expect(WrappedPrefetch.prefetch)
                .to.exist;

            expect(WrappedPrefetch.prefetch)
                .to.respondTo("run");

            const runner = WrappedPrefetch.prefetch.run()
                .then((response) => {
                    expect(response)
                        .to.be.an("object")
                        .that.equals(stubs.prefetchedData);

                    done();
                });

            expect(runner)
                .to.be.an.instanceof(Promise);
        });

        it("exposes getKey static method", () => {
            expect(WrappedPrefetch.prefetch)
                .to.exist;

            expect(WrappedPrefetch.prefetch)
                .to.respondTo("getKey");

            const key = WrappedPrefetch.prefetch.getKey();

            expect(key)
                .to.equal("asyncData");
        });

        context("unique key", () => {
            it("as string", () => {
                WrappedPrefetch = Prefetch(stubs.fetchPromise, stubs.prefetchedDataKey)(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("getKey");

                const key = WrappedPrefetch.prefetch.getKey();

                expect(key)
                    .to.equal(stubs.prefetchedDataKey);
            });

            it("as key / value", () => {
                WrappedPrefetch = Prefetch(stubs.fetchPromise, {
                    key: stubs.prefetchedDataKey
                })(World);

                expect(WrappedPrefetch.prefetch)
                    .to.exist;

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("getKey");

                const key = WrappedPrefetch.prefetch.getKey();

                expect(key)
                    .to.equal(stubs.prefetchedDataKey);
            });
        });
    });

    context("data hydration", () => {
        context("hydration", () => {
            before(() => {
                document.body.innerHTML = stubs.defaultTemplate({
                    data: stubs.prefetchedData,
                    head: {
                        title: "<title></title>",
                        meta: "",
                        link: ""
                    },
                    html: "",
                    wildcatConfig: stubs.wildcatConfig
                });

                window[stubs.__REACT_ROOT_ID__] = stubs.wildcatConfig.clientSettings.reactRootElementID;
                window[stubs.__INITIAL_DATA__] = stubs.prefetchedData;
            });

            it("hydrates React components with server data", (done) => {
                class WindowHydrationTest extends React.Component {
                    static propTypes = {
                        asyncData: React.PropTypes.object
                    }

                    static defaultProps = {
                        asyncData: {}
                    }

                    render() {
                        expect(this.props.asyncData)
                            .to.equal(stubs.prefetchedData.asyncData);

                        done();

                        return
{Object.keys(this.props)}
;
                    }
                }

                const WrappedPrefetch = Prefetch(stubs.fetchPromise)(WindowHydrationTest);
                ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
            });

            context("setting a custom key", () => {
                beforeEach(() => {
                    document.body.innerHTML = stubs.defaultTemplate({
                        data: stubs.prefetchedData,
                        head: {
                            title: "<title></title>",
                            meta: "",
                            link: ""
                        },
                        html: "",
                        wildcatConfig: stubs.wildcatConfig
                    });

                    window[stubs.__REACT_ROOT_ID__] = stubs.wildcatConfig.clientSettings.reactRootElementID;
                    window[stubs.__INITIAL_DATA__] = stubs.prefetchedDataCustomKey;
                });

                it("using a custom key as hash", (done) => {
                    class CustomKeyHydrationTest extends React.Component {
                        static propTypes = {
                            [stubs.prefetchedDataKey]: React.PropTypes.object
                        }

                        static defaultProps = {
                            [stubs.prefetchedDataKey]: {}
                        }

                        render() {
                            expect(this.props[stubs.prefetchedDataKey])
                                .to.equal(stubs.prefetchedDataCustomKey[stubs.prefetchedDataKey]);

                            done();

                            return
{Object.keys(this.props)}
;
                        }
                    }

                    const WrappedPrefetch = Prefetch(stubs.fetchPromiseCustomKey, {
                        key: stubs.prefetchedDataKey
                    })(CustomKeyHydrationTest);
                    ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
                });

                it("using a custom key as string", (done) => {
                    class CustomKeyHydrationTest extends React.Component {
                        static propTypes = {
                            [stubs.prefetchedDataKey]: React.PropTypes.object
                        }

                        static defaultProps = {
                            [stubs.prefetchedDataKey]: {}
                        }

                        render() {
                            expect(this.props[stubs.prefetchedDataKey])
                                .to.equal(stubs.prefetchedDataCustomKey[stubs.prefetchedDataKey]);

                            done();

                            return
{Object.keys(this.props)}
;
                        }
                    }

                    const WrappedPrefetch = Prefetch(stubs.fetchPromiseCustomKey, stubs.prefetchedDataKey)(CustomKeyHydrationTest);
                    ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
                });
            });

            it("hydrates React components with memory data", (done) => {
                class MemoryHydrationTest extends React.Component {
                    static propTypes = {
                        asyncData: React.PropTypes.object
                    }

                    static defaultProps = {
                        asyncData: {}
                    }

                    render() {
                        expect(this.props.asyncData)
                            .to.equal(stubs.prefetchedData.asyncData);

                        done();

                        return
{Object.keys(this.props)}
;
                    }
                }

                const WrappedPrefetch = Prefetch(stubs.fetchPromise)(MemoryHydrationTest);

                expect(WrappedPrefetch)
                    .to.have.property("prefetch");

                expect(WrappedPrefetch.prefetch)
                    .to.respondTo("run");

                WrappedPrefetch.prefetch.run()
                    .then(props => {
                        expect(WrappedPrefetch.prefetch)
                            .to.respondTo("getKey");

                        const key = WrappedPrefetch.prefetch.getKey();
                        WrappedPrefetch.prefetch[key] = props;

                        ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
                    });
            });

            after(() => {
                window[stubs.__INITIAL_DATA__] = null;
                delete window[stubs.__INITIAL_DATA__];
            });
        });

        context("rehydration", () => {
            it("rehydrates React components", (done) => {
                let renderCount = 1;

                class RehydrationTest extends React.Component {
                    static propTypes = {
                        asyncData: React.PropTypes.object
                    }

                    render() {
                        if (renderCount === 1) {
                            expect(this.props.asyncData)
                                .to.be.undefined;

                            renderCount += 1;
                        } else {
                            expect(this.props.asyncData)
                                .to.equal(stubs.prefetchedData.asyncData);

                            done();
                        }

                        return
{Object.keys(this.props)}
;
                    }
                }

                const WrappedPrefetch = Prefetch(stubs.fetchPromise)(RehydrationTest);
                ReactTestUtils.renderIntoDocument(<WrappedPrefetch title={"Test Title"} />);
            });
        });
    });
});
<|endoftext|>


<commit_before>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = {};
  var filterOn = 'all';
  var selfMarker;

  var iconPath = '../www/img/icons/markers/';

  // TODO: add marker img for each category
  var markerImg = {
    'theft': 'theft.png',
    'assault': 'assult.png',
    'other': 'other.png'
  };

  var createMarker = function(crime) {

    if (markers[crime.id] === undefined) { // If crime isn't displayed yet add it
      var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

      var icon;

      if(markerImg[crime.type]){
        icon = iconPath + markerImg[crime.type];
      } else {
        icon = iconPath + markerImg.other;
      }

      var newMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: crime.category,
        icon: icon,
        id: crime.id,
        category: crime.category,
        date: crime.date,
        time: crime.time,
        description: crime.descript,
        type: crime.type.toLowerCase()
      });

      // Check if the marker should be displayed or not
      if (filterOn === 'all' || filterOn === crime.type) {
        newMarker.setMap(map);
      }
      // Make a new InfoWindow and associate it to the marker
      // *** note infobox can be used as well for more styling ***
      newMarker.info = new google.maps.InfoWindow({
        content: '
' + newMarker.description + '
',
        maxWidth: 100
      });
      // Add the map listener here
      google.maps.event.addListener(newMarker, 'mouseover', function(){
        // Close all open crime info windows first
        for (var crimeID in markers) {
          markers[crimeID].info.close();
        }
        // Open the pertinent info window
        newMarker.info.open(map, newMarker);
      });
      markers[crime.id] = newMarker; // Add it to the markers object
    }
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        streetViewControl: false,
        overviewMapControl: false,
        scrollwheel: false
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
      for(var i = 0; i < crimes.length; i++){
        createMarker(crimes[i]);
      }
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // Returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    setSelf: function(lat, lng){

      var latlng = new google.maps.LatLng(lat, lng);
      var icon = iconPath +'selfpin.png';

      selfMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: 'You Are Here',
        icon: icon
      });

      selfMarker.setMap(map);

      selfMarker.info = new google.maps.InfoWindow({
        content: '
You Are Here
',
        maxWidth: 100
      });

      google.maps.event.addListener(newMarker, 'mouseover', function(){
        // Open the pertinent info window
        selfMarker.info.open(map, selfMarker);
      });

    },

    filterBy: function(filter){
      filterOn = filter;
      // The filter will match the type field on the markers
      for (var markerID in markers){

        var marker = markers[markerID];
        var cat = marker.type;

        // Check if the filter is all, if so, show all markers
        if (filter === 'all') {
          marker.setMap(map);
        } else { // A filter was specified
          if (filter === cat) {
            marker.setMap(map);
          } else {
            marker.setMap(null);
          }
        }
      }
    }
  };
})

.factory('loaderService', function($rootScope, $ionicLoading) {
  return {
    show : function() {
      $ionicLoading.show({

        // The text to display in the loading indicator
        content: ' Loading',

        // The animation to use
        animation: 'fade-in',

        // Will a dark overlay or backdrop cover the entire view
        showBackdrop: true,

        // The maximum width of the loading indicator
        // Text will be wrapped if longer than maxWidth
        maxWidth: 200,

        // The delay in showing the indicator
        showDelay: 10
      });
    },

    hide : function(){
      $ionicLoading.hide();
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps, loaderService){

  // add an event listener to update the map location on resume
  document.addEventListener("resume", function(){$scope.resume();}, false);

  $scope.filters = ['other', 'assault', 'theft'];
  $scope.searchClear = true;

  var hideKeyboard = function() {
    document.activeElement.blur();
    $("input").blur();
  };

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);
    $scope.gpsSearchCrime();

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // Get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });

    $scope.trackLocation(pushAlert);
  };

  $scope.resume = function() {
    $scope.gpsSearchCrime();
  };

  $scope.gpsSearchCrime = function() {

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      // display self marker
      googleMaps.setSelf(lat, lng);
      // display crimes
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng, cb){

    loaderService.show();

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      headers: {
      "Authorization" : "Basic " + btoa("sf-sense:858F8CDDB1F324A762DBEFDC77844")
      },
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      if (!cb){
        googleMaps.createMarkers(response);
        loaderService.hide();
      } else {
        cb(response);
      }
    }).error(function(error){
      loaderService.hide();
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // On success, calls getCrimes with the lat/lng
    // If map search if undefined use current location. Placeholder is current location.
    if(!$scope.mapSearch) {
      $scope.gpsSearchCrime();
    } else {
      googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
    }

    searchHide();
  };

  $scope.filterBy = function (filterArg) {
    filterArg = filterArg || 'all';
    googleMaps.filterBy(filterArg);
  };

  var pushAlert = function(incidents) {

    var alertMessage = function(incidentsOcc) {
      if (incidentsOcc.assault > 1 && incidentsOcc.theft > 2) {
        return "Warning! You are entering an area where assaults and thefts have been reported";
      } else if (incidentsOcc.assault > 1) {
        return "Warning! You are entering an area where assaults have been reported";
      } else if (incidentsOcc.theft > 2) {
        return "Warning! You are entering an area where thefts have been reported";
      }
    };

    var incidentsOcc = {
      assault : 0,
      theft : 0,
      other : 0
    };

    for (var i = 0; i < incidents.length; i++) {
      incidentsOcc[incidents[i].type]++;
    }

    if (incidentsOcc.assault > 1 || incidentsOcc.theft > 2) {
      window.plugin.notification.local.add({ message: alertMessage(incidentsOcc) });
    }
  };

  $scope.trackLocation = function(onSuccessCallback) {
    var bgGeo = window.plugins.backgroundGeoLocation;

    var onSuccess = function(pos) {
      var lat = pos.latitude;
      var lng = pos.longitude;

      $scope.getCrimes(lat, lng, function(crimes){
        onSuccessCallback(crimes);
      });
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    bgGeo.configure(onSuccess, onError, {
      desiredAccuracy: 1,
      stationaryRadius: 1,
      distanceFilter: 1,
      // debug: true // <-- enable this hear sounds for background-geolocation life-cycle.
    });

    bgGeo.start();
  };

  $scope.onFocusSearch = function(){
    $scope.searchClear = false;
  };

  $scope.clearSearch = function(){
    $scope.mapSearch = '';
  };

  var searchHide = function(){
    $scope.searchClear = true;
    hideKeyboard();
  };

  $scope.cancelSearch = function(){
    searchHide();
    hideKeyboard();
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<commit_msg>Removes old selfMarkers before making new one<commit_after>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = {};
  var filterOn = 'all';
  var selfMarker;

  var iconPath = '../www/img/icons/markers/';

  // TODO: add marker img for each category
  var markerImg = {
    'theft': 'theft.png',
    'assault': 'assult.png',
    'other': 'other.png'
  };

  var createMarker = function(crime) {

    if (markers[crime.id] === undefined) { // If crime isn't displayed yet add it
      var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

      var icon;

      if(markerImg[crime.type]){
        icon = iconPath + markerImg[crime.type];
      } else {
        icon = iconPath + markerImg.other;
      }

      var newMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: crime.category,
        icon: icon,
        id: crime.id,
        category: crime.category,
        date: crime.date,
        time: crime.time,
        description: crime.descript,
        type: crime.type.toLowerCase()
      });

      // Check if the marker should be displayed or not
      if (filterOn === 'all' || filterOn === crime.type) {
        newMarker.setMap(map);
      }
      // Make a new InfoWindow and associate it to the marker
      // *** note infobox can be used as well for more styling ***
      newMarker.info = new google.maps.InfoWindow({
        content: '
' + newMarker.description + '
',
        maxWidth: 100
      });
      // Add the map listener here
      google.maps.event.addListener(newMarker, 'mouseover', function(){
        // Close all open crime info windows first
        for (var crimeID in markers) {
          markers[crimeID].info.close();
        }
        // Open the pertinent info window
        newMarker.info.open(map, newMarker);
      });
      markers[crime.id] = newMarker; // Add it to the markers object
    }
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        streetViewControl: false,
        overviewMapControl: false,
        scrollwheel: false
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
      for(var i = 0; i < crimes.length; i++){
        createMarker(crimes[i]);
      }
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // Returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    setSelf: function(lat, lng){

      // remove old selfMarker if it exists
      if (selfMarker.setMap) {
        selfMarker.setMap(null);
      }
      selfMarker = null;

      var latlng = new google.maps.LatLng(lat, lng);
      var icon = iconPath +'selfpin.png';

      selfMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: 'You Are Here',
        icon: icon
      });

      selfMarker.setMap(map);

      selfMarker.info = new google.maps.InfoWindow({
        content: '
You Are Here
',
        maxWidth: 100
      });

      google.maps.event.addListener(newMarker, 'mouseover', function(){
        // Open the pertinent info window
        selfMarker.info.open(map, selfMarker);
      });

    },

    filterBy: function(filter){
      filterOn = filter;
      // The filter will match the type field on the markers
      for (var markerID in markers){

        var marker = markers[markerID];
        var cat = marker.type;

        // Check if the filter is all, if so, show all markers
        if (filter === 'all') {
          marker.setMap(map);
        } else { // A filter was specified
          if (filter === cat) {
            marker.setMap(map);
          } else {
            marker.setMap(null);
          }
        }
      }
    }
  };
})

.factory('loaderService', function($rootScope, $ionicLoading) {
  return {
    show : function() {
      $ionicLoading.show({

        // The text to display in the loading indicator
        content: ' Loading',

        // The animation to use
        animation: 'fade-in',

        // Will a dark overlay or backdrop cover the entire view
        showBackdrop: true,

        // The maximum width of the loading indicator
        // Text will be wrapped if longer than maxWidth
        maxWidth: 200,

        // The delay in showing the indicator
        showDelay: 10
      });
    },

    hide : function(){
      $ionicLoading.hide();
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps, loaderService){

  // add an event listener to update the map location on resume
  document.addEventListener("resume", function(){$scope.resume();}, false);

  $scope.filters = ['other', 'assault', 'theft'];
  $scope.searchClear = true;

  var hideKeyboard = function() {
    document.activeElement.blur();
    $("input").blur();
  };

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);
    $scope.gpsSearchCrime();

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // Get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });

    $scope.trackLocation(pushAlert);
  };

  $scope.resume = function() {
    $scope.gpsSearchCrime();
  };

  $scope.gpsSearchCrime = function() {

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      // display self marker
      googleMaps.setSelf(lat, lng);
      // display crimes
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng, cb){

    loaderService.show();

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      headers: {
      "Authorization" : "Basic " + btoa("sf-sense:858F8CDDB1F324A762DBEFDC77844")
      },
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      if (!cb){
        googleMaps.createMarkers(response);
        loaderService.hide();
      } else {
        cb(response);
      }
    }).error(function(error){
      loaderService.hide();
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // On success, calls getCrimes with the lat/lng
    // If map search if undefined use current location. Placeholder is current location.
    if(!$scope.mapSearch) {
      $scope.gpsSearchCrime();
    } else {
      googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
    }

    searchHide();
  };

  $scope.filterBy = function (filterArg) {
    filterArg = filterArg || 'all';
    googleMaps.filterBy(filterArg);
  };

  var pushAlert = function(incidents) {

    var alertMessage = function(incidentsOcc) {
      if (incidentsOcc.assault > 1 && incidentsOcc.theft > 2) {
        return "Warning! You are entering an area where assaults and thefts have been reported";
      } else if (incidentsOcc.assault > 1) {
        return "Warning! You are entering an area where assaults have been reported";
      } else if (incidentsOcc.theft > 2) {
        return "Warning! You are entering an area where thefts have been reported";
      }
    };

    var incidentsOcc = {
      assault : 0,
      theft : 0,
      other : 0
    };

    for (var i = 0; i < incidents.length; i++) {
      incidentsOcc[incidents[i].type]++;
    }

    if (incidentsOcc.assault > 1 || incidentsOcc.theft > 2) {
      window.plugin.notification.local.add({ message: alertMessage(incidentsOcc) });
    }
  };

  $scope.trackLocation = function(onSuccessCallback) {
    var bgGeo = window.plugins.backgroundGeoLocation;

    var onSuccess = function(pos) {
      var lat = pos.latitude;
      var lng = pos.longitude;

      $scope.getCrimes(lat, lng, function(crimes){
        onSuccessCallback(crimes);
      });
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    bgGeo.configure(onSuccess, onError, {
      desiredAccuracy: 1,
      stationaryRadius: 1,
      distanceFilter: 1,
      // debug: true // <-- enable this hear sounds for background-geolocation life-cycle.
    });

    bgGeo.start();
  };

  $scope.onFocusSearch = function(){
    $scope.searchClear = false;
  };

  $scope.clearSearch = function(){
    $scope.mapSearch = '';
  };

  var searchHide = function(){
    $scope.searchClear = true;
    hideKeyboard();
  };

  $scope.cancelSearch = function(){
    searchHide();
    hideKeyboard();
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<|endoftext|>


<commit_before>var
  dummy

, hotplate =  require('hotplate')
, path = require('path')

, Store = require('jsonreststores-mongo')

, async = require('async')
, util = require('util')
, mongoWrapper = require('mongowrapper')
, db = hotplate.get('db')
, declare = require( 'simpledeclare' )

, ObjectId = mongoWrapper.ObjectId
, Schema = Store.Schema
;

app = hotplate.app;

exports.hotHooks = hooks = {}

hooks.creatingUser = function( done, u, body ){

  var userConfig = {};
  userConfig.email = u.registerEmail;
  userConfig.name = body.name;
  userConfig.surname = body.surname;
  userConfig._id = u._id;

  var userConfigCollection = db.collection('userConfig');

  console.log( userConfig );
  userConfigCollection.insert( userConfig, done );

}

hooks.creatingWorkspace = function( done, u, w ){

  var accessConfig = {};

  accessConfig._id = u._id;
  accessConfig.workspaceId = w._id;
  accessConfig.localEmail = u.registerEmail;
  // ...

  db.collection('accessConfig').insert( accessConfig, function( err ){

    if( err ){
      done( err );
    } else {

      var workspaceConfig = {};
      workspaceConfig.tag = "Your tagline here";
      workspaceConfig.longName = "Your workspace's description here";
      workspaceConfig._id = w._id;

      db.collection('workspaceConfig').insert( workspaceConfig, done );
    }
  })
}

hooks.createWorkspaceAnonSchema = function( done, schema ){

  schema.structure.name    = { type: 'string', notEmpty: true, required: true, trim: 45 };
  schema.structure.surname = { type: 'string', notEmpty: true, required: true, trim: 60 };

  done( null );
}

hooks.init = function( done ){
  done( null );
}

hooks.run = function( done ){

  var resUtils = hotplate.getModule('hotCoreResUtils');
  var messages = hotplate.getModule('hotMongoCometMessages');
  var sharedCode = hotplate.getModule('hotCoreSharedCode');
  var hotCoreJsonRestStores = hotplate.getModule('hotCoreJsonRestStores');

  // Add the db property to the mixin
  hotCoreJsonRestStores.StoreMixin.db = db;

  // Mixin the extra hotplate-specific methods and attributes to
  // the picked JsonRest Stores
  var HotStore = declare( Store, hotCoreJsonRestStores.StoreMixin );
  var HotSchema = declare( Store.Schema, hotCoreJsonRestStores.SchemaMixin );
  HotStore.Schema = HotSchema;

  var Categories = declare( HotStore, {

    // COMMON
    schema: new Schema({
      name    : { type: 'string', searchable: true, searchPartial: true, sortable: true, notEmpty: true, trim: 50 },
    }),

    handlePut: true,
    handlePost: true,
    handleGet: true,
    handleGetQuery: true,
    handleDelete: true,

    storeName:  'categories',
    paramIds: [ 'workspaceId', '_id' ],
    // queryFilterType: '$or',
    // cometGroup: ['one', 'two', 'three' ],

  });

  Categories.make.All( app, '/call/:workspaceId/Categories/', ':_id', Categories );

  /* ****************************************************************** */
  /* ****************************************************************** */
  /* ****************************************************************** */

  var UserConfig = declare( HotStore, {

    // COMMON
    schema: new Schema({
      email   : { type: 'string', notEmpty: true, sharedValidator: 'email', trim: 70, min: 4 },
      surname : { type: 'string', notEmpty: true, trim: 10 },
      name    : { type: 'string', notEmpty: true, trim: 50 },
    },
    {
      validate: function( schema, errors, cb ){
        if( this.name == 'Tony' ){
          cb( new Error("NO, TONY NO!" ) );
        } else {
          cb( null );
        }
      },

    } ),

    handlePut: true,
    handleGet: true,

    collectionName: 'userConfig',

    storeName:  'userConfig',
    paramIds: [ 'workspaceId', '_id' ],
    ignoreIds: [ 'workspaceId' ],

    // Permissions for the get
    checkPermissionsGet: function( req, doc, fullDoc, cb ) {
      cb( null, req.application.workspace.access.filter( function(o){ return o._id.toString() === doc._id.toString(); } ).length  );
    },

    // Permissions to save data
    checkPermissionsPutExisting: function( req, doc, fullDoc, cb ) {
      // TODO: implement this
      cb( null, true );
    },

    // Nobody cannnot create new records -- they need to exist beforehand
    checkPermissionsPutNew: function( req, cb){  cb( null, false );  },
  });

  Store.make.All( app, '/call/:workspaceId/userConfig/', ':_id', UserConfig );

  var UserConfigNoWorkspace = declare( UserConfig, {

    // Redefine the permission calls
    checkPermissionsGet: function(  req, doc, fullDoc, cb ){
      cb( null,  req.session.userId.toString() == req.params.userId );
    },
    checkPermissionsPutExisting: function( req, doc, fullDoc, cb ) {
      cb( null, ! req.session.userId.toString() == doc._id.toString() );
    },

    killComet: true,
  });

  Store.make.All( app, '/call/userConfigNoWorkspace/', ':_id', UserConfigNoWorkspace );

  var WorkspaceConfig = declare( HotStore, {

    schema: new Schema({
      longName: { type: 'string', notEmpty: true, trim: 35 },
      tag     : { type: 'string', notEmpty: true, notEmpty: true, trim: 70 },
    }),
    storeName:  'workspaceConfig',
    paramIds: [ 'workspaceId', '_id' ],
    ignoreIds: [ 'workspaceId' ],

    handlePut: true,
    handleGet: true,

    checkPermissionsGet: function(  req, doc, fullDoc, cb ){
      cb( null, true );
      // cb( null, resUtils.currentUserInWorkspaceAccess( req, fullDoc ) );
    },

    checkPermissionsPutExisting: function( req, doc, fullDoc, cb ) {
      cb( null, true );
      // cb( null, resUtils.currentUserInWorkspaceAccess( req, fullDoc ) );
    },

    // Nobody cannnot create new records -- they need to exist beforehand
    checkPermissionsPutNew: function( req, cb){  cb( null, false );  },

  });

  Store.make.All( app, '/call/:workspaceId/workspaceConfig/', ':_id', WorkspaceConfig );

  var AccessConfig = declare( HotStore, {

    // COMMON

    schema: new Schema({
      localEmail: { type: 'string', notEmpty: true, trim: 35 },
    }),

    storeName: 'accessConfig',
    paramIds: [ 'workspaceId', '_id' ],

    handlePut: true,
    handleGet: true,

    // checkPermissionsGet:function( req, doc, fullDoc, cb ) {
    //   cb( null, true );
    // },

    // checkPermissionsPutExisting:function( req, doc, fullDoc, cb ) {
    //   cb( null, req.application.user._id.toString() == doc._id.toString() );
    // },

  } );

  Store.make.All( app, '/call/:workspaceId/accessConfig/', ':_id', AccessConfig );

  done( null );
}

hooks.pageElementsPerPage = function( done, elements, req, pageName ){

  switch(pageName){

    case 'hotDojoAppContainer/container':

      var userConfig, accessConfig, workspaceConfig;

      db.collection('userConfig').findOne( { _id: req.application.user._id }, function( err, doc ){

        if( err ) {
          done( err );
        } else {
          userConfig = doc;

          db.collection('workspaceConfig').findOne( { _id: req.application.workspace._id }, function( err, doc ){
            if( err ) {
              done( err );
            } else {
              workspaceConfig = doc;

              db.collection('accessConfig').findOne( { _id: req.application.user._id, workspaceId: req.application.workspace._id }, function( err, doc ){
                if( err ) {
                  done( err );
                } else {

                  accessConfig        = doc;

                  // Sending the page out
                  done( null, {
                    moduleName: 'bd', result: {
                      jses:  ['bdMain.js', 'jade.js' ],
                      csses: ['bdMain.css' ],
                      vars: [
                        { name: 'userConfig',      value: userConfig },
                        { name: 'accessConfig',    value: accessConfig },
                        { name: 'workspaceConfig', value: workspaceConfig }
                      ],
                    }
                  });
                }
              })

            };
          })
        }

      });

   break;

    // Add an extra div to the "No workspaces to pick!" page, so that
    // a user can click on their config if they like (they are logged in after all)
    case 'hotDojoAuth/pickButEmptyPage':

      done( null, {
               moduleName: 'bd', result: {
                 body: elements.body.replace('
', '

'),
                 jses: ['mainPickEnrich.js', 'jade.js'],
              }
      });
    break;

    case 'hotDojoAuth/registerPage':
      done( null, {
               moduleName: 'bd', result: {
                 jses: ['mainChangeRegisterForm.js'],
              }
      });
    break;

    default:
      done( null, { moduleName: 'bd', result: {} }  );
    break;
  }
}

// Simply activate path to client files
hooks.clientPaths = function( done ){
  done( null, { moduleName: 'bd', result: [ path.join(__dirname, '../client') ] } );
}

hooks.stores = function( done ){
  done( null, {
    accessConfig         : { target: '/call/:workspaceId/accessConfig/',    idProperty: '_id', sortParam: 'sortBy', },
    workspaceConfig      : { target: '/call/:workspaceId/workspaceConfig/', idProperty: '_id', sortParam: 'sortBy', },
    userConfig           : { target: '/call/:workspaceId/userConfig/',      idProperty: '_id', sortParam: 'sortBy', },
    userConfigNoWorkspace: { target: '/call/userConfigNoWorkspace/',        idProperty: '_id', sortParam: 'sortBy', },
    options              : { target: '/call/:workspaceId/Options/',         idProperty: '_id', sortParam: 'sortBy', },
    categories           : { target: '/call/:workspaceId/Categories/',      idProperty: '_id', sortParam: 'sortBy', },
  });
}

hooks.sharedFunctions = function( done ) {
  var result = {};
  done( null, { moduleName: 'bd', result: result } );
}

/*
  var OptionsStore = declare( Store,  {
    storeName: 'options',
    db: db,
    schema: new Schema({
      _id   : { type: 'id', required: true },

      name  : { type: 'string', notEmpty: true, trim: 50, searchable: true, sortable: true, searchPartial: true },
      age   : { type: 'number', notEmpty: true , searchable: true, sortable: true },
    }),

    paramIds: [ 'optionId' ],
    handleGet: true,
    handleGetQuery: true,
    handlePut: true,
    handlePost: true,

    allDbExtrapolateDoc: function( fullDoc, res, cb ){
      var d = {};
      d.name = fullDoc.name;
      d._id = fullDoc._id;
      cb( null, d );
    },
    getDbPrepareBeforeSend: (function(){
      var i = 0;

      return function( doc, cb ){
        doc.CAZ = i ++;
        cb( null, doc )
      }
    })(),
  });

  // app.get( '/call/:workspaceId/Options/:optionId', JsonRestStores.Store.makeGet( OptionsStore ) );

  Store.make.All( app,  '/call/:workspaceId/Options/', ':optionId', OptionsStore );
  */

<commit_msg>Using latest stores<commit_after>var
  dummy

, hotplate =  require('hotplate')
, path = require('path')

, Store = require('jsonreststores-mongo')

, async = require('async')
, util = require('util')
, mongoWrapper = require('mongowrapper')
, db = hotplate.get('db')
, declare = require( 'simpledeclare' )

, ObjectId = mongoWrapper.ObjectId
, Schema = Store.Schema
;

app = hotplate.app;

exports.hotHooks = hooks = {}

hooks.creatingUser = function( done, u, body ){

  var userConfig = {};
  userConfig.email = u.registerEmail;
  userConfig.name = body.name;
  userConfig.surname = body.surname;
  userConfig._id = u._id;

  var userConfigCollection = db.collection('userConfig');

  userConfigCollection.insert( userConfig, done );

}

hooks.creatingWorkspace = function( done, u, w ){

  var accessConfig = {};

  accessConfig._id = u._id;
  accessConfig.workspaceId = w._id;
  accessConfig.localEmail = u.registerEmail;
  // ...

  db.collection('accessConfig').insert( accessConfig, function( err ){

    if( err ){
      done( err );
    } else {

      var workspaceConfig = {};
      workspaceConfig.tag = "Your tagline here";
      workspaceConfig.longName = "Your workspace's description here";
      workspaceConfig._id = w._id;

      db.collection('workspaceConfig').insert( workspaceConfig, done );
    }
  })
}

hooks.createWorkspaceAnonSchema = function( done, schema ){

  schema.structure.name    = { type: 'string', notEmpty: true, required: true, trim: 45 };
  schema.structure.surname = { type: 'string', notEmpty: true, required: true, trim: 60 };

  done( null );
}

hooks.init = function( done ){
  done( null );
}

hooks.run = function( done ){

  var resUtils = hotplate.getModule('hotCoreResUtils');
  var messages = hotplate.getModule('hotMongoCometMessages');
  var sharedCode = hotplate.getModule('hotCoreSharedCode');
  var hotCoreJsonRestStores = hotplate.getModule('hotCoreJsonRestStores');

  // Add the db property to the mixin
  hotCoreJsonRestStores.StoreMixin.db = db;

  // Mixin the extra hotplate-specific methods and attributes to
  // the picked JsonRest Stores
  var HotStore = declare( Store, hotCoreJsonRestStores.StoreMixin );
  var HotSchema = declare( Store.Schema, hotCoreJsonRestStores.SchemaMixin );
  HotStore.Schema = HotSchema;

  var Categories = declare( HotStore, {

    // COMMON
    schema: new Schema({
      name    : { type: 'string', searchable: true, searchPartial: true, sortable: true, notEmpty: true, trim: 50 },

      _id     : { type: 'string', isRequired: true, searchable: true },
    }),

    allDbMakeId: function( object, done ){
      done( null, object.name + "_KEY" );
    },

    handlePut: true,
    handlePost: true,
    handleGet: true,
    handleGetQuery: true,
    handleDelete: true,

    storeName:  'categories',
    paramIds: [ 'workspaceId', '_id' ],
    // queryFilterType: '$or',
    // cometGroup: ['one', 'two', 'three' ],

  });

  Categories.make.All( app, '/call/:workspaceId/Categories/', ':_id', Categories );

  /* ****************************************************************** */
  /* ****************************************************************** */
  /* ****************************************************************** */

  var UserConfig = declare( HotStore, {

    // COMMON
    schema: new Schema({
      email   : { type: 'string', notEmpty: true, sharedValidator: 'email', trim: 70, min: 4 },
      surname : { type: 'string', notEmpty: true, trim: 10 },
      name    : { type: 'string', notEmpty: true, trim: 50 },
    },
    {
      validate: function( schema, errors, cb ){
        if( this.name == 'Tony' ){
          cb( new Error("NO, TONY NO!" ) );
        } else {
          cb( null );
        }
      },

    } ),

    handlePut: true,
    handleGet: true,

    collectionName: 'userConfig',

    storeName:  'userConfig',
    paramIds:  [ 'workspaceId', '_id' ],
    ignoreIds: [ 'workspaceId' ],

    // Permissions for the get
    checkPermissionsGet: function( req, doc, fullDoc, cb ) {
      cb( null, req.application.workspace.access.filter( function(o){ return o._id.toString() === doc._id.toString(); } ).length  );
    },

    // Permissions to save data
    checkPermissionsPutExisting: function( req, doc, fullDoc, cb ) {
      // TODO: implement this
      cb( null, true );
    },

    // Nobody cannnot create new records -- they need to exist beforehand
    checkPermissionsPutNew: function( req, cb){  cb( null, false );  },
  });

  Store.make.All( app, '/call/:workspaceId/userConfig/', ':_id', UserConfig );

  var UserConfigNoWorkspace = declare( UserConfig, {

    // COMMON
    schema: new Schema({
      email   : { type: 'string', notEmpty: true, sharedValidator: 'email', trim: 70, min: 4 },
      surname : { type: 'string', notEmpty: true, trim: 10 },
      name    : { type: 'string', notEmpty: true, trim: 50 },
    }),

    paramIds: [ '_id' ],

    // Redefine the permission calls
    checkPermissionsGet: function(  req, doc, fullDoc, cb ){
      cb( null,  req.session.userId.toString() == req.params._id );
    },
    checkPermissionsPutExisting: function( req, doc, fullDoc, cb ) {
      cb( null, req.session.userId.toString() == doc._id.toString() );
    },

    killComet: true,
  });

  Store.make.All( app, '/call/userConfigNoWorkspace/', ':_id', UserConfigNoWorkspace );

  var WorkspaceConfig = declare( HotStore, {

    schema: new Schema({
      longName: { type: 'string', notEmpty: true, trim: 35 },
      tag     : { type: 'string', notEmpty: true, notEmpty: true, trim: 70 },
    }),
    storeName:  'workspaceConfig',
    paramIds: [ 'workspaceId', '_id' ],
    ignoreIds: [ 'workspaceId' ],

    handlePut: true,
    handleGet: true,

    checkPermissionsGet: function(  req, doc, fullDoc, cb ){
      cb( null, true );
      // cb( null, resUtils.currentUserInWorkspaceAccess( req, fullDoc ) );
    },

    checkPermissionsPutExisting: function( req, doc, fullDoc, cb ) {
      cb( null, true );
      // cb( null, resUtils.currentUserInWorkspaceAccess( req, fullDoc ) );
    },

    // Nobody cannnot create new records -- they need to exist beforehand
    checkPermissionsPutNew: function( req, cb){  cb( null, false );  },

  });

  Store.make.All( app, '/call/:workspaceId/workspaceConfig/', ':_id', WorkspaceConfig );

  var AccessConfig = declare( HotStore, {

    // COMMON

    schema: new Schema({
      localEmail: { type: 'string', notEmpty: true, trim: 35 },
    }),

    storeName: 'accessConfig',
    paramIds: [ 'workspaceId', '_id' ],

    handlePut: true,
    handleGet: true,

    // checkPermissionsGet:function( req, doc, fullDoc, cb ) {
    //   cb( null, true );
    // },

    // checkPermissionsPutExisting:function( req, doc, fullDoc, cb ) {
    //   cb( null, req.application.user._id.toString() == doc._id.toString() );
    // },

  } );

  Store.make.All( app, '/call/:workspaceId/accessConfig/', ':_id', AccessConfig );

  done( null );
}

hooks.pageElementsPerPage = function( done, elements, req, pageName ){

  switch(pageName){

    case 'hotDojoAppContainer/container':

      var userConfig, accessConfig, workspaceConfig;

      db.collection('userConfig').findOne( { _id: req.application.user._id }, function( err, doc ){

        if( err ) {
          done( err );
        } else {
          userConfig = doc;

          db.collection('workspaceConfig').findOne( { _id: req.application.workspace._id }, function( err, doc ){
            if( err ) {
              done( err );
            } else {
              workspaceConfig = doc;

              db.collection('accessConfig').findOne( { _id: req.application.user._id, workspaceId: req.application.workspace._id }, function( err, doc ){
                if( err ) {
                  done( err );
                } else {

                  accessConfig        = doc;

                  // Sending the page out
                  done( null, {
                    moduleName: 'bd', result: {
                      jses:  ['bdMain.js', 'jade.js' ],
                      csses: ['bdMain.css' ],
                      vars: [
                        { name: 'userConfig',      value: userConfig },
                        { name: 'accessConfig',    value: accessConfig },
                        { name: 'workspaceConfig', value: workspaceConfig }
                      ],
                    }
                  });
                }
              })

            };
          })
        }

      });

   break;

    // Add an extra div to the "No workspaces to pick!" page, so that
    // a user can click on their config if they like (they are logged in after all)
    case 'hotDojoAuth/pickButEmptyPage':

      done( null, {
               moduleName: 'bd', result: {
                 body: elements.body.replace('
', '

'),
                 jses: ['mainPickEnrich.js', 'jade.js'],
              }
      });
    break;

    case 'hotDojoAuth/registerPage':
      done( null, {
               moduleName: 'bd', result: {
                 jses: ['mainChangeRegisterForm.js'],
              }
      });
    break;

    default:
      done( null, { moduleName: 'bd', result: {} }  );
    break;
  }
}

// Simply activate path to client files
hooks.clientPaths = function( done ){
  done( null, { moduleName: 'bd', result: [ path.join(__dirname, '../client') ] } );
}

hooks.stores = function( done ){
  done( null, {
    accessConfig         : { target: '/call/:workspaceId/accessConfig/',    idProperty: '_id', sortParam: 'sortBy', },
    workspaceConfig      : { target: '/call/:workspaceId/workspaceConfig/', idProperty: '_id', sortParam: 'sortBy', },
    userConfig           : { target: '/call/:workspaceId/userConfig/',      idProperty: '_id', sortParam: 'sortBy', },
    userConfigNoWorkspace: { target: '/call/userConfigNoWorkspace/',        idProperty: '_id', sortParam: 'sortBy', },
    options              : { target: '/call/:workspaceId/Options/',         idProperty: '_id', sortParam: 'sortBy', },
    categories           : { target: '/call/:workspaceId/Categories/',      idProperty: '_id', sortParam: 'sortBy', },
  });
}

hooks.sharedFunctions = function( done ) {
  var result = {};
  done( null, { moduleName: 'bd', result: result } );
}

<|endoftext|>


<commit_before>import AccountViewContainer from './views/AccountViewContainer'
import { fetchRooms } from 'store/modules/rooms'
import { fetchPrefs } from 'store/modules/prefs'

// route definition
export default function (store) {
  return {
    path: 'account',
    getComponent (nextState, cb) {
      store.dispatch(fetchRooms())
      store.dispatch(fetchPrefs())

      cb(null, AccountViewContainer)
    }
  }
}
<commit_msg>Remove fetches on route load (components each handle this now)<commit_after>import AccountViewContainer from './views/AccountViewContainer'

// route definition
export default function (store) {
  return {
    path: 'account',
    getComponent (nextState, cb) {
      cb(null, AccountViewContainer)
    }
  }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name                Selfish Youtube
// @version             2013-05-06
// @namespace           https://github.com/ASzc/selfish-youtube
// @description         On the watch page, remove the share panel.
// @include             http://youtube.com/watch*
// @include             http://*.youtube.com/watch*
// @include             https://youtube.com/watch*
// @include             https://*.youtube.com/watch*
// @grant               none
// ==/UserScript==

var panelName = "action-panel-share";

// Remove panel
var actionPanelShare = document.getElementById(panelName);
actionPanelShare.parentNode.removeChild(actionPanelShare);

// Remove buttons targeting the panel
var buttons = document.body.getElementsByTagName("button");
if (buttons != null) {
    for (var i = 0; i < buttons.length; i++) {
        var button = buttons[i];
        var buttonDTF = button.getAttribute("data-trigger-for");
        if (buttonDTF != null && buttonDTF == panelName) {
            button.parentNode.removeChild(button);
        }
    }
}
<commit_msg>Change to remove the new action-panel-error panel<commit_after>// ==UserScript==
// @name                Selfish Youtube
// @version             2013-05-06
// @namespace           https://github.com/ASzc/selfish-youtube
// @description         On the watch page, remove the share panel.
// @include             http://youtube.com/watch*
// @include             http://*.youtube.com/watch*
// @include             https://youtube.com/watch*
// @include             https://*.youtube.com/watch*
// @grant               none
// ==/UserScript==

function removeActionPanel(rootElem, panelName) {
    // Remove panel
    var actionPanelShare = rootElem.getElementById(panelName);

    if (actionPanelShare != null) {
        actionPanelShare.parentNode.removeChild(actionPanelShare);

        // Remove buttons targeting the panel
        var buttons = rootElem.body.getElementsByTagName("button");
        if (buttons != null) {
            for (var i = 0; i < buttons.length; i++) {
                var button = buttons[i];
                var buttonDTF = button.getAttribute("data-trigger-for");
                if (buttonDTF != null && buttonDTF == panelName) {
                    button.parentNode.removeChild(button);
                }
            }
        }
    }
}

var panelsToRemove = ["action-panel-share", "action-panel-error"];

for (var i = 0; i < panelsToRemove.length; i++) {
    removeActionPanel(document, panelsToRemove[i]);
}
<|endoftext|>


<commit_before>import path from 'path';
import express from 'express';
import { ParseServer } from '../index';
import definitions from './cli-definitions';
import program from './utils/commander';
import colors from 'colors';

program.loadDefinitions(definitions);

program
  .usage('[options] <path/to/configuration.json>');

program.on('--help', function(){
  console.log('  Get Started guide:');
  console.log('');
  console.log('    Please have a look at the get started guide!')
  console.log('    https://github.com/ParsePlatform/parse-server/wiki/Parse-Server-Guide');
  console.log('');
  console.log('');
  console.log('  Usage with npm start');
  console.log('');
  console.log('    $ npm start -- path/to/config.json');
  console.log('    $ npm start -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('    $ npm start -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('');
  console.log('');
  console.log('  Usage:');
  console.log('');
  console.log('    $ parse-server path/to/config.json');
  console.log('    $ parse-server -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('    $ parse-server -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('');
});

program.parse(process.argv, process.env);

let options = {};
if (program.args.length > 0 ) {
  let jsonPath = program.args[0];
  jsonPath = path.resolve(jsonPath);
  options = require(jsonPath);
  console.log(`Configuation loaded from ${jsonPath}`)
}

options = Object.keys(definitions).reduce(function (options, key) {
  if (program[key]) {
    options[key] = program[key];
  }
  return options;
}, options);

if (!options.serverURL) {
  options.serverURL = `http://localhost:${options.port}${options.mountPath}`;
}

if (!options.appId || !options.masterKey || !options.serverURL) {
  program.outputHelp();
  console.error("");
  console.error(colors.red("ERROR: appId, masterKey and serverURL are required"));
  console.error("");
  process.exit(1);
}

const app = express();
const api = new ParseServer(options);
app.use(options.mountPath, api);

var server = app.listen(options.port, function() {

  for (let key in options) {
    let value = options[key];
    if (key == "masterKey") {
      value = "***REDACTED***";
    }
    console.log(`${key}: ${value}`);
  }
  console.log('');
  console.log('parse-server running on '+options.serverURL);
});

var handleShutdown = function() {
  console.log('Termination signal received. Shutting down.');
  server.close(function () {
    process.exit(0);
  });
};
process.on('SIGTERM', handleShutdown);
process.on('SIGINT', handleShutdown);
<commit_msg>Adds support for apps key in config file, throws if length is > 1<commit_after>import path from 'path';
import express from 'express';
import { ParseServer } from '../index';
import definitions from './cli-definitions';
import program from './utils/commander';
import colors from 'colors';

program.loadDefinitions(definitions);

program
  .usage('[options] <path/to/configuration.json>');

program.on('--help', function(){
  console.log('  Get Started guide:');
  console.log('');
  console.log('    Please have a look at the get started guide!')
  console.log('    https://github.com/ParsePlatform/parse-server/wiki/Parse-Server-Guide');
  console.log('');
  console.log('');
  console.log('  Usage with npm start');
  console.log('');
  console.log('    $ npm start -- path/to/config.json');
  console.log('    $ npm start -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('    $ npm start -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('');
  console.log('');
  console.log('  Usage:');
  console.log('');
  console.log('    $ parse-server path/to/config.json');
  console.log('    $ parse-server -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('    $ parse-server -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL');
  console.log('');
});

program.parse(process.argv, process.env);

let options = {};
if (program.args.length > 0 ) {
  let jsonPath = program.args[0];
  jsonPath = path.resolve(jsonPath);
  let jsonConfig = require(jsonPath);
  if (jsonConfig.apps) {
    if (jsonConfig.apps.length > 1) {
      throw 'Multiple apps are not supported';
    }
    options = jsonConfig.apps[0];
  } else {
    options = jsonConfig;
  }
  console.log(`Configuation loaded from ${jsonPath}`)
}

options = Object.keys(definitions).reduce(function (options, key) {
  if (program[key]) {
    options[key] = program[key];
  }
  return options;
}, options);

if (!options.serverURL) {
  options.serverURL = `http://localhost:${options.port}${options.mountPath}`;
}

if (!options.appId || !options.masterKey || !options.serverURL) {
  program.outputHelp();
  console.error("");
  console.error(colors.red("ERROR: appId, masterKey and serverURL are required"));
  console.error("");
  process.exit(1);
}

const app = express();
const api = new ParseServer(options);
app.use(options.mountPath, api);

var server = app.listen(options.port, function() {

  for (let key in options) {
    let value = options[key];
    if (key == "masterKey") {
      value = "***REDACTED***";
    }
    console.log(`${key}: ${value}`);
  }
  console.log('');
  console.log('parse-server running on '+options.serverURL);
});

var handleShutdown = function() {
  console.log('Termination signal received. Shutting down.');
  server.close(function () {
    process.exit(0);
  });
};
process.on('SIGTERM', handleShutdown);
process.on('SIGINT', handleShutdown);
<|endoftext|>


<commit_before>$(function initPage() {
  var dbMyComments = db('my_comments[]')
  var $form_comment = $('#form_comment')
  var submitted = false

  // hack
  $('span>button').each(function () {
    var $btn = $(this)
    //$btn.height($btn.parent().height())
    $btn.css({
      '-webkit-box-sizing': 'border-box',
      'box-sizing': 'border-box',
      'height': $btn.parent().height()
    })
  })

  var myComment = dbMyComments
    .findLast({ topic_key: topic.key }).value()
  if (myComment) {
    document.title = '我参与了 ##' + topic.title +
      '## ，' + myComment.floor + '楼是我'
  }

  $form_comment.on('submit', function (e) {
    e.preventDefault()
    if (submitted) return alert('稍安勿躁')
    var form = $form_comment.serializeJSON()
    if (!form['text']) return
    var url = '../api/topics/' + topic.key + '/comments'
    $.post(url, form, function (d) {
      if (typeof d !== 'object' || !d.floor) {
        return alert('评论失败，为毛？')
      }
      dbMyComments.push({
        floor: d.floor,
        topic_key: topic.key
      }).save()
      submitted = true
      //alert('评论成功，楼层：' + d.floor)
      location.reload()
    })
  })
})
<commit_msg>调整分享标题<commit_after>$(function initPage() {
  var dbMyComments = db('my_comments[]')
  var $form_comment = $('#form_comment')
  var submitted = false

  // hack
  $('span>button').each(function () {
    var $btn = $(this)
    //$btn.height($btn.parent().height())
    $btn.css({
      '-webkit-box-sizing': 'border-box',
      'box-sizing': 'border-box',
      'height': $btn.parent().height()
    })
  })

  var myComment = dbMyComments
    .findLast({ topic_key: topic.key }).value()
  if (myComment) {
    //document.title = '我参与了 ##' + topic.title +
    //  '## ，' + myComment.floor + '楼是我'
  }

  $form_comment.on('submit', function (e) {
    e.preventDefault()
    if (submitted) return alert('稍安勿躁')
    var form = $form_comment.serializeJSON()
    if (!form['text']) return
    var url = '../api/topics/' + topic.key + '/comments'
    $.post(url, form, function (d) {
      if (typeof d !== 'object' || !d.floor) {
        return alert('评论失败，为毛？')
      }
      dbMyComments.push({
        floor: d.floor,
        topic_key: topic.key
      }).save()
      submitted = true
      //alert('评论成功，楼层：' + d.floor)
      location.reload()
    })
  })
})
<|endoftext|>