-
Notifications
You must be signed in to change notification settings - Fork 212
@W-18172401 Integrate getUrlMapping on server-side navigation #2290
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
base: feature/extensibility-v2
Are you sure you want to change the base?
Changes from 167 commits
02e1334
41b34a7
87567d8
0a42f90
9b1dada
b8505d0
74ea27a
5988996
61839ff
1a8d1be
8380df6
182f7b6
babf5ab
3651f4e
efdc0c5
2d1031f
5e45dac
f178dec
cfd82eb
7b8b80b
4f30443
c78b81b
55c4415
5da9d8e
4d13fe3
8a54875
4604d76
e6542fc
7a1f51f
ddb88d2
138f44b
3bfa646
2054078
a547b24
63a9d1f
d90c79c
c67fefa
af9f3df
b002c86
bd74cf8
b84c8c3
3a9f90d
4a3a6ce
6d92af9
9f6c055
6d5fb39
0115d21
fa85193
040e3f1
86a78ed
0a7e855
9acff92
c5d924b
2206dd5
392387a
0c1bd41
08e72bd
0dbbb34
8324897
5586726
645a91f
d0ffc37
f97aaed
42879f5
b71c0b9
bb692bc
0d2ed3b
35a453e
272639f
2067892
0e44b84
1579626
806fa87
85f9516
11b5af3
6402e62
e8bba80
af93217
579bdf3
18adf16
d9b32e2
4ad2535
965a34a
6baf649
5dbe489
26da1ee
f1eab7c
0a1626c
c622823
92a1c9a
f615878
38e352f
4119cda
6677213
0058e80
fa4540a
4af8642
7fdd261
bcdcea3
7b48662
62e0060
347c486
de121c3
2152142
ab23cd6
5236d90
131f670
6e257cd
edcae1d
04ee8fb
c6be840
c8e8035
88419bf
e9c00dd
4d2587a
1de2122
38425c2
2f1a48a
2bcbbc2
7ba4d99
7c731f2
a2096c3
18a566f
0e0edcb
422bd78
7ed9fbd
e08d7ce
bab7884
c594557
794b0a3
0cd67cc
54ec28a
6d7c6a9
12b071b
fc461cd
5f5de44
ad8933a
f65cf58
876b4c2
ad6d337
f05a70a
16f461b
7aa5a85
c9a58da
b01d659
0751fd9
8017fa6
d3b5651
07d7da0
0fe9e28
90fabe5
ef43d50
03dda35
a0c8a18
5f11e34
b4a23f2
12e4116
ac3cf68
9129a42
3782fb9
6ed3ffa
0de2b6a
8382e9a
a27ce96
0096116
da93df5
b42d623
ceae1c5
78837c1
a2113da
6cfecf0
613813e
be17100
366c74b
c4a432f
cc4714b
ade541e
44dcdc7
3adf867
4b91cbd
6a1caee
93f6789
70dcfb1
1a3fda9
c78d0cd
1bdf645
83332ff
c0b0803
07598e4
75c2a0c
1d524d1
98a5011
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* | ||
| * Copyright (c) 2021, salesforce.com, inc. | ||
| * All rights reserved. | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
|
|
||
| module.exports = { | ||
| extends: [require.resolve('@salesforce/pwa-kit-dev/configs/eslint')] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| coverage | ||
| dist | ||
| generator-assets | ||
| docs | ||
| vendor | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| printWidth: 100 | ||
| singleQuote: true | ||
| semi: false | ||
| bracketSpacing: false | ||
| tabWidth: 4 | ||
| arrowParens: 'always' | ||
| trailingComma: 'none' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| :loudspeaker: Hey there, Salesforce Commerce Cloud community! | ||
|
|
||
| We’re excited to hear your thoughts on your developer experience with PWA Kit and the Composable Storefront generally! Your feedback is incredibly valuable in helping us guide our roadmap and improve our offering. | ||
|
|
||
| :clipboard: Take our quick survey here: [Survey](https://forms.gle/bUZNxQ3QKUcrjhV18) | ||
|
|
||
| Feel free to share this survey link with your colleagues, partners, or anyone who has experience with PWA Kit. Your input will help us shape the future of our development tools. | ||
|
|
||
| Thank you for being a part of our community and for your continuous support! :raised_hands: | ||
|
|
||
| # Description | ||
|
|
||
| This is a sample PWA-Kit Application Extension. The purpose of this application extensions is to show how | ||
| the Application Extensions API can be used to enhance your PWA-Kit base project. | ||
|
|
||
| # Folder Structure | ||
|
|
||
| This directory contains the PWA Kit Application Extension base files and structure. It includes the following files: | ||
| ``` | ||
| ├── src | ||
| │ ├── setup-server.ts | ||
| │ └── setup-client.ts | ||
| └── dev | ||
| ``` | ||
|
|
||
| 1. `src/setup-server.ts`: The server-side setup function for the extension. | ||
| 2. `src/setup-client.ts`: The client-side setup function for the extension. | ||
| 3. `dev/`: PWA Kit App TypeScript template project used for developing the generated PWA Kit App Extension. | ||
|
|
||
| # Peer Dependencies | ||
|
|
||
| PWA-Kit Application Extensions are NPM packages at their most simplest form, and as such you can define | ||
| what peer dependencies are required when using it. Because this sample application extension provides | ||
| UI via a new "Sample" page, it requires that the below dependencies are installed at a minimum. | ||
|
|
||
| Depending on what features your application extensions provides it's recommended you include any third-party | ||
| packages as peer dependencies so that your base application doesn't end up having multiple versions of a | ||
| given package. | ||
|
|
||
| "react": "^18.2.0", | ||
| "react-dom": "^18.2.0" | ||
|
|
||
| # Configuration | ||
|
|
||
| This section is optional and will depend on your application extensions implementation. If you have features | ||
| that are configurable, then list those configurations here so that the PWA-Kit project implementor can configure | ||
| the extension as they like. | ||
|
|
||
| ``` | ||
| { | ||
| path: '/sample-page' | ||
| } | ||
| ``` | ||
|
|
||
| # Installation | ||
|
|
||
| ``` | ||
| > npm install @salesforce/extension-starter<br/> | ||
| > Downloading npm package... <br/> | ||
| > Installing extension... <br/> | ||
| > Finished. <br/> | ||
| > Congratulations! The Sample extension was successfully installed! Please visit https://www.npmjs.com/package/@salesforce/extension-starter for more information on how to use this extension. | ||
| ``` | ||
|
|
||
| # State Management | ||
|
|
||
| By default all extensions are enhanced with state management using the `withApplicationExtensionStore` higher-order component. Under the hood | ||
| the state is provided using [Zustand](https://www.npmjs.com/package/zustand) as a global store for the entire PWA-Kit application. | ||
| Each Application Extension inserts a "slice" into this global store following the | ||
| [slicing pattern](https://github.com/pmndrs/zustand/blob/37e1e3f193a5e5dec6fbd0f07514aec59a187e01/docs/guides/slices-pattern.md). | ||
| This allows you to have data separation from one extension to the other, but also allows you to access state and associated actions of other extensions when needed. | ||
|
|
||
| You can access the state of other extensions via the global store. Below is an example of why you might want to access state and actions from another extensions. In the following snippet we use the global store to access actions from the store locator. You can then use these actions as you please. | ||
|
|
||
| This is how you would do something like this. | ||
|
|
||
| ``` | ||
| // /base-project/app/components/my-component.jsx | ||
| import {useApplicationExtensionsStore} from '@salesforce/pwa-kit-extension-sdk/react' | ||
|
|
||
| export MyComponent = () => { | ||
| // Zustand V5 requires stable selector outputs. E.g. Do NOT return a new reference in your selectors return value. This will | ||
| // cause infinite re-renders. | ||
| const defaultState = {} | ||
|
|
||
| // Grab the slice of the extension state for "extension-a" | ||
| const {toggleMapsModal} = useApplicationExtensionsStore( | ||
| (state) => | ||
| state.state['@salesforce/extension-store-locator'] || defaultState | ||
| ) | ||
|
|
||
| return ( | ||
| <div> | ||
| <button onClick={() => toggleMapsModal()}/> | ||
| </div> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| # Advanced Usage | ||
|
|
||
| As an application extension developer you are responsible for documenting how your extension works including basic usage, its configuration, and advanced customization via overrides. Use this section to explain how your extension can use overrides to accomplish this. Make should to include what files are overridable as well as their expected inputs and outputs. | ||
|
|
||
| ## Overridable Files | ||
|
|
||
| ``` | ||
| /src/path/to/overridable/files.ts | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /* | ||
| * Copyright (c) 2021, salesforce.com, inc. | ||
| * All rights reserved. | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
| module.exports = require('@salesforce/pwa-kit-dev/configs/babel/babel-config') |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # Extension Configuration 🧩 | ||
|
|
||
| In most cases it's beneficial to make your application extension configurable. This will allow your extension to meet the needs of different PWA-Kit developers whom have varying requirements. This can be as simple as configuring the url path to the page your extension adds, to more complex scenarios like configuring layouts to those same pages. | ||
|
|
||
|
|
||
| ## `Sample` vs `Default` Configurations | ||
|
|
||
| This folder is home to two configuration files, `default.json` and `sample.json`. Both of which have their type define in the `src/types/config` file. But these files are used differently. Below is a summary of how each file is used. | ||
|
|
||
| ### `default.json` | ||
|
|
||
| This configuration is used during the project generation as well as the extensions loading phase when running your PWA-Kit application. | ||
|
|
||
| During your PWA-Kit project generation, you can select which extensions are configured for your app. This ultimately leads to your applications configuration being setup with the extensions selected during the project questionnaire phase. For example, if you were to choose to use `@salesforce/extension-chakra-storefront` in your PWA-Kit app, then you might see something along the lines of this in your app config, where `<user_defined_configuration>` is initially set to the contents of the `default.json` file: | ||
|
|
||
| ``` | ||
| app: { | ||
| extensions: [ | ||
| ['@salesforce/extension-chakra-storefront', <user_defined_configuration>] | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| Additionally, during the PWA-Kit application execution the default configuration is merged with the user define configuration to ensure that all configuration key have a value. This means that you do not have to worry about scattering default values in your extensions code, whether it's in a React component or the setup files. | ||
|
|
||
| It's worth noting that if your configuration file is expected to have values supplied by the PWA-Kit application developer, you can use placeholder values that will prompt the developer to replace them with real world values. Below is an example default config file with a placeholder: | ||
|
|
||
| ``` | ||
| { | ||
| "enabled": true, | ||
| "activeDataEnabled": false, | ||
| "categoryNav": { | ||
| "defaultNavSsrDepth": 1, | ||
| "defaultRootCategory": "root" | ||
| }, | ||
| "commerceAPI": { | ||
| "proxyPath": "/mobify/proxy/api", | ||
| "parameters": { | ||
| "clientId": "<CLIENT_ID>", | ||
| "organizationId": "<ORGANIZATION_ID>", | ||
| "shortCode": "<SHORT_CODE>", | ||
| "siteId": "<SITE_ID>" | ||
| } | ||
| }, | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
| ### `sample.json` | ||
|
|
||
| This configuration is similar in many ways to the one above, with the primary difference being that you cannot use placeholder values in it. The configuration is expected to have all its properties defined with valid values. | ||
|
|
||
| This configuration file is used internally by the PWA-Kit create-app application whenever a project is generated using a preset. This allows us to create E2E tests on our CI environment where we know that a project generated can be run without further modification to the configuration file. | ||
|
|
||
| We also recommend that you reference this configuration file from your extensions root README so that developers know what a valid configuration looks like. | ||
|
|
||
| ## How to use your extension configuration? | ||
|
|
||
| Your extensions configuration can be used in different ways depending on the context in which you want to use it. Your configuration will primarily be used in two places, your React components and your extension setup files. | ||
|
|
||
| ### Setup Files | ||
|
|
||
| The exported extension classes in `setup-app.ts` and `setup-server.ts` are extended from the `ApplicationExtension` class. This class provide a method called `getConfig` which returns the configuration your extension was instantiated with. you can use this method to grab the configuration and use it however you want. | ||
|
|
||
| Please refer to the `src/setup-app.ts` file to see a sample of how `getConfig` is being used in the `getRoutes` implementation. | ||
|
|
||
| ### React Components | ||
|
|
||
| Every application extension generated will have a convenience hook scaffolded for you located at `src/hooks/use-extension-config`. You can use this hook in any pages, components, or other hooks that you add to your extension. Below is an example component that uses this hook: | ||
|
|
||
| ``` | ||
| // src/components/sample-component.tsx | ||
| import React from 'react' | ||
| import {useExtensionConfig} from '../hooks/use-extension-config' | ||
|
|
||
| export const Sample = (): JSX.Element => { | ||
| const {path} = useExtensionConfig() | ||
|
|
||
| return ( | ||
| <span>{path}<span/> | ||
| ) | ||
| } | ||
|
|
||
| export default Sample | ||
| ``` | ||
|
|
||
| ### Other Contexts | ||
|
|
||
| If you plan on using the extension configuration in other contexts such as utility files, we recommend that you use dependency injection whenever possible. Passing in the configuration to these utilities will not only be a simple solution, but it will also make testing these utilities easier if you choose to do that. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "enabled": true, | ||
| "path": "/sample-page", | ||
| "commerceAPI": { | ||
| "proxyPath": "/mobify/proxy/api", | ||
| "parameters": { | ||
| "clientId": "c9c45bfd-0ed3-4aa2-9971-40f88962b836", | ||
| "organizationId": "f_ecom_zzrf_001", | ||
| "shortCode": "8o7m175y", | ||
| "siteId": "RefArchGlobal" | ||
| } | ||
| }, | ||
| "commerceAPIAuth": { | ||
| "propertyNameInLocals": "commerceAPIAuth" | ||
|
||
| }, | ||
| "resourceTypeToComponentMap": { | ||
| "category": "ProductList", | ||
| "product": "ProductDetail" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "id": "@salesforce/extension-commerce-seo-bm" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| * Copyright (c) 2025, salesforce.com, inc. | ||
| * All rights reserved. | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| const base = require('@salesforce/pwa-kit-dev/configs/jest/jest.config.js') | ||
|
|
||
| module.exports = { | ||
| ...base, | ||
| moduleNameMapper: { | ||
| ...base.moduleNameMapper, | ||
|
|
||
| // handle pwa-kit extensibility special import | ||
| '^overridable!(.*)': '$1' | ||
|
Comment on lines
+16
to
+17
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No action required, but we might want to move this somewhere reusable so it doesn't show up in all the extensions. A simple solution would be to have a special config like '@salesforce/pwa-kit-dev/configs/jest/jest.config-extension.js') |
||
| }, | ||
| coverageThreshold: { | ||
| global: { | ||
| branches: 87, | ||
| functions: 100, | ||
| lines: 100, | ||
| statements: 100 | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these all valid entries?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was copied from
extension-starterand I see that the other extensions have the same entries. However it does seem like these 3 entries don't exist