@riosst100/pwa-marketplace 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +16 -0
- package/src/Utilities/graphQL.js +76 -0
- package/src/componentOverrideMapping.js +11 -0
- package/src/components/Header/websiteSwitcher.js +109 -0
- package/src/components/Header/websiteSwitcher.module.css +111 -0
- package/src/components/Header/websiteSwitcher.shimmer.js +6 -0
- package/src/components/Header/websiteSwitcherItem.js +47 -0
- package/src/components/Header/websiteSwitcherItem.module.css +20 -0
- package/src/index.js +7 -0
- package/src/intercept.js +50 -0
- package/src/moduleOverrideWebpackPlugin.js +71 -0
- package/src/overwrites/peregrine/lib/talons/Adapter/useAdapter.js +208 -0
- package/src/overwrites/peregrine/lib/talons/Header/storeSwitcher.gql.js +45 -0
- package/src/overwrites/peregrine/lib/talons/Header/useStoreSwitcher.js +204 -0
- package/src/overwrites/pwa-buildpack/lib/queries/getAvailableStoresConfigData.graphql +11 -0
- package/src/overwrites/venia-ui/lib/components/Adapter/adapter.js +110 -0
- package/src/overwrites/venia-ui/lib/components/Header/header.js +116 -0
- package/src/overwrites/venia-ui/lib/components/Header/storeSwitcher.js +118 -0
- package/src/overwrites/venia-ui/lib/components/Header/switcherItem.js +47 -0
- package/src/overwrites/venia-ui/lib/components/StoreCodeRoute/storeCodeRoute.js +75 -0
- package/src/queries/getAvailableWebsitesConfigData.graphql +14 -0
- package/src/queries/index.js +30 -0
- package/src/talons/Header/useWebsiteSwitcher.js +219 -0
- package/src/talons/Header/websiteSwitcher.gql.js +45 -0
- package/src/talons/WebsiteByIp/getWebsiteByIp.gql.js +14 -0
- package/src/talons/WebsiteByIp/useWebsiteByIp.js +33 -0
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@riosst100/pwa-marketplace",
|
|
3
|
+
"author": "riosst100@gmail.com",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"pwa-studio": {
|
|
7
|
+
"targets": {
|
|
8
|
+
"intercept": "src/intercept.js"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"axios": "^1.6.5"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"private": false
|
|
16
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const debug = require('@magento/pwa-buildpack/lib/util/debug').makeFileLogger(__filename);
|
|
2
|
+
|
|
3
|
+
const fetch = require('node-fetch');
|
|
4
|
+
const graphQLQueries = require('@riosst100/pwa-multi-website/src/queries');
|
|
5
|
+
const https = require('https');
|
|
6
|
+
|
|
7
|
+
// To be used with `node-fetch` in order to allow self-signed certificates.
|
|
8
|
+
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
9
|
+
|
|
10
|
+
const fetchQuery = query => {
|
|
11
|
+
const targetURL = new URL('graphql', process.env.MAGENTO_BACKEND_URL);
|
|
12
|
+
const headers = {
|
|
13
|
+
'Content-Type': 'application/json',
|
|
14
|
+
'Accept-Encoding': 'gzip',
|
|
15
|
+
Accept: 'application/json',
|
|
16
|
+
'User-Agent': 'pwa-buildpack',
|
|
17
|
+
Host: targetURL.host
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (process.env.STORE_VIEW_CODE) {
|
|
21
|
+
headers['store'] = process.env.STORE_VIEW_CODE;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
debug('Fetching query: %s', query);
|
|
25
|
+
|
|
26
|
+
return fetch(targetURL.toString(), {
|
|
27
|
+
agent: targetURL.protocol === 'https:' ? httpsAgent : null,
|
|
28
|
+
body: JSON.stringify({ query }),
|
|
29
|
+
headers: headers,
|
|
30
|
+
method: 'POST'
|
|
31
|
+
})
|
|
32
|
+
.then(result => {
|
|
33
|
+
debug('Result received');
|
|
34
|
+
debug('Status: %s', result.status);
|
|
35
|
+
|
|
36
|
+
return result.json();
|
|
37
|
+
})
|
|
38
|
+
.catch(err => {
|
|
39
|
+
debug('Error received: %s', err);
|
|
40
|
+
|
|
41
|
+
console.error(err);
|
|
42
|
+
|
|
43
|
+
throw err;
|
|
44
|
+
})
|
|
45
|
+
.then(json => {
|
|
46
|
+
if (json && json.errors && json.errors.length > 0) {
|
|
47
|
+
console.warn(
|
|
48
|
+
'\x1b[36m%s\x1b[0m',
|
|
49
|
+
'As of version 12.1.0, PWA Studio requires the appropriate PWA metapackage to be installed on the backend.\n' +
|
|
50
|
+
'For more information, refer to the 12.1.0 release notes here: https://github.com/magento/pwa-studio/releases/tag/v12.1.0'
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return Promise.reject(
|
|
54
|
+
new Error(
|
|
55
|
+
json.errors[0].message +
|
|
56
|
+
` (... ${json.errors.length} errors total)`
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return json.data;
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* An async function that will fetch the availableStores
|
|
67
|
+
*
|
|
68
|
+
* @returns Promise
|
|
69
|
+
*/
|
|
70
|
+
const getAvailableWebsitesConfigData = () => {
|
|
71
|
+
return fetchQuery(graphQLQueries.getAvailableWebsitesConfigData);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
getAvailableWebsitesConfigData
|
|
76
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = componentOverrideMapping = {
|
|
2
|
+
[`@magento/venia-ui/lib/components/Adapter/adapter.js`]: '@riosst100/pwa-multi-website/src/overwrites/venia-ui/lib/components/Adapter/adapter.js',
|
|
3
|
+
[`@magento/venia-ui/lib/components/Header/header.js`]: '@riosst100/pwa-multi-website/src/overwrites/venia-ui/lib/components/Header/header.js',
|
|
4
|
+
[`@magento/venia-ui/lib/components/Header/storeSwitcher.js`]: '@riosst100/pwa-multi-website/src/overwrites/venia-ui/lib/components/Header/storeSwitcher.js',
|
|
5
|
+
[`@magento/venia-ui/lib/components/Header/switcherItem.js`]: '@riosst100/pwa-multi-website/src/overwrites/venia-ui/lib/components/Header/switcherItem.js',
|
|
6
|
+
[`@magento/venia-ui/lib/components/StoreCodeRoute/storeCodeRoute.js`]: '@riosst100/pwa-multi-website/src/overwrites/venia-ui/lib/components/StoreCodeRoute/storeCodeRoute.js',
|
|
7
|
+
[`@magento/peregrine/lib/talons/Adapter/useAdapter.js`]: '@riosst100/pwa-multi-website/src/overwrites/peregrine/lib/talons/Adapter/useAdapter.js',
|
|
8
|
+
[`@magento/peregrine/lib/talons/Header/useStoreSwitcher.js`]: '@riosst100/pwa-multi-website/src/overwrites/peregrine/lib/talons/Header/useStoreSwitcher.js',
|
|
9
|
+
[`@magento/peregrine/lib/talons/Header/storeSwitcher.gql.js`]: '@riosst100/pwa-multi-website/src/overwrites/peregrine/lib/talons/Header/storeSwitcher.gql.js',
|
|
10
|
+
[`@magento/pwa-buildpack/lib/queries/getAvailableStoresConfigData.graphql`]: '@riosst100/pwa-multi-website/src/overwrites/pwa-buildpack/lib/queries/getAvailableStoresConfigData.graphql'
|
|
11
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shape, string } from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import { useWebsiteSwitcher } from '@riosst100/pwa-multi-website/src/talons/Header/useWebsiteSwitcher';
|
|
5
|
+
import { availableRoutes } from '@magento/venia-ui/lib/components/Routes/routes';
|
|
6
|
+
|
|
7
|
+
import { useStyle } from '@magento/venia-ui/lib/classify';
|
|
8
|
+
import defaultClasses from './websiteSwitcher.module.css';
|
|
9
|
+
import WebsiteSwitcherItem from './websiteSwitcherItem';
|
|
10
|
+
import Shimmer from './websiteSwitcher.shimmer';
|
|
11
|
+
|
|
12
|
+
const WebsiteSwitcher = props => {
|
|
13
|
+
const {
|
|
14
|
+
availableStores,
|
|
15
|
+
currentGroupName,
|
|
16
|
+
currentWebsiteName,
|
|
17
|
+
handleSwitchWebsite,
|
|
18
|
+
storeGroups,
|
|
19
|
+
storeMenuRef,
|
|
20
|
+
storeMenuTriggerRef,
|
|
21
|
+
storeMenuIsOpen,
|
|
22
|
+
handleTriggerClick
|
|
23
|
+
} = useWebsiteSwitcher({ availableRoutes });
|
|
24
|
+
|
|
25
|
+
const classes = useStyle(defaultClasses, props.classes);
|
|
26
|
+
const menuClassName = storeMenuIsOpen ? classes.menu_open : classes.menu;
|
|
27
|
+
|
|
28
|
+
if (!availableStores) return <Shimmer />;
|
|
29
|
+
|
|
30
|
+
if (availableStores.size <= 1) return null;
|
|
31
|
+
|
|
32
|
+
const groups = [];
|
|
33
|
+
const hasOnlyOneGroup = storeGroups.size === 1;
|
|
34
|
+
|
|
35
|
+
storeGroups.forEach((group, key) => {
|
|
36
|
+
const stores = [];
|
|
37
|
+
group.forEach(({ storeGroupName, websiteCode, websiteName, isCurrent, storeCode }) => {
|
|
38
|
+
let label = `${websiteName}`;
|
|
39
|
+
stores.push(
|
|
40
|
+
<li
|
|
41
|
+
aria-selected={currentWebsiteName}
|
|
42
|
+
role="option"
|
|
43
|
+
key={storeCode}
|
|
44
|
+
className={classes.menuItem}
|
|
45
|
+
data-cy="WebsiteSwitcher-view"
|
|
46
|
+
>
|
|
47
|
+
<WebsiteSwitcherItem
|
|
48
|
+
active={isCurrent}
|
|
49
|
+
onClick={handleSwitchWebsite}
|
|
50
|
+
option={storeCode}
|
|
51
|
+
option2={websiteCode}
|
|
52
|
+
>
|
|
53
|
+
{label}
|
|
54
|
+
</WebsiteSwitcherItem>
|
|
55
|
+
</li>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
groups.push(
|
|
60
|
+
<ul
|
|
61
|
+
role="listbox"
|
|
62
|
+
className={classes.groupList}
|
|
63
|
+
key={key}
|
|
64
|
+
data-cy="WebsiteSwitcher-group"
|
|
65
|
+
>
|
|
66
|
+
{stores}
|
|
67
|
+
</ul>
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
let triggerLabel = `${currentWebsiteName}`;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div className={classes.root} data-cy="WebsiteSwitcher-root">
|
|
75
|
+
<button
|
|
76
|
+
data-cy="WebsiteSwitcher-triggerButton"
|
|
77
|
+
className={classes.trigger}
|
|
78
|
+
aria-label={currentWebsiteName || ''}
|
|
79
|
+
onClick={handleTriggerClick}
|
|
80
|
+
ref={storeMenuTriggerRef}
|
|
81
|
+
data-cy="WebsiteSwitcher-trigger"
|
|
82
|
+
aria-expanded={storeMenuIsOpen}
|
|
83
|
+
>
|
|
84
|
+
{triggerLabel}
|
|
85
|
+
</button>
|
|
86
|
+
<div
|
|
87
|
+
ref={storeMenuRef}
|
|
88
|
+
className={menuClassName}
|
|
89
|
+
data-cy="WebsiteSwitcher-menu"
|
|
90
|
+
>
|
|
91
|
+
<div className={classes.groups}>{groups}</div>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default WebsiteSwitcher;
|
|
98
|
+
|
|
99
|
+
WebsiteSwitcher.propTypes = {
|
|
100
|
+
classes: shape({
|
|
101
|
+
groupList: string,
|
|
102
|
+
groups: string,
|
|
103
|
+
menu: string,
|
|
104
|
+
menu_open: string,
|
|
105
|
+
menuItem: string,
|
|
106
|
+
root: string,
|
|
107
|
+
trigger: string
|
|
108
|
+
})
|
|
109
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
composes: grid from global;
|
|
3
|
+
composes: items-center from global;
|
|
4
|
+
composes: justify-items-start from global;
|
|
5
|
+
composes: max-w-site from global;
|
|
6
|
+
composes: mx-auto from global;
|
|
7
|
+
composes: my-0 from global;
|
|
8
|
+
composes: px-xs from global;
|
|
9
|
+
composes: py-2xs from global;
|
|
10
|
+
composes: relative from global;
|
|
11
|
+
|
|
12
|
+
composes: sm_justify-items-end from global;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.trigger {
|
|
16
|
+
composes: max-w-[15rem] from global;
|
|
17
|
+
composes: overflow-ellipsis from global;
|
|
18
|
+
composes: overflow-hidden from global;
|
|
19
|
+
composes: whitespace-nowrap from global;
|
|
20
|
+
|
|
21
|
+
composes: sm_max-w-full from global;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.menu {
|
|
25
|
+
composes: absolute from global;
|
|
26
|
+
composes: bg-white from global;
|
|
27
|
+
composes: border from global;
|
|
28
|
+
composes: border-solid from global;
|
|
29
|
+
composes: border-subtle from global;
|
|
30
|
+
composes: bottom-md from global;
|
|
31
|
+
composes: left-xs from global;
|
|
32
|
+
composes: max-w-[90vw] from global;
|
|
33
|
+
composes: opacity-0 from global;
|
|
34
|
+
composes: pb-2xs from global;
|
|
35
|
+
composes: pt-2xs from global;
|
|
36
|
+
composes: right-auto from global;
|
|
37
|
+
composes: rounded from global;
|
|
38
|
+
composes: shadow-menu from global;
|
|
39
|
+
composes: top-auto from global;
|
|
40
|
+
composes: w-max from global;
|
|
41
|
+
composes: z-menu from global;
|
|
42
|
+
transform: translate3d(0, -8px, 0);
|
|
43
|
+
transition-duration: 192ms;
|
|
44
|
+
transition-timing-function: var(--venia-global-anim-out);
|
|
45
|
+
transition-property: opacity, transform, visibility;
|
|
46
|
+
|
|
47
|
+
/* TODO @TW: review (B6) */
|
|
48
|
+
/* composes: invisible from global; */
|
|
49
|
+
visibility: hidden;
|
|
50
|
+
|
|
51
|
+
composes: sm_bottom-auto from global;
|
|
52
|
+
composes: sm_left-auto from global;
|
|
53
|
+
composes: sm_right-xs from global;
|
|
54
|
+
composes: sm_top-md from global;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.menu_open {
|
|
58
|
+
composes: menu;
|
|
59
|
+
|
|
60
|
+
composes: opacity-100 from global;
|
|
61
|
+
transform: translate3d(0, 4px, 0);
|
|
62
|
+
transition-duration: 224ms;
|
|
63
|
+
transition-timing-function: var(--venia-global-anim-in);
|
|
64
|
+
|
|
65
|
+
/* TODO @TW: review (B6) */
|
|
66
|
+
/* composes: visible from global; */
|
|
67
|
+
visibility: visible;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.menuItem {
|
|
71
|
+
composes: hover_bg-subtle from global;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.groups {
|
|
75
|
+
composes: max-h-[24rem] from global;
|
|
76
|
+
composes: overflow-auto from global;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.groupList {
|
|
80
|
+
composes: border-b from global;
|
|
81
|
+
composes: border-solid from global;
|
|
82
|
+
composes: border-subtle from global;
|
|
83
|
+
composes: pb-2xs from global;
|
|
84
|
+
composes: pt-2xs from global;
|
|
85
|
+
|
|
86
|
+
composes: last_border-none from global;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
* Mobile-specific styles.
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
@media (max-width: 639px) {
|
|
94
|
+
.root:only-child {
|
|
95
|
+
grid-column: 2;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* TODO @TW: cannot compose */
|
|
99
|
+
.root:last-child .menu {
|
|
100
|
+
right: 1rem;
|
|
101
|
+
left: auto;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.menu {
|
|
105
|
+
transform: translate3d(0, 8px, 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.menu_open {
|
|
109
|
+
transform: translate3d(0, -4px, 0);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { Check } from 'react-feather';
|
|
3
|
+
import { bool, func, shape, string } from 'prop-types';
|
|
4
|
+
|
|
5
|
+
import { useStyle } from '@magento/venia-ui/lib/classify';
|
|
6
|
+
import Icon from '@magento/venia-ui/lib/components/Icon/icon';
|
|
7
|
+
import defaultClasses from './websiteSwitcherItem.module.css';
|
|
8
|
+
|
|
9
|
+
const WebsiteSwitcherItem = props => {
|
|
10
|
+
const { active, onClick, option, option2, children } = props;
|
|
11
|
+
const classes = useStyle(defaultClasses, props.classes);
|
|
12
|
+
|
|
13
|
+
const handleClick = useCallback(() => {
|
|
14
|
+
onClick(option, option2);
|
|
15
|
+
}, [option, option2, onClick]);
|
|
16
|
+
|
|
17
|
+
const activeIcon = active ? (
|
|
18
|
+
<Icon data-cy="WebsiteSwitcherItem-activeIcon" size={20} src={Check} />
|
|
19
|
+
) : null;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<button
|
|
23
|
+
data-cy="WebsiteSwitcherItem-button"
|
|
24
|
+
className={classes.root}
|
|
25
|
+
disabled={active}
|
|
26
|
+
onClick={handleClick}
|
|
27
|
+
>
|
|
28
|
+
<span className={classes.content}>
|
|
29
|
+
<span className={classes.text}>{children}</span>
|
|
30
|
+
{activeIcon}
|
|
31
|
+
</span>
|
|
32
|
+
</button>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
WebsiteSwitcherItem.propTypes = {
|
|
37
|
+
active: bool,
|
|
38
|
+
classes: shape({
|
|
39
|
+
content: string,
|
|
40
|
+
root: string,
|
|
41
|
+
text: string
|
|
42
|
+
}),
|
|
43
|
+
onClick: func,
|
|
44
|
+
option: string
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default WebsiteSwitcherItem;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
composes: flex from global;
|
|
3
|
+
composes: items-center from global;
|
|
4
|
+
composes: w-full from global;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.content {
|
|
8
|
+
composes: gap-3 from global;
|
|
9
|
+
composes: grid from global;
|
|
10
|
+
composes: grid-cols-[1fr] from global;
|
|
11
|
+
composes: grid-flow-col from global;
|
|
12
|
+
composes: items-center from global;
|
|
13
|
+
composes: px-xs from global;
|
|
14
|
+
composes: py-2xs from global;
|
|
15
|
+
composes: w-full from global;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.text {
|
|
19
|
+
composes: text-left from global;
|
|
20
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom index for the extension attention this file should be not delete!
|
|
3
|
+
* It is use as main file but this can be empty by default only need to exits.
|
|
4
|
+
*
|
|
5
|
+
* A project index.js should contain default exports like:
|
|
6
|
+
* export { default } from './components/main';
|
|
7
|
+
*/
|
package/src/intercept.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const componentOverrideMapping = require('./componentOverrideMapping');
|
|
2
|
+
const moduleOverridePlugin = require('./moduleOverrideWebpackPlugin');
|
|
3
|
+
const { DefinePlugin } = require('webpack');
|
|
4
|
+
const { getAvailableWebsitesConfigData } = require('./Utilities/graphQL');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Custom intercept file for the extension
|
|
8
|
+
* By default you can only use target of @magento/pwa-buildpack.
|
|
9
|
+
*
|
|
10
|
+
* If do want extend @magento/peregrine or @magento/venia-ui
|
|
11
|
+
* you should add them to peerDependencies to your package.json
|
|
12
|
+
*
|
|
13
|
+
* If you want to add overwrites for @magento/venia-ui components you can use
|
|
14
|
+
* moduleOverrideWebpackPlugin and componentOverrideMapping
|
|
15
|
+
*/
|
|
16
|
+
module.exports = async targets => {
|
|
17
|
+
targets.of('@magento/pwa-buildpack').specialFeatures.tap(flags => {
|
|
18
|
+
/**
|
|
19
|
+
* Wee need to activated esModules and cssModules to allow build pack to load our extension
|
|
20
|
+
* {@link https://magento.github.io/pwa-studio/pwa-buildpack/reference/configure-webpack/#special-flags}.
|
|
21
|
+
*/
|
|
22
|
+
flags[targets.name] = { esModules: true, cssModules: true, graphqlQueries: true };
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
targets.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
|
|
26
|
+
new moduleOverridePlugin(componentOverrideMapping).apply(compiler);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
targets.of('@magento/pwa-buildpack').envVarDefinitions.tap((defs) => {
|
|
30
|
+
defs.sections.push({
|
|
31
|
+
name: "Default Website Code",
|
|
32
|
+
variables: [
|
|
33
|
+
{
|
|
34
|
+
name: "WEBSITE_CODE",
|
|
35
|
+
type: "str",
|
|
36
|
+
desc: "Default Website Code for Multi Website Extension",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const availableWebsites = await getAvailableWebsitesConfigData();
|
|
43
|
+
|
|
44
|
+
targets.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
|
|
45
|
+
new DefinePlugin({
|
|
46
|
+
AVAILABLE_WEBSITES: JSON.stringify(availableWebsites.availableStoresByUserIp),
|
|
47
|
+
WEBSITE_CODE: process.env.WEBSITE_CODE
|
|
48
|
+
}).apply(compiler);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
|
|
4
|
+
module.exports = class NormalModuleOverridePlugin {
|
|
5
|
+
constructor(moduleOverrideMap) {
|
|
6
|
+
this.name = 'NormalModuleOverridePlugin';
|
|
7
|
+
this.moduleOverrideMap = moduleOverrideMap;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
requireResolveIfCan(id, options = undefined) {
|
|
11
|
+
try {
|
|
12
|
+
return require.resolve(id, options);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
resolveModulePath(context, request) {
|
|
18
|
+
const filePathWithoutExtension = path.resolve(context, request);
|
|
19
|
+
const files = glob.sync(`${filePathWithoutExtension}@(|.*)`);
|
|
20
|
+
if (files.length === 0) {
|
|
21
|
+
throw new Error(`There is no file '${filePathWithoutExtension}'`);
|
|
22
|
+
}
|
|
23
|
+
if (files.length > 1) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`There is more than one file '${filePathWithoutExtension}'`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return require.resolve(files[0]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
resolveModuleOverrideMap(context, map) {
|
|
33
|
+
return Object.keys(map).reduce(
|
|
34
|
+
(result, x) => ({
|
|
35
|
+
...result,
|
|
36
|
+
[require.resolve(x)]:
|
|
37
|
+
this.requireResolveIfCan(map[x]) ||
|
|
38
|
+
this.resolveModulePath(context, map[x]),
|
|
39
|
+
}),
|
|
40
|
+
{}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
apply(compiler) {
|
|
45
|
+
if (Object.keys(this.moduleOverrideMap).length === 0) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const moduleMap = this.resolveModuleOverrideMap(
|
|
50
|
+
compiler.context,
|
|
51
|
+
this.moduleOverrideMap
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
compiler.hooks.normalModuleFactory.tap(this.name, (nmf) => {
|
|
55
|
+
nmf.hooks.beforeResolve.tap(this.name, (resolve) => {
|
|
56
|
+
if (!resolve) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const moduleToReplace = this.requireResolveIfCan(resolve.request, {
|
|
61
|
+
paths: [resolve.context],
|
|
62
|
+
});
|
|
63
|
+
if (moduleToReplace && moduleMap[moduleToReplace]) {
|
|
64
|
+
resolve.request = moduleMap[moduleToReplace];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return resolve;
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|