Skip to content

Commit

Permalink
Merge pull request #2434 from filrak/module_factory
Browse files Browse the repository at this point in the history
Module factory
  • Loading branch information
filrak committed Feb 17, 2019
2 parents c46c4fa + dd9beed commit 8a68a38
Show file tree
Hide file tree
Showing 33 changed files with 219 additions and 254 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [1.9.0]
### Changed / Improved
- Way of creating VS Modules was changed to use factory method instead of explict object creation. - @filrak (#2434)
- Added clear filters button on desktop also and only show if filters are applied - @DaanKouters (#2342)
- Improved docs at contributing.md and configuration.md (spelling etc.) - @ruthgeridema (#2421, #2422, #2423, #2425, #2426)
- Fixed design issue of Country label on Edge 17 & Firefox - @ananth-iyer (#2390,#2399)
Expand Down
35 changes: 35 additions & 0 deletions core/lib/module/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { VueStorefrontModuleConfig } from './types'
import { Module } from 'vuex'
import merge from 'lodash-es/merge'
import some from 'lodash-es/some'
import find from 'lodash-es/find'

function doesStoreAlreadyExists (key: string, registeredModules: VueStorefrontModuleConfig[]) : boolean {
registeredModules.forEach(m => {
if (m.store) {
if (m.store.modules.some(m => m.key === key)) return true
}
})
return false
}

function mergeStores (
originalStore: { modules?: { key: string, module: Module<any, any> }[], plugin?: Function },
extendedStore: { modules?: { key: string, module: Module<any, any> }[], plugin?: Function }
) {
let mergedArray = []
originalStore.modules.map(item => {
mergedArray.push(merge(item, find(extendedStore.modules, { 'key' : item.key })));
})
extendedStore.modules.map(extendedStoreItem => {
if(some(originalStore.modules, null, { 'key' : extendedStoreItem.key}) === false){
mergedArray.push(extendedStoreItem)
}
})
return mergedArray
}

export {
doesStoreAlreadyExists,
mergeStores
}
136 changes: 55 additions & 81 deletions core/lib/module.ts → core/lib/module/index.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,46 @@
import { Module, Store } from 'vuex'
import { Module } from 'vuex'
import { RouteConfig, NavigationGuard } from 'vue-router'
import Vue, { VueConstructor } from 'vue'
import Vue from 'vue'
import merge from 'lodash-es/merge'
import some from 'lodash-es/some'
import find from 'lodash-es/find'
import RootState from '@vue-storefront/core/types/RootState'
import rootStore from '@vue-storefront/store'
import { Logger } from '@vue-storefront/core/lib/logger'
import { setupMultistoreRoutes } from './multistore'
import { setupMultistoreRoutes } from '..//multistore'
import { router } from '@vue-storefront/core/app'
import { isServer } from '@vue-storefront/core/helpers'
import { VSF, VueStorefrontModuleConfig } from './types'
import { doesStoreAlreadyExists, mergeStores } from './helpers'

export interface VSF {
Vue?: VueConstructor,
config?: Object,
store?: Store<RootState>,
isServer?: boolean
const moduleExtendings: VueStorefrontModuleConfig[] = []
const registeredModules: VueStorefrontModuleConfig[] = []

function registerModules (modules: VueStorefrontModule[], context): void {
modules.forEach(m => m.register())
Logger.info('VS Modules registration finished.', 'module', {
succesfulyRegistered: registeredModules.length + ' / ' + modules.length,
registrationOrder: registeredModules
}
)()
}

export interface VueStorefrontModuleConfig {
key: string;
store?: { modules?: { key: string, module: Module<any, any> }[], plugin?: Function };
router?: { routes?: RouteConfig[], beforeEach?: NavigationGuard, afterEach?: NavigationGuard },
beforeRegistration?: (VSF: VSF | VueConstructor, config?: Object, store?: Store<RootState>, isServer?: boolean) => void,
afterRegistration?: (VSF: VSF | VueConstructor, config?: Object, store?: Store<RootState>, isServer?: boolean) => void,
function isModuleRegistered (key: string): boolean {
return registeredModules.some(m => m.key === key)
}

const moduleExtendings: VueStorefrontModuleConfig[] = []
function createModule (config: VueStorefrontModuleConfig): VueStorefrontModule {
return new VueStorefrontModule(config)
}

/** Provide `VueStorefrontModule` config that will be merged with module with the same `key` as this config.
* It's important to call this function before module is registered.
*
* Read more: [here](https://docs.vuestorefront.io/guide/modules/introduction.html#extending-and-overriding-vue-storefront-modules) */
export function extendModule(moduleConfig: VueStorefrontModuleConfig) {
function extendModule(moduleConfig: VueStorefrontModuleConfig) {
moduleExtendings.push(moduleConfig)
}

export class VueStorefrontModule {

class VueStorefrontModule {
private _isRegistered = false
constructor (
private _c: VueStorefrontModuleConfig,
) { }

public get config () {
return this._c
}

/** Use only if you want to explicitly modify module config. Otherwise it's much easier to use `extendModule` */
public set config (config) {
this._c = config
}

private static _registeredModules: VueStorefrontModuleConfig[] = []

private static _doesStoreAlreadyExists (key: string) : boolean {
let moduleExists = false
VueStorefrontModule._registeredModules.forEach(m => {
if (m.store) {
if (m.store.modules.some(m => m.key === key)) moduleExists = true
}
})
return moduleExists
}

private static _extendStore (storeInstance: any, modules: { key: string, module: Module<any, any> }[], plugin: any) : void {
if (modules) modules.forEach(store => storeInstance.registerModule(store.key, store.module))
if (plugin) storeInstance.subscribe(plugin)
Expand All @@ -77,56 +55,52 @@ export class VueStorefrontModule {
if (afterEach) routerInstance.afterEach(afterEach)
}

private _extend (extendedConfig: VueStorefrontModuleConfig) {
private _extendModule (extendedConfig: VueStorefrontModuleConfig): void {
const mergedStore = { modules: [] };
const key = this._c.key
const originalStore = this._c.store
const extendedStore = extendedConfig.store
delete this._c.store
delete extendedConfig.store
this._c = merge(this._c, extendedConfig)
mergedStore.modules = this._mergeStore(originalStore, extendedStore)
mergedStore.modules = mergeStores(originalStore, extendedStore)
this._c.store = mergedStore
Logger.info('Module "' + key + '" has been succesfully extended.', 'module')()
}

private _mergeStore(originalStore, extendedStore) {
let mergedArray = []
originalStore.modules.map(item => {
mergedArray.push(merge(item, find(extendedStore.modules, { 'key' : item.key })));
})
extendedStore.modules.map(extendedStoreItem => {
if(some(originalStore.modules, { 'key' : extendedStoreItem.key}) === false){
mergedArray.push(extendedStoreItem)
}
})
return mergedArray
public get config () {
return this._c
}

/** Use only if you want to explicitly modify module config. Otherwise it's much easier to use `extendModule` */
public set config (config) {
this._c = config
}

public register (): VueStorefrontModuleConfig | void {

const VSF = {
Vue,
config: rootStore.state.config,
store: rootStore,
isServer
}

if (!this._isRegistered) {
let areStoresUnique = true
const VSF: VSF = {
Vue,
config: rootStore.state.config,
store: rootStore,
isServer
}

moduleExtendings.forEach(extending => {
if (extending.key === this._c.key) this._extend(extending)
if (extending.key === this._c.key) this._extendModule(extending)
})

let isUnique = true
if ( this._c.store) {
if (this._c.store) {
this._c.store.modules.forEach(store => {
if (VueStorefrontModule._doesStoreAlreadyExists(store.key)) {
if (doesStoreAlreadyExists(store.key, registeredModules)) {
Logger.warn('Error during "' + this._c.key + '" module registration! Store with key "' + store.key + '" already exists!', 'module')()
isUnique = false
areStoresUnique = false
}
})
}
if (isUnique) {

if (areStoresUnique) {
if (this._c.beforeRegistration) {
if (this._c.beforeRegistration.length === 1 ) {
this._c.beforeRegistration(VSF)
Expand All @@ -137,7 +111,7 @@ export class VueStorefrontModule {
}
if (this._c.store) VueStorefrontModule._extendStore(rootStore, this._c.store.modules, this._c.store.plugin)
if (this._c.router) VueStorefrontModule._extendRouter(router, this._c.router.routes, this._c.router.beforeEach, this._c.router.afterEach)
VueStorefrontModule._registeredModules.push(this._c)
registeredModules.push(this._c)
this._isRegistered = true
if (this._c.afterRegistration) {
if (this._c.afterRegistration.length === 1 ) {
Expand All @@ -153,12 +127,12 @@ export class VueStorefrontModule {
}
}

export function registerModules (modules: VueStorefrontModule[], context): void {
let registeredModules = []
modules.forEach(m => registeredModules.push(m.register()))
Logger.info('VS Modules registration finished.', 'module', {
succesfulyRegistered: registeredModules.length + ' / ' + modules.length,
registrationOrder: registeredModules
}
)()
export {
VSF,
VueStorefrontModuleConfig,
extendModule,
VueStorefrontModule,
registerModules,
isModuleRegistered,
createModule
}
24 changes: 24 additions & 0 deletions core/lib/module/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Module, Store } from 'vuex'
import { RouteConfig, NavigationGuard } from 'vue-router'
import { VueConstructor } from 'vue'
import RootState from '@vue-storefront/core/types/RootState'

interface VSF {
Vue?: VueConstructor,
config?: Object,
store?: Store<RootState>,
isServer?: boolean
}

interface VueStorefrontModuleConfig {
key: string;
store?: { modules?: { key: string, module: Module<any, any> }[], plugin?: Function };
router?: { routes?: RouteConfig[], beforeEach?: NavigationGuard, afterEach?: NavigationGuard },
beforeRegistration?: (VSF: VSF | VueConstructor, config?: Object, store?: Store<RootState>, isServer?: boolean) => void,
afterRegistration?: (VSF: VSF | VueConstructor, config?: Object, store?: Store<RootState>, isServer?: boolean) => void,
}

export {
VSF,
VueStorefrontModuleConfig
}
9 changes: 3 additions & 6 deletions core/modules/breadcrumbs/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { module } from './store'
import { VueStorefrontModule, VueStorefrontModuleConfig } from '@vue-storefront/core/lib/module'
import { createModule } from '@vue-storefront/core/lib/module'

export const KEY = 'breadcrumbs'

const moduleConfig: VueStorefrontModuleConfig = {
export const Breadcrumbs = createModule({
key: KEY,
store: { modules: [
{ key: KEY, module: module }
] },
}

export const Breadcrumbs = new VueStorefrontModule(moduleConfig)
})
9 changes: 3 additions & 6 deletions core/modules/cart/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { module } from './store'
import { VueStorefrontModule, VueStorefrontModuleConfig } from '@vue-storefront/core/lib/module'
import { createModule } from '@vue-storefront/core/lib/module'
import { beforeRegistration } from './hooks/beforeRegistration'
import { afterRegistration } from './hooks/afterRegistration'

export const KEY = 'cart'

const moduleConfig: VueStorefrontModuleConfig = {
export const Cart = createModule({
key: KEY,
store: { modules: [{ key: KEY, module }] },
beforeRegistration,
afterRegistration
}

export const Cart = new VueStorefrontModule(moduleConfig)
})
9 changes: 3 additions & 6 deletions core/modules/catalog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { attributeModule } from './store/attribute'
import { stockModule } from './store/stock'
import { taxModule } from './store/tax'
import { categoryModule } from './store/category'
import { VueStorefrontModule, VueStorefrontModuleConfig } from '@vue-storefront/core/lib/module'
import { createModule } from '@vue-storefront/core/lib/module'
import { beforeRegistration } from './hooks/beforeRegistration'

export const KEY = 'catalog'

const moduleConfig: VueStorefrontModuleConfig = {
export const Catalog = createModule({
key: KEY,
store: { modules: [
{ key: 'product', module: productModule },
Expand All @@ -18,6 +17,4 @@ const moduleConfig: VueStorefrontModuleConfig = {
{ key: 'category', module: categoryModule }
] },
beforeRegistration
}

export const Catalog = new VueStorefrontModule(moduleConfig)
})
10 changes: 3 additions & 7 deletions core/modules/checkout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { paymentModule } from './store/payment'
import { shippingModule } from './store/shipping'
import { beforeRegistration } from './hooks/beforeRegistration'
import { afterRegistration } from './hooks/afterRegistration'

import { VueStorefrontModule, VueStorefrontModuleConfig } from '@vue-storefront/core/lib/module'
import { createModule } from '@vue-storefront/core/lib/module'

export const KEY = 'checkout'

const moduleConfig: VueStorefrontModuleConfig = {
export const Checkout = createModule({
key: KEY,
store: { modules: [
{ key: 'shipping', module: shippingModule },
Expand All @@ -17,6 +15,4 @@ const moduleConfig: VueStorefrontModuleConfig = {
] },
beforeRegistration,
afterRegistration
}

export const Checkout = new VueStorefrontModule(moduleConfig)
})
9 changes: 3 additions & 6 deletions core/modules/cms/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import { cmsPageModule } from './store/page'
import { cmsBlockModule } from './store/block'
import { cmsHierarchyModule } from './store/hierarchy'
import { VueStorefrontModule, VueStorefrontModuleConfig } from '@vue-storefront/core/lib/module'
import { createModule } from '@vue-storefront/core/lib/module'
import { beforeRegistration } from './hooks/beforeRegistration'
import { plugin } from './store/plugin'
import { initCacheStorage } from '@vue-storefront/core/helpers/initCacheStorage';

export const KEY = 'cms'
export const cacheStorage = initCacheStorage(KEY)

const moduleConfig: VueStorefrontModuleConfig = {
export const Cms = createModule({
key: KEY,
store: { modules: [
{ key: 'cmsPage', module: cmsPageModule },
{ key: 'cmsBlock', module: cmsBlockModule },
{ key: 'cmsHierarchy', module: cmsHierarchyModule }
], plugin },
beforeRegistration
}

export const Cms = new VueStorefrontModule(moduleConfig)
})
Loading

0 comments on commit 8a68a38

Please sign in to comment.