Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring storeCodeFromRoute, resolve store code on SSR #3593

Merged
merged 5 commits into from
Sep 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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