prefixaut/splitterino

View on GitHub
src/store/index.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { ipcRenderer, remote } from 'electron';
import { Injector } from 'lightweight-di';
import Vuex, { DispatchOptions, Payload } from 'vuex';

import { ActionResult } from '../common/interfaces/electron';
import { Logger } from '../utils/logger';
import { getSplitterinoStoreModules } from './modules/index.module';
import { RootState } from './states/root.state';

export function getStoreConfig(injector: Injector) {
    return {
        strict: true,
        modules: {
            splitterino: {
                namespaced: true,
                modules: getSplitterinoStoreModules(injector)
            }
        }
    };
}

export function getClientStore(vueRef, injector: Injector) {
    vueRef.use(Vuex);

    const store = new Vuex.Store<RootState>({
        plugins: [
            events => {
                events.subscribe(mutation => {
                    let payload: any;
                    let id = '';

                    if (
                        typeof mutation.payload === 'object' &&
                        'id' in mutation.payload &&
                        'payload' in mutation.payload
                    ) {
                        payload = mutation.payload.payload;
                        id = `:${mutation.payload.id}`;
                    } else {
                        payload = mutation.payload;
                    }

                    vueRef.prototype.$eventHub.$emit(
                        `commit:${mutation.type}${id}`,
                        payload
                    );
                });
            },
        ],
        ...getStoreConfig(injector)
    });

    // * Probably fine if we don't do any heavy init stuff in state
    store.replaceState(ipcRenderer.sendSync('vuex-connect'));

    const windowRef = remote.getCurrentWindow();
    windowRef.on('close', () => {
        ipcRenderer.send('vuex-disconnect');
    });

    // Override the dispatch function to delegate it to the main process instead
    // tslint:disable-next-line only-arrow-functions no-string-literal
    store['_dispatch'] = store.dispatch = function <P extends Payload>(
        typeMaybeWithPayload: string | P,
        payloadOrOptions?: any | DispatchOptions,
        options?: DispatchOptions
    ) {
        let actualType: string;
        let actualPayload: any;
        let actualOptions: DispatchOptions;

        if (typeof typeMaybeWithPayload === 'string') {
            actualType = typeMaybeWithPayload;
            actualPayload = payloadOrOptions;
            actualOptions = options;
        } else if (typeMaybeWithPayload != null && typeof typeMaybeWithPayload === 'object') {
            const { type, ...payloadData } = typeMaybeWithPayload;
            actualType = type;
            actualPayload = payloadData;
            actualOptions = payloadOrOptions;
        }

        if (actualType == null) {
            const errorMsg = 'The type for the dispatch could not be determined';
            Logger.error({
                msg: errorMsg,
                arguments: arguments
            });

            return Promise.reject(new Error(errorMsg));
        }

        Logger.debug({
            msg: 'Forwarding action to main process',
            type: actualType,
            payload: actualPayload,
            options: actualOptions,
        });

        return new Promise((resolve, reject) => {
            try {
                const actionResult: ActionResult = ipcRenderer.sendSync('vuex-dispatch', {
                    type: actualType,
                    payload: actualPayload,
                    options: actualOptions
                });
                if (actionResult.error == null) {
                    resolve(actionResult.result);
                } else {
                    reject(actionResult.error);
                }
            } catch (error) {
                reject(error);
            }
        });
    };

    ipcRenderer.on('vuex-apply-mutation', (event, { type, payload }) => {
        Logger.debug({
            msg: 'vuex-apply-mutation',
            type,
            payload
        });

        try {
            store.commit(type, payload);
        } catch (err) {
            Logger.error({
                msg: 'Could not apply vuex-mutation!',
                error: err,
            });
        }
    });

    return store;
}