Skip to content

Commit

Permalink
Handle submodule instantiations
Browse files Browse the repository at this point in the history
  • Loading branch information
presidenten committed Apr 25, 2017
1 parent ff10830 commit 4efadab
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 57 deletions.
72 changes: 44 additions & 28 deletions dist/vuex+.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,14 @@ var getLocalPath = function (path, context) {
/**
* Private method that modifies magics strings to contain their parents
*/
function addModuleToNames(name, subapi, instanceName) {
function addModuleToNames(name, subapi) {
var result = {};
Object.keys(subapi).forEach(function (type) {
if (type === 'get' || type === 'act' || type === 'mutate') {
result[type] = {};
Object.keys(subapi[type]).forEach(function (pathName) {
var path = subapi[type][pathName];
var subname = path.match(/[a-zA-Z]*/)[0];
result[type][pathName] = name + '/' + path;
if (instanceName) {
result[type][pathName] = result[type][pathName].replace(subname, subname + '$' + instanceName);
}
});
} else {
result[type] = addModuleToNames(name, subapi[type]);
Expand Down Expand Up @@ -78,13 +74,12 @@ var storeWrapper = function (store) {
// Clone modules
if (store.modules) {
Object.keys(store.modules).forEach(function (name) {
var hashPos = name.indexOf('$');
var instanceName = hashPos >= 0 ? name.slice(hashPos + 1) : undefined;

store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api, instanceName);
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api);
});
}

store.$api = clone(store.api, false);

return store;
};

Expand Down Expand Up @@ -241,11 +236,10 @@ var api$1 = {};
*/
var generateAPI = function (newImporter) {
importer$1 = newImporter;

var modules = importer$1.getModules();
Object.keys(modules).forEach(function (module) {
var camelCasedName = toCamelCase(modules[module].name);
api$1[camelCasedName] = modules[module].api;
api$1[camelCasedName] = modules[module].$api;
});
};

Expand All @@ -271,17 +265,26 @@ function searchDeeper(map, key) {
return result;
}

function getFullPath(config) {
var suffix = config.subinstance ? '$' + config.subinstance : '';
var getterKey = config.mappedKey.match(/[a-zA-Z]*/)[0];

var getFullPath = function (config) {
var suffix = config.instance ? '$' + config.instance : '';
var getterKey = config.subpath.match(/[a-zA-Z]*/)[0];
var localApi = api$1[config.vuexPlus.baseStoreName];

if (getterKey !== config.vuexPlus.baseStoreName) {
localApi = searchDeeper(api$1[config.vuexPlus.baseStoreName], getterKey + suffix);
}
return localApi[config.method][config.key]
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);
}

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

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

return fullPath;
};

var map = {
getters: function getters(m) {
Expand All @@ -291,12 +294,12 @@ var map = {
var path = getFullPath({
method: 'get',
key: key,
mappedKey: m[key],
subinstance: this.subinstance,
subpath: m[key],
instance: this.instance,
vuexPlus: this['$vuex+'],
container: this.$parent.$vnode.componentOptions.tag,
});

// localApi.get[key].replace(this['$vuex+'].baseStoreName, this['$vuex+'].storeInstanceName)
return this.$store.getters[path];
};
});
Expand All @@ -310,10 +313,12 @@ var map = {
var path = getFullPath({
method: 'act',
key: key,
mappedKey: m[key],
subinstance: this.subinstance,
subpath: m[key],
instance: this.instance,
vuexPlus: this['$vuex+'],
container: this.$parent.$vnode.componentOptions.tag,
});

return this.$store.dispatch(path, payload);
};
});
Expand Down Expand Up @@ -362,13 +367,26 @@ var hmrCallback = hmrHandler;
*/
var api$$1 = api$1;

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

return result;
};

/**
* 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
*/
var instance = {
var global = {
get: function get(ref) {
var path = ref.path;
var context = ref.context;
Expand Down Expand Up @@ -403,6 +421,7 @@ var setupDone = false;
var vuex_ = {
install: function install(Vue) {
Vue.mixin({
props: ['instance'],
created: function created() {
var this$1 = this;

Expand All @@ -418,11 +437,9 @@ var vuex_ = {

var findModuleName = function (parent) {
if (!this$1['$vuex+'] && parent.$parent) {
// console.info(parent.$parent.name, parent.$parent);
if (!parent.$parent['$vuex+']) {
findModuleName(parent.$parent, '/');
} else {
// console.info('found [vuex+]', parent.$parent['$vuex+'].baseStoreName);
this$1['$vuex+'] = {
baseStoreName: parent.$parent['$vuex+'].baseStoreName,
storeInstanceName: parent.$parent['$vuex+'].storeInstanceName,
Expand All @@ -431,11 +448,10 @@ var vuex_ = {
}
};

// console.info('finding', this.$options['_componentTag']);
findModuleName(this, '/');
},
});
},
};

export { addStore, map, store, hmrCallback, api$$1 as api, instance };export default vuex_;
export { addStore, map, store, hmrCallback, api$$1 as api, newInstance, global };export default vuex_;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vuex-plus",
"version": "0.3.1",
"version": "0.4.0",
"description": "Opinionated library that handles module instances in Vuex",
"main": "dist/vuex+.js",
"scripts": {
Expand Down
3 changes: 2 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ module.exports = {
entry: 'src/vuex+.js',
dest: 'dist/vuex+.js',
format: 'es',
plugins: [ buble() ],
plugins: [buble()],
external: ['webpack-context-vuex-hmr', 'clone'],
};
3 changes: 1 addition & 2 deletions src/instanceHandling/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ export const api = {};
*/
export const generateAPI = (newImporter) => {
importer = newImporter;

const modules = importer.getModules();
Object.keys(modules).forEach((module) => {
const camelCasedName = toCamelCase(modules[module].name);
api[camelCasedName] = modules[module].api;
api[camelCasedName] = modules[module].$api;
});
};
14 changes: 5 additions & 9 deletions src/instanceHandling/storeWrapper.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import clone from 'clone';
import { toCamelCase } from './helpers.js';

/**
* Private method that modifies magics strings to contain their parents
*/
function addModuleToNames(name, subapi, instanceName) {
function addModuleToNames(name, subapi) {
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];
const subname = path.match(/[a-zA-Z]*/)[0];
result[type][pathName] = name + '/' + path;
if (instanceName) {
result[type][pathName] = result[type][pathName].replace(subname, subname + '$' + instanceName);
}
});
} else {
result[type] = addModuleToNames(name, subapi[type]);
Expand Down Expand Up @@ -62,12 +59,11 @@ export default function (store) {
// Clone modules
if (store.modules) {
Object.keys(store.modules).forEach((name) => {
const hashPos = name.indexOf('$');
const instanceName = hashPos >= 0 ? name.slice(hashPos + 1) : undefined;

store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api, instanceName);
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api);
});
}

store.$api = clone(store.api, false);

return store;
}
55 changes: 39 additions & 16 deletions src/vuex+.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import contextHmr from 'webpack-context-vuex-hmr';
import clone from 'clone';

import storeWrapper from './instanceHandling/storeWrapper.js';
import { hmrHandler, setStore } from './instanceHandling/hmrHandler.js';
Expand Down Expand Up @@ -28,17 +29,26 @@ function searchDeeper(map, key) {
return result;
}

function getFullPath(config) {
const suffix = config.subinstance ? '$' + config.subinstance : '';
const getterKey = config.mappedKey.match(/[a-zA-Z]*/)[0];

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

if (getterKey !== config.vuexPlus.baseStoreName) {
localApi = searchDeeper(apiManager.api[config.vuexPlus.baseStoreName], getterKey + suffix);
}
return localApi[config.method][config.key]
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);
}

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 const map = {
getters(m) {
Expand All @@ -48,12 +58,12 @@ export const map = {
const path = getFullPath({
method: 'get',
key,
mappedKey: m[key],
subinstance: this.subinstance,
subpath: m[key],
instance: this.instance,
vuexPlus: this['$vuex+'],
container: this.$parent.$vnode.componentOptions.tag,
});

// localApi.get[key].replace(this['$vuex+'].baseStoreName, this['$vuex+'].storeInstanceName)
return this.$store.getters[path];
};
});
Expand All @@ -67,10 +77,12 @@ export const map = {
const path = getFullPath({
method: 'act',
key,
mappedKey: m[key],
subinstance: this.subinstance,
subpath: m[key],
instance: this.instance,
vuexPlus: this['$vuex+'],
container: this.$parent.$vnode.componentOptions.tag,
});

return this.$store.dispatch(path, payload);
};
});
Expand Down Expand Up @@ -119,13 +131,26 @@ export const hmrCallback = hmrHandler;
*/
export const api = apiManager.api;

export const newInstance = function newInstance(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;
};

/**
* 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 const instance = {
export const global = {
get({ path, context }) {
const localPath = getLocalPath(path, context);

Expand All @@ -149,6 +174,7 @@ let setupDone = false;
export default {
install(Vue) {
Vue.mixin({
props: ['instance'],
created() {
if (!setupDone && this.$store) {
setStore(this.$store);
Expand All @@ -162,11 +188,9 @@ export default {

const findModuleName = (parent) => {
if (!this['$vuex+'] && parent.$parent) {
// console.info(parent.$parent.name, parent.$parent);
if (!parent.$parent['$vuex+']) {
findModuleName(parent.$parent, '/');
} else {
// console.info('found [vuex+]', parent.$parent['$vuex+'].baseStoreName);
this['$vuex+'] = {
baseStoreName: parent.$parent['$vuex+'].baseStoreName,
storeInstanceName: parent.$parent['$vuex+'].storeInstanceName,
Expand All @@ -175,7 +199,6 @@ export default {
}
};

// console.info('finding', this.$options['_componentTag']);
findModuleName(this, '/');
},
});
Expand Down

0 comments on commit 4efadab

Please sign in to comment.