Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
presidenten committed Apr 27, 2017
1 parent 4d9b586 commit 9465029
Show file tree
Hide file tree
Showing 13 changed files with 468 additions and 534 deletions.
465 changes: 214 additions & 251 deletions dist/vuex+.js

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions src/api/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* The api for all stores
* The api is autogenerated once the module importer has been set
* ```
* api.aStore.get.something => vuex magic string for vuex getter
* ```
*/
export const api = {};

/**
* Get subtree from map matching key
* TODO -- verify --
*/
export function extractSubstoreApi(map, key) {
const submodules = Object.keys(map).filter(k => k !== 'get' && k !== 'act' && k !== 'mutate');
const keyIsInMap = submodules.indexOf(key) >= 0;

if (keyIsInMap) {
return map[key];
}

// TODO Speed up with some nice algorithm
let result;
submodules.forEach((submodule) => {
const searchResult = extractSubstoreApi(map[submodule], key);
if (searchResult) {
result = searchResult;
}
});

return result;
}


export const getFullPath = (config) => {
const suffix = config.instance ? '$' + config.instance : '';
const getterKey = config.subpath.match(/[a-zA-Z]*/)[0];
let localApi = api[config.vuexPlus.baseStoreName];
if (getterKey !== config.vuexPlus.baseStoreName) {
localApi = extractSubstoreApi(api[config.vuexPlus.baseStoreName], getterKey + suffix);
}

if (!localApi) {
const instance = config.subpath.split('/')[0] + '$' + config.instance;
console.error('[Vuex+ warn]: Cant find substore instance "' + instance + '" in "' + config.container + '"');
return undefined;
}

const fullPath = localApi[config.method][config.key]
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);

return fullPath;
};

export function remapBaseStore(storeApi, baseStoreName, newStoreName) {
newStoreName = newStoreName || baseStoreName;
const result = {};
Object.keys(storeApi).forEach((type) => {
if (type === 'get' || type === 'act' || type === 'mutate') {
result[type] = {};
Object.keys(storeApi[type]).forEach((pathName) => {
result[type][pathName] = storeApi[type][pathName].replace(baseStoreName, newStoreName);
});
} else {
result[type] = remapBaseStore(storeApi[type], baseStoreName, newStoreName);
}
});

return result;
}
48 changes: 48 additions & 0 deletions src/api/global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import clone from 'clone';
import { api } from './api.js';
import { getStoreInstanceName } from '../common/helpers.js';

const getLocalPath = (path, context) => {
const storeName = context.state['vuex+'].storeName;
const instance = context.state['vuex+'].instance;
return path.replace(storeName, getStoreInstanceName(storeName, instance));
};

/**
* Method that returns a getter from the same instance.
* @param {string} - Path as as string, usually from api. Eg. `api.example.get.something`
* @param {Context} - Vuex context
* @returns {any} - Value from Vuex getter
*/
export default {
get api() {
return clone(api);
},

get({ path, context, local }) {
if (local) {
const localPath = getLocalPath(path, context);
return context.rootGetters[localPath];
}

return context.rootGetters[path];
},

dispatch({ path, data, context, local }) {
if (local) {
const localPath = getLocalPath(path, context);
return context.dispatch(localPath, data, { root: true });
}

return context.dispatch(path, data, { root: true });
},

commit({ path, data, context, local }) {
if (local) {
const localPath = getLocalPath(path, context);
return context.commit(localPath, data, { root: true });
}

return context.commit(path, data, { root: true });
},
};
41 changes: 41 additions & 0 deletions src/api/map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { getFullPath } from './api.js';

export default {
getters(m) {
const result = {};
Object.keys(m).forEach((key) => {
result[key] = function get() {
const path = getFullPath({
method: 'get',
key,
subpath: m[key],
instance: this.instance,
vuexPlus: this['$vuex+'],
container: this.$parent.$vnode.componentOptions.tag,
});

return this.$store.getters[path];
};
});
return result;
},

actions(m) {
const result = {};
Object.keys(m).forEach((key) => {
result[key] = function dispatch(payload) {
const path = getFullPath({
method: 'act',
key,
subpath: m[key],
instance: this.instance,
vuexPlus: this['$vuex+'],
container: this.$parent.$vnode.componentOptions.tag,
});

return this.$store.dispatch(path, payload);
};
});
return result;
},
};
6 changes: 0 additions & 6 deletions src/instanceHandling/helpers.js → src/common/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,3 @@ export const getStoreInstanceName = (storeName, instance) => {
};

export const toCamelCase = str => str.replace(/(-|_)([a-z])/g, s => s[1].toUpperCase());

export const getLocalPath = (path, context) => {
const storeName = context.state['vuex+'].storeName;
const instance = context.state['vuex+'].instance;
return path.replace(storeName, getStoreInstanceName(storeName, instance));
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { api, remapBaseStore } from './api.js';
import { api, remapBaseStore } from '../api/api.js';
import { toCamelCase } from './helpers.js';

let handlers = [];
Expand Down
58 changes: 0 additions & 58 deletions src/instanceHandling/api.js

This file was deleted.

10 changes: 4 additions & 6 deletions src/instanceHandling/addStore.js → src/mixins/addStore.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import newStore from './newStore.js';
import { api, remapBaseStore } from './api.js';
import { getStoreInstanceName, toCamelCase } from './helpers.js';
import { registerForHMR, unregisterForHMR } from './hmrHandler.js';
import { api, remapBaseStore } from '../api/api.js';
import { getStoreInstanceName, toCamelCase } from '../common/helpers.js';
import { registerForHMR, unregisterForHMR } from '../common/hmrHandler.js';

let importer;

Expand All @@ -18,7 +18,7 @@ export function setup(newImporter) {
* @param {Object} loadedModule - The loaded javascript module containing the Vuex module store
* @returns {mixin, api} api for the loaded module and a mixin
*/
export function add(baseStoreName) {
export default function add(baseStoreName) {
const loadedModule = importer.getModules()[baseStoreName];
const counter = {};
function HmrHandler(instanceName, getNewInstanceStore) {
Expand Down Expand Up @@ -62,8 +62,6 @@ export function add(baseStoreName) {
if (!this.preserve && counter[this['$vuex+'].storeInstanceName] === 0) {
this.$store.unregisterModule(this['$vuex+'].storeInstanceName);

// delete api[this['$vuex+'].storeInstanceName];

if (module.hot) {
unregisterForHMR(this.$hmrHandler);
}
Expand Down
38 changes: 38 additions & 0 deletions src/mixins/install.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import contextHmr from 'webpack-context-vuex-hmr';

import { setup } from './addStore.js';
import { hmrHandler, setStore } from '../common/hmrHandler.js';

let setupDone = false;
export default {
install(Vue) {
Vue.mixin({
props: ['instance'],
created() {
if (!setupDone && this.$store) {
setStore(this.$store);
const importer = contextHmr.getNewInstance();
setup(importer);
importer.getModules();
importer.setupHMR(hmrHandler);
setupDone = true;
}

const findModuleName = (parent) => {
if (!this['$vuex+'] && parent.$parent) {
if (!parent.$parent['$vuex+']) {
findModuleName(parent.$parent, '/');
} else {
this['$vuex+'] = {
baseStoreName: parent.$parent['$vuex+'].baseStoreName,
storeInstanceName: parent.$parent['$vuex+'].storeInstanceName,
};
}
}
};

findModuleName(this, '/');
},
});
},
};
File renamed without changes.
14 changes: 14 additions & 0 deletions src/store/newInstance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import clone from 'clone';

export default (substore, instance) => {
const result = clone(substore);
Object.keys(result.api).forEach((type) => {
if (type === 'get' || type === 'act' || type === 'mutate') {
Object.keys(result.api[type]).forEach((key) => {
result.api[type][key] = result.api[type][key].split('/')[0] + '$' + instance + '/' + key;
});
}
});

return result;
};
27 changes: 24 additions & 3 deletions src/instanceHandling/storeWrapper.js → src/store/storeWrapper.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import clone from 'clone';
import { toCamelCase } from './helpers.js';
import { addModuleToNames } from './api.js';
import { toCamelCase } from '../common/helpers.js';

/**
* Private method that modifies magics strings to contain their parents
* @param {Object} api - object tree with magic strings
* @param {string} parentName - parentName
* @returns {Object} all tree nodes have been padded with parentName '/'
*/
function addParentToPath(subapi, parentName) {
const result = {};
Object.keys(subapi).forEach((type) => {
if (type === 'get' || type === 'act' || type === 'mutate') {
result[type] = {};
Object.keys(subapi[type]).forEach((pathName) => {
const path = subapi[type][pathName];
result[type][pathName] = parentName + '/' + path;
});
} else {
result[type] = addParentToPath(subapi[type], parentName);
}
});

return result;
}

/**
* Modify Vuex Module to contain an api with magic strings
Expand Down Expand Up @@ -42,7 +63,7 @@ export default function (store) {
// Clone modules
if (store.modules) {
Object.keys(store.modules).forEach((name) => {
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api);
store.api[name] = addParentToPath(store.modules[name].api, camelCasedName);
});
}

Expand Down
Loading

0 comments on commit 9465029

Please sign in to comment.