Skip to content

Commit

Permalink
Merge pull request #3593 from andrzejewsky/bugfix/3576
Browse files Browse the repository at this point in the history
Refactoring storeCodeFromRoute, resolve store code on SSR
  • Loading branch information
pkarw committed Sep 24, 2019
2 parents 6115522 + 97c8472 commit b53646a
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 98 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Prevent caching storage instance in plugin module scope - @gibkigonzo (#3571)
- Fixed incorrect image sizes in related section on product page - @andrzejewsky (#3590)
- Fix typo on default language - @lorenaramonda (#3076)
- Fixed resolving store code on SSR - @andrzejewsky (#3576)
- clear user data if error occurs while login - @gibkigonzo (#3588)
- Fix loading bestsellers on 404 error page - @andrzejewsky (#3540)

Expand Down
3 changes: 2 additions & 1 deletion core/client-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import rootStore from '@vue-storefront/core/store'
import { registerSyncTaskProcessor } from '@vue-storefront/core/lib/sync/task'
import i18n from '@vue-storefront/i18n'
import omit from 'lodash-es/omit'
import { prepareStoreView, storeCodeFromRoute, currentStoreView, localizedRoute } from '@vue-storefront/core/lib/multistore'
import storeCodeFromRoute from '@vue-storefront/core/lib/storeCodeFromRoute'
import { prepareStoreView, currentStoreView, localizedRoute } from '@vue-storefront/core/lib/multistore'
import { onNetworkStatusChange } from '@vue-storefront/core/modules/offline-order/helpers/onNetworkStatusChange'
import '@vue-storefront/core/service-worker/registration' // register the service worker
import { AsyncDataLoader } from './lib/async-data-loader'
Expand Down
83 changes: 2 additions & 81 deletions core/lib/multistore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,8 @@ import VueRouter, { RouteConfig, RawLocation } from 'vue-router'
import config from 'config'
import { coreHooksExecutors } from '@vue-storefront/core/hooks'
import { StorageManager } from '@vue-storefront/core/lib/storage-manager'

export interface LocalizedRoute {
path?: string,
name?: string,
hash?: string,
params?: { [key: string]: unknown },
fullPath?: string,
host?: string
}

export interface StoreView {
storeCode: string,
extend?: string,
disabled?: boolean,
storeId: any,
name?: string,
url?: string,
appendStoreCode?: boolean,
elasticsearch: {
host: string,
index: string
},
tax: {
sourcePriceIncludesTax: boolean,
defaultCountry: string,
defaultRegion: null | string,
calculateServerSide: boolean,
userGroupId?: number,
useOnlyDefaultUserGroupId: boolean
},
i18n: {
fullCountryName: string,
fullLanguageName: string,
defaultLanguage: string,
defaultCountry: string,
defaultLocale: string,
currencyCode: string,
currencySign: string,
dateFormat: string
},
seo: {
defaultTitle: string
}
}
import { LocalizedRoute, StoreView } from './types'
import storeCodeFromRoute from './storeCodeFromRoute'

function getExtendedStoreviewConfig (storeView: StoreView): StoreView {
if (storeView.extend) {
Expand Down Expand Up @@ -117,43 +75,6 @@ export function prepareStoreView (storeCode: string): StoreView {
return storeView
}

export function storeCodeFromRoute (matchedRouteOrUrl: LocalizedRoute | RawLocation | string): string {
if (matchedRouteOrUrl) {
for (let storeCode of config.storeViews.mapStoreUrlsFor) {
const store = config.storeViews[storeCode]

// handle resolving by path
const matchingPath = typeof matchedRouteOrUrl === 'object' ? matchedRouteOrUrl.path : matchedRouteOrUrl
let normalizedPath = matchingPath // assume that matching string is a path
if (matchingPath.length > 0 && matchingPath[0] !== '/') {
normalizedPath = '/' + matchingPath
}

if (normalizedPath.startsWith(`${store.url}/`) || normalizedPath === store.url) {
return storeCode
}

// handle resolving by domain+path
let url = ''

if (typeof matchedRouteOrUrl === 'object') {
if (matchedRouteOrUrl['host']) {
url = matchedRouteOrUrl['host'] + normalizedPath
} else {
return '' // this route does not have url so there is nothing to do here
}
} else {
url = matchedRouteOrUrl as string
}

if (url.startsWith(`${store.url}/`) || url === store.url) {
return storeCode
}
}
}
return ''
}

export function removeStoreCodeFromRoute (matchedRouteOrUrl: LocalizedRoute | string): LocalizedRoute | string {
const storeCodeInRoute = storeCodeFromRoute(matchedRouteOrUrl)
if (storeCodeInRoute !== '') {
Expand Down
49 changes: 49 additions & 0 deletions core/lib/storeCodeFromRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { RawLocation } from 'vue-router'
import config from 'config'
import { LocalizedRoute } from './types'

const getNormalizedPath = (matchedRouteOrUrl) => {
const matchingPath = matchedRouteOrUrl && (matchedRouteOrUrl.path || matchedRouteOrUrl)

return matchingPath && (matchingPath.length > 0 && matchingPath[0] !== '/') ? `/${matchingPath}` : matchingPath
}

const getUrl = (matchedRouteOrUrl) => {
const normalizedPath = getNormalizedPath(matchedRouteOrUrl)

if (matchedRouteOrUrl && typeof matchedRouteOrUrl === 'object') {
if (matchedRouteOrUrl['host']) {
return matchedRouteOrUrl['host'] + normalizedPath
}

return ''
}

return matchedRouteOrUrl
}

const isMatchingByPath = (matchedRouteOrUrl, store) => {
const normalizedPath = getNormalizedPath(matchedRouteOrUrl)
return normalizedPath.startsWith(`${store.url}/`) || normalizedPath === store.url
}

const isMatchingByDomainAndPath = (matchedRouteOrUrl, store) => {
const url = getUrl(matchedRouteOrUrl)
return url.startsWith(`${store.url}/`) || url === store.url
}

const storeCodeFromRoute = (matchedRouteOrUrl: LocalizedRoute | RawLocation | string): string => {
if (!matchedRouteOrUrl) return ''

for (let storeCode of config.storeViews.mapStoreUrlsFor) {
const store = config.storeViews[storeCode]

if (isMatchingByPath(matchedRouteOrUrl, store) || isMatchingByDomainAndPath(matchedRouteOrUrl, store)) {
return storeCode
}
}

return ''
}

export default storeCodeFromRoute
4 changes: 2 additions & 2 deletions core/lib/test/unit/multistore.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import storeCodeFromRoute from '@vue-storefront/core/lib/storeCodeFromRoute'
import { LocalizedRoute } from '@vue-storefront/core/lib/types'
import {
storeCodeFromRoute,
prepareStoreView,
adjustMultistoreApiUrl,
localizedDispatcherRoute,
LocalizedRoute,
setupMultistoreRoutes,
localizedRoutePath,
localizedRouteConfig
Expand Down
43 changes: 43 additions & 0 deletions core/lib/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export interface LocalizedRoute {
path?: string,
name?: string,
hash?: string,
params?: { [key: string]: unknown },
fullPath?: string,
host?: string
}

export interface StoreView {
storeCode: string,
extend?: string,
disabled?: boolean,
storeId: any,
name?: string,
url?: string,
appendStoreCode?: boolean,
elasticsearch: {
host: string,
index: string
},
tax: {
sourcePriceIncludesTax: boolean,
defaultCountry: string,
defaultRegion: null | string,
calculateServerSide: boolean,
userGroupId?: number,
useOnlyDefaultUserGroupId: boolean
},
i18n: {
fullCountryName: string,
fullLanguageName: string,
defaultLanguage: string,
defaultCountry: string,
defaultLocale: string,
currencyCode: string,
currencySign: string,
dateFormat: string
},
seo: {
defaultTitle: string
}
}
5 changes: 2 additions & 3 deletions core/modules/url/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { router } from '@vue-storefront/core/app'
import config from 'config'
import { localizedDispatcherRoute, localizedRoute, LocalizedRoute, currentStoreView } from '@vue-storefront/core/lib/multistore'
import { LocalizedRoute } from '@vue-storefront/core/lib/types'
import { localizedDispatcherRoute, localizedRoute, currentStoreView } from '@vue-storefront/core/lib/multistore'
import { RouteConfig } from 'vue-router/types/router';
import { RouterManager } from '@vue-storefront/core/lib/router-manager'
import { Category } from 'core/modules/catalog-next/types/Category'
import { removeStoreCodeFromRoute } from '@vue-storefront/core/lib/multistore'
import { Logger } from '@vue-storefront/core/lib/logger'

export function parametrizeRouteData (routeData: LocalizedRoute, query: { [id: string]: any } | string, storeCodeInPath: string): LocalizedRoute {
Expand All @@ -20,7 +20,6 @@ function prepareDynamicRoute (routeData: LocalizedRoute, path: string): RouteCon
const userRoute = RouterManager.findByName(routeData.name)
if (userRoute) {
const normalizedPath = `${path.startsWith('/') ? '' : '/'}${path}`
const currentStoreCode = currentStoreView().storeCode
const dynamicRoute = Object.assign({}, userRoute, routeData, { path: normalizedPath, name: `urldispatcher-${normalizedPath}` })
return dynamicRoute
} else {
Expand Down
7 changes: 3 additions & 4 deletions core/modules/url/router/beforeEach.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import { Route } from 'vue-router'
import store from '@vue-storefront/core/store'
import { Logger } from '@vue-storefront/core/lib/logger'
import { processDynamicRoute, normalizeUrlPath } from '../helpers'
import { isServer } from '@vue-storefront/core/helpers'
import { currentStoreView, LocalizedRoute, localizedRoute, storeCodeFromRoute } from '@vue-storefront/core/lib/multistore'
import config from 'config'
import { currentStoreView, localizedRoute } from '@vue-storefront/core/lib/multistore'
import { LocalizedRoute } from '@vue-storefront/core/lib/types'
import { RouterManager } from '@vue-storefront/core/lib/router-manager'
import { router } from '@vue-storefront/core/app'

export const UrlDispatchMapper = async (to) => {
const routeData = await store.dispatch('url/mapUrl', { url: to.path, query: to.query })
return Object.assign({}, to, routeData)
Expand Down
3 changes: 2 additions & 1 deletion core/modules/url/store/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import queryString from 'query-string'
import config from 'config'
import SearchQuery from '@vue-storefront/core/lib/search/searchQuery'
import { preProcessDynamicRoutes, normalizeUrlPath, parametrizeRouteData } from '../helpers'
import { storeCodeFromRoute, removeStoreCodeFromRoute, currentStoreView, localizedDispatcherRouteName } from '@vue-storefront/core/lib/multistore'
import { removeStoreCodeFromRoute, currentStoreView, localizedDispatcherRouteName } from '@vue-storefront/core/lib/multistore'
import storeCodeFromRoute from '@vue-storefront/core/lib/storeCodeFromRoute'

// it's a good practice for all actions to return Promises with effect of their execution
export const actions: ActionTree<UrlState, any> = {
Expand Down
2 changes: 1 addition & 1 deletion core/modules/url/types/UrlState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LocalizedRoute } from 'core/lib/multistore'
import { LocalizedRoute } from '@vue-storefront/core/lib/types'

// This object should represent structure of your modules Vuex state
// It's a good practice is to name this interface accordingly to the KET (for example mailchimpState)
Expand Down
6 changes: 1 addition & 5 deletions core/server-entry.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import union from 'lodash-es/union'
import { createApp } from '@vue-storefront/core/app'
import { HttpError } from '@vue-storefront/core/helpers/internal'
import { storeCodeFromRoute } from '@vue-storefront/core/lib/multistore'
import storeCodeFromRoute from '@vue-storefront/core/lib/storeCodeFromRoute'
import omit from 'lodash-es/omit'
import pick from 'lodash-es/pick'
import buildTimeConfig from 'config'
Expand Down Expand Up @@ -53,10 +53,6 @@ function _ssrHydrateSubcomponents (components, store, router, resolve, reject, a
})
}

function getHostFromHeader (headers: string[]): string {
return headers ? (headers['x-forwarded-host'] !== undefined ? headers['x-forwarded-host'] : headers['host']) : null
}

export default async context => {
let storeCode = context.vs.storeCode
if (config.storeViews.multistore === true) {
Expand Down

0 comments on commit b53646a

Please sign in to comment.