Skip to content

Commit 4efadab

Browse files
committed
Handle submodule instantiations
1 parent ff10830 commit 4efadab

File tree

6 files changed

+92
-57
lines changed

6 files changed

+92
-57
lines changed

dist/vuex+.js

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,14 @@ var getLocalPath = function (path, context) {
1919
/**
2020
* Private method that modifies magics strings to contain their parents
2121
*/
22-
function addModuleToNames(name, subapi, instanceName) {
22+
function addModuleToNames(name, subapi) {
2323
var result = {};
2424
Object.keys(subapi).forEach(function (type) {
2525
if (type === 'get' || type === 'act' || type === 'mutate') {
2626
result[type] = {};
2727
Object.keys(subapi[type]).forEach(function (pathName) {
2828
var path = subapi[type][pathName];
29-
var subname = path.match(/[a-zA-Z]*/)[0];
3029
result[type][pathName] = name + '/' + path;
31-
if (instanceName) {
32-
result[type][pathName] = result[type][pathName].replace(subname, subname + '$' + instanceName);
33-
}
3430
});
3531
} else {
3632
result[type] = addModuleToNames(name, subapi[type]);
@@ -78,13 +74,12 @@ var storeWrapper = function (store) {
7874
// Clone modules
7975
if (store.modules) {
8076
Object.keys(store.modules).forEach(function (name) {
81-
var hashPos = name.indexOf('$');
82-
var instanceName = hashPos >= 0 ? name.slice(hashPos + 1) : undefined;
83-
84-
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api, instanceName);
77+
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api);
8578
});
8679
}
8780

81+
store.$api = clone(store.api, false);
82+
8883
return store;
8984
};
9085

@@ -241,11 +236,10 @@ var api$1 = {};
241236
*/
242237
var generateAPI = function (newImporter) {
243238
importer$1 = newImporter;
244-
245239
var modules = importer$1.getModules();
246240
Object.keys(modules).forEach(function (module) {
247241
var camelCasedName = toCamelCase(modules[module].name);
248-
api$1[camelCasedName] = modules[module].api;
242+
api$1[camelCasedName] = modules[module].$api;
249243
});
250244
};
251245

@@ -271,17 +265,26 @@ function searchDeeper(map, key) {
271265
return result;
272266
}
273267

274-
function getFullPath(config) {
275-
var suffix = config.subinstance ? '$' + config.subinstance : '';
276-
var getterKey = config.mappedKey.match(/[a-zA-Z]*/)[0];
277-
268+
var getFullPath = function (config) {
269+
var suffix = config.instance ? '$' + config.instance : '';
270+
var getterKey = config.subpath.match(/[a-zA-Z]*/)[0];
278271
var localApi = api$1[config.vuexPlus.baseStoreName];
272+
279273
if (getterKey !== config.vuexPlus.baseStoreName) {
280274
localApi = searchDeeper(api$1[config.vuexPlus.baseStoreName], getterKey + suffix);
281275
}
282-
return localApi[config.method][config.key]
283-
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);
284-
}
276+
277+
if (!localApi) {
278+
var instance = config.subpath.split('/')[0] + '$' + config.instance;
279+
console.error('[Vuex+ warn]: Cant find substore instance "' + instance + '" in "' + config.container + '"');
280+
return undefined;
281+
}
282+
283+
var fullPath = localApi[config.method][config.key]
284+
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);
285+
286+
return fullPath;
287+
};
285288

286289
var map = {
287290
getters: function getters(m) {
@@ -291,12 +294,12 @@ var map = {
291294
var path = getFullPath({
292295
method: 'get',
293296
key: key,
294-
mappedKey: m[key],
295-
subinstance: this.subinstance,
297+
subpath: m[key],
298+
instance: this.instance,
296299
vuexPlus: this['$vuex+'],
300+
container: this.$parent.$vnode.componentOptions.tag,
297301
});
298302

299-
// localApi.get[key].replace(this['$vuex+'].baseStoreName, this['$vuex+'].storeInstanceName)
300303
return this.$store.getters[path];
301304
};
302305
});
@@ -310,10 +313,12 @@ var map = {
310313
var path = getFullPath({
311314
method: 'act',
312315
key: key,
313-
mappedKey: m[key],
314-
subinstance: this.subinstance,
316+
subpath: m[key],
317+
instance: this.instance,
315318
vuexPlus: this['$vuex+'],
319+
container: this.$parent.$vnode.componentOptions.tag,
316320
});
321+
317322
return this.$store.dispatch(path, payload);
318323
};
319324
});
@@ -362,13 +367,26 @@ var hmrCallback = hmrHandler;
362367
*/
363368
var api$$1 = api$1;
364369

370+
var newInstance = function newInstance(substore, instance) {
371+
var result = clone(substore);
372+
Object.keys(result.api).forEach(function (type) {
373+
if (type === 'get' || type === 'act' || type === 'mutate') {
374+
Object.keys(result.api[type]).forEach(function (key) {
375+
result.api[type][key] = result.api[type][key].split('/')[0] + '$' + instance + '/' + key;
376+
});
377+
}
378+
});
379+
380+
return result;
381+
};
382+
365383
/**
366384
* Method that returns a getter from the same instance.
367385
* @param {string} - Path as as string, usually from api. Eg. `api.example.get.something`
368386
* @param {Context} - Vuex context
369387
* @returns {any} - Value from Vuex getter
370388
*/
371-
var instance = {
389+
var global = {
372390
get: function get(ref) {
373391
var path = ref.path;
374392
var context = ref.context;
@@ -403,6 +421,7 @@ var setupDone = false;
403421
var vuex_ = {
404422
install: function install(Vue) {
405423
Vue.mixin({
424+
props: ['instance'],
406425
created: function created() {
407426
var this$1 = this;
408427

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

419438
var findModuleName = function (parent) {
420439
if (!this$1['$vuex+'] && parent.$parent) {
421-
// console.info(parent.$parent.name, parent.$parent);
422440
if (!parent.$parent['$vuex+']) {
423441
findModuleName(parent.$parent, '/');
424442
} else {
425-
// console.info('found [vuex+]', parent.$parent['$vuex+'].baseStoreName);
426443
this$1['$vuex+'] = {
427444
baseStoreName: parent.$parent['$vuex+'].baseStoreName,
428445
storeInstanceName: parent.$parent['$vuex+'].storeInstanceName,
@@ -431,11 +448,10 @@ var vuex_ = {
431448
}
432449
};
433450

434-
// console.info('finding', this.$options['_componentTag']);
435451
findModuleName(this, '/');
436452
},
437453
});
438454
},
439455
};
440456

441-
export { addStore, map, store, hmrCallback, api$$1 as api, instance };export default vuex_;
457+
export { addStore, map, store, hmrCallback, api$$1 as api, newInstance, global };export default vuex_;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vuex-plus",
3-
"version": "0.3.1",
3+
"version": "0.4.0",
44
"description": "Opinionated library that handles module instances in Vuex",
55
"main": "dist/vuex+.js",
66
"scripts": {

rollup.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ module.exports = {
55
entry: 'src/vuex+.js',
66
dest: 'dist/vuex+.js',
77
format: 'es',
8-
plugins: [ buble() ],
8+
plugins: [buble()],
9+
external: ['webpack-context-vuex-hmr', 'clone'],
910
};

src/instanceHandling/api.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ export const api = {};
1616
*/
1717
export const generateAPI = (newImporter) => {
1818
importer = newImporter;
19-
2019
const modules = importer.getModules();
2120
Object.keys(modules).forEach((module) => {
2221
const camelCasedName = toCamelCase(modules[module].name);
23-
api[camelCasedName] = modules[module].api;
22+
api[camelCasedName] = modules[module].$api;
2423
});
2524
};

src/instanceHandling/storeWrapper.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1+
import clone from 'clone';
12
import { toCamelCase } from './helpers.js';
23

34
/**
45
* Private method that modifies magics strings to contain their parents
56
*/
6-
function addModuleToNames(name, subapi, instanceName) {
7+
function addModuleToNames(name, subapi) {
78
const result = {};
89
Object.keys(subapi).forEach((type) => {
910
if (type === 'get' || type === 'act' || type === 'mutate') {
1011
result[type] = {};
1112
Object.keys(subapi[type]).forEach((pathName) => {
1213
const path = subapi[type][pathName];
13-
const subname = path.match(/[a-zA-Z]*/)[0];
1414
result[type][pathName] = name + '/' + path;
15-
if (instanceName) {
16-
result[type][pathName] = result[type][pathName].replace(subname, subname + '$' + instanceName);
17-
}
1815
});
1916
} else {
2017
result[type] = addModuleToNames(name, subapi[type]);
@@ -62,12 +59,11 @@ export default function (store) {
6259
// Clone modules
6360
if (store.modules) {
6461
Object.keys(store.modules).forEach((name) => {
65-
const hashPos = name.indexOf('$');
66-
const instanceName = hashPos >= 0 ? name.slice(hashPos + 1) : undefined;
67-
68-
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api, instanceName);
62+
store.api[name] = addModuleToNames(camelCasedName, store.modules[name].api);
6963
});
7064
}
7165

66+
store.$api = clone(store.api, false);
67+
7268
return store;
7369
}

src/vuex+.js

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import contextHmr from 'webpack-context-vuex-hmr';
2+
import clone from 'clone';
23

34
import storeWrapper from './instanceHandling/storeWrapper.js';
45
import { hmrHandler, setStore } from './instanceHandling/hmrHandler.js';
@@ -28,17 +29,26 @@ function searchDeeper(map, key) {
2829
return result;
2930
}
3031

31-
function getFullPath(config) {
32-
const suffix = config.subinstance ? '$' + config.subinstance : '';
33-
const getterKey = config.mappedKey.match(/[a-zA-Z]*/)[0];
34-
32+
const getFullPath = (config) => {
33+
const suffix = config.instance ? '$' + config.instance : '';
34+
const getterKey = config.subpath.match(/[a-zA-Z]*/)[0];
3535
let localApi = apiManager.api[config.vuexPlus.baseStoreName];
36+
3637
if (getterKey !== config.vuexPlus.baseStoreName) {
3738
localApi = searchDeeper(apiManager.api[config.vuexPlus.baseStoreName], getterKey + suffix);
3839
}
39-
return localApi[config.method][config.key]
40-
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);
41-
}
40+
41+
if (!localApi) {
42+
const instance = config.subpath.split('/')[0] + '$' + config.instance;
43+
console.error('[Vuex+ warn]: Cant find substore instance "' + instance + '" in "' + config.container + '"');
44+
return undefined;
45+
}
46+
47+
const fullPath = localApi[config.method][config.key]
48+
.replace(config.vuexPlus.baseStoreName, config.vuexPlus.storeInstanceName);
49+
50+
return fullPath;
51+
};
4252

4353
export const map = {
4454
getters(m) {
@@ -48,12 +58,12 @@ export const map = {
4858
const path = getFullPath({
4959
method: 'get',
5060
key,
51-
mappedKey: m[key],
52-
subinstance: this.subinstance,
61+
subpath: m[key],
62+
instance: this.instance,
5363
vuexPlus: this['$vuex+'],
64+
container: this.$parent.$vnode.componentOptions.tag,
5465
});
5566

56-
// localApi.get[key].replace(this['$vuex+'].baseStoreName, this['$vuex+'].storeInstanceName)
5767
return this.$store.getters[path];
5868
};
5969
});
@@ -67,10 +77,12 @@ export const map = {
6777
const path = getFullPath({
6878
method: 'act',
6979
key,
70-
mappedKey: m[key],
71-
subinstance: this.subinstance,
80+
subpath: m[key],
81+
instance: this.instance,
7282
vuexPlus: this['$vuex+'],
83+
container: this.$parent.$vnode.componentOptions.tag,
7384
});
85+
7486
return this.$store.dispatch(path, payload);
7587
};
7688
});
@@ -119,13 +131,26 @@ export const hmrCallback = hmrHandler;
119131
*/
120132
export const api = apiManager.api;
121133

134+
export const newInstance = function newInstance(substore, instance) {
135+
const result = clone(substore);
136+
Object.keys(result.api).forEach((type) => {
137+
if (type === 'get' || type === 'act' || type === 'mutate') {
138+
Object.keys(result.api[type]).forEach((key) => {
139+
result.api[type][key] = result.api[type][key].split('/')[0] + '$' + instance + '/' + key;
140+
});
141+
}
142+
});
143+
144+
return result;
145+
};
146+
122147
/**
123148
* Method that returns a getter from the same instance.
124149
* @param {string} - Path as as string, usually from api. Eg. `api.example.get.something`
125150
* @param {Context} - Vuex context
126151
* @returns {any} - Value from Vuex getter
127152
*/
128-
export const instance = {
153+
export const global = {
129154
get({ path, context }) {
130155
const localPath = getLocalPath(path, context);
131156

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

163189
const findModuleName = (parent) => {
164190
if (!this['$vuex+'] && parent.$parent) {
165-
// console.info(parent.$parent.name, parent.$parent);
166191
if (!parent.$parent['$vuex+']) {
167192
findModuleName(parent.$parent, '/');
168193
} else {
169-
// console.info('found [vuex+]', parent.$parent['$vuex+'].baseStoreName);
170194
this['$vuex+'] = {
171195
baseStoreName: parent.$parent['$vuex+'].baseStoreName,
172196
storeInstanceName: parent.$parent['$vuex+'].storeInstanceName,
@@ -175,7 +199,6 @@ export default {
175199
}
176200
};
177201

178-
// console.info('finding', this.$options['_componentTag']);
179202
findModuleName(this, '/');
180203
},
181204
});

0 commit comments

Comments
 (0)