Skip to content
This repository was archived by the owner on Feb 12, 2022. It is now read-only.

Commit 96fcda3

Browse files
anndiep-sfccsf-zsardoneab-kapechessmanBret Little
authored
Integration (#206)
* Update the link on homepage (#111) * New: sampleApp - Document Product Search Result and Home components (W-7156928) * bug: fix ux (W-7208631) * bug: fix ux (W-7208228) * Don't send private values to the browser via apiconfig.js * Fix the prod build to work on first run The sass styles need to be compiled first, otherwise LWC won't pickup the output CSS and add them to the final bundle. * Remove data-sources functionality * Initial PoC for @sfcc-core/core * Fix license Signed-off-by: Bret Little <[email protected]> * Logger implementation * Add tests to logger * Migrate the remainder of core to typescript * Add typescript configuration files to version control * Cleanup types (remove some any's) * add component extension readme (#120) * Paul's edits to Zi's componentExtension.md file. * minor updates (#123) * Cleanup * Switch to interfaces * new: Search - Keyword Search Encoding for Security Best Practices (W-6984514) * new: Search - Keyword Search Encoding for Security Best Practices (W-6984514) (#126) * Breaking: replace product detial wire adaptor with lwc-apollo-client * Update: sampleApp - Update to SDK 1.3.0-alpha.8. Update PDP and product search to use new authentication and product search refinement (W-7241436) * Bug: Fixed issue on PDP where strike through price appears when there is no sale price (W-7162332) * chore: get product search sorting rules from BFF (W-7034305) * edit: acknowledged Ozzy's comments (W-7034305) * Adding Cart Services & Authentication (#135) New: Session Management & Cart Authentication * edit: acknowledged Zi's comment on keyword-search-encoding * edit: acknowledged Zi's comment on keyword-search-encoding * removing conflicts after rebase edit: acknowledged Ozzy's comments (W-7034305) edit: acknowledged Zi's comment on keyword-search-encoding edit: acknowledged Zi's comment on keyword-search-encoding * edit: resolved merge conflicts, acknowledged Zi's keyword encoding comment * edit: reorder import graphqlPassport * edit: yarn.lock upgrade * edit: cartResolvers.js empty object linting issue * edit: productDetailsResolvers.js empty object linting issue * fix: cart.js, productDetail.js linting issue * edit: acknowledged Evan's comment on router.js * Bug: Fix the TypeScript definitions inside core (#141) * Fix running the app on windows by adding cross-env Fixes #127 * New: update Cart UX initial commit (#142) * New: Rename cart functionality to basket and move to TypeScript * Propogate error from authenticate middleware * Fix fix building on windows (#147) Co-authored-by: Gurpreet Saini <[email protected]> * Chore: fix linting problems throughout the typescript source (#149) * Fix cross env to be a main dependency (#154) Cannot be a dev dependency because it is used in the main startup * new: search no result page clean up (W-7246249) * new: search no result page clean-up * new: search no result page should be cleaned up (W-7246249) * edit: acknowledged Bret's comments on PR * edit: empty div rendered when loading products * New(storefront-lwc): add bundle analysis to the deployment (#155) * edit: text changes addressing Paul's feedback * Update(@sfcc-bff) commerce-sdk to v1.3.0-alpha.9 (#157) * Fix the build by removing deploy to heroku Heroku already is hooked into the git repo and will deploy independent of circle ci * Chore: adding a list of library components to README * update readme (#148) * Fix(storefront-lwc) remove innerHTML in favor of imperative dom creation (#160) This should resolve some of the XSS concerns * New: Show empty cart view (W-7114838) * Bug: Fixed hyberlink on need help message. * New: Remove Product from Basket (#163) New: Remove Product from Basket * Update: Handle cross site scripting (W-7262039) * Chore: Performance Improvement for getBasket (#166) * NEW: Search Results to use new apollo-client * CHORE: linting pdp gql query file * New: Show Product Quantity on Header Cart (#171) New: Show Product Quantity on Header Cart * Chore: Add lint step to CircleCI config and fix lint error * Lots of cleanup (#172) * Update(storefront-lwc): remove lwc-services and use rollup directly * Chore remove mjs in favor of using esm Bug(@sfcc-bff/productapi): the default image property was defined properly Fix tests Fix lint issue on an unused expression Add linting to circle ci steps * Fix sass build and change documentation for api.js and port 3000 * Fix dev build * Paul's edits to README.md file. * Fix lint * Update rollup config * Remove lwce/router from this PR Co-authored-by: Paul DiSabito <[email protected]> Co-authored-by: Gurpreet Saini <[email protected]> * New:Basket product line item Card(W-7114827) (#170) New:Basket product line item Card(W-7114827) * minor css updates for Basket * more css cleanup * use bootstrap classes * New: Coupon add and remove functionality on cart page (W-7114978) * reset auth token on request if it has expired - remove basketid from session on product search/detail * Disable cors unless defined by an environment variable * Add documenation * Update: the error handling in basketapi, productapi, and on the client (W-7361704) (#191) * Update: Fixed some UX styling for Promo code and Order totals * Blittle add lwce router (#178) * Update(storefront-lwc): move to @lwce/router single-page-app routing * Fix(storefront-lwc): show the query in the searchbar header * Update: change the cookie to have a strict same-site policy (#195) * New: session management documentation * Paul's edits to sessionManagement.md. * Bug(storefront-lwc): Fix PDP carousel back and forward buttons (W-7361322) * Fix(storefront-lwc): build fixes (#198) 1. Fix lwc to output proper sourcemaps 2. Add live reload 3. Fix express-session warnings * New: add header component (W-7360766) * New: Replace Cart Sevice with LWC Apollo Client * Basket readme (#194) * Update(storefront-lwc): add tests for the product detail page (#203) * New: Error Handling (#197) New: Error Handling * chore(release): publish v1.0.0-alpha.2 @skip-ci@ * Fix integration (#207) * Integration (#119) * Update the link on homepage (#111) * New: sampleApp - Document Product Search Result and Home components (W-7156928) * bug: fix ux (W-7208631) * bug: fix ux (W-7208228) * Don't send private values to the browser via apiconfig.js * Fix the prod build to work on first run The sass styles need to be compiled first, otherwise LWC won't pickup the output CSS and add them to the final bundle. * Remove data-sources functionality Co-authored-by: Zi Sardone <[email protected]> Co-authored-by: anndiep-sfcc <[email protected]> Co-authored-by: Abhinav Kapoor <[email protected]> Co-authored-by: echessman <[email protected]> * New: Adding a PR checklist to the master branch Co-authored-by: echessman <[email protected]> Co-authored-by: Zi Sardone <[email protected]> Co-authored-by: anndiep-sfcc <[email protected]> Co-authored-by: Abhinav Kapoor <[email protected]> Co-authored-by: Syed Shehroz Hussain (Ozzy) <[email protected]> Co-authored-by: Zi Sardone <[email protected]> Co-authored-by: Abhinav Kapoor <[email protected]> Co-authored-by: echessman <[email protected]> Co-authored-by: Bret Little <[email protected]> Co-authored-by: Bret Little <[email protected]> Co-authored-by: Paul DiSabito <[email protected]> Co-authored-by: Jason Cooper <[email protected]> Co-authored-by: Evan Chessman <[email protected]> Co-authored-by: Gurpreet Saini <[email protected]> Co-authored-by: Alex Clark <[email protected]> Co-authored-by: Alex Clark <[email protected]> Co-authored-by: Syed Shehroz Hussain (Ozzy) <[email protected]>
1 parent ba1204f commit 96fcda3

File tree

749 files changed

+8258
-6359
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

749 files changed

+8258
-6359
lines changed

.circleci/config.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
orbs:
2+
node: circleci/[email protected]
3+
14
jobs:
25
build:
36
working_directory: ~/build_only
@@ -7,10 +10,10 @@ jobs:
710
steps:
811
- checkout
912
- run: yarn install
13+
- run: yarn lint
1014
- run: yarn build
1115
- run: yarn test
16+
- run: yarn clean:stats
1217
- store_test_results:
1318
path: ~/
14-
orbs:
15-
node: circleci/[email protected]
16-
version: 2.1
19+
version: 2.1

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ coverage
1111
*.iml
1212
jest-report
1313
yarn-error.log
14-
tsconfig.json
1514
.idea
1615

1716
**/package-lock.json

README.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,20 @@ To set up the sample application:
2323
2. Change into the `sfcc-sample-apps` folder:
2424
`cd sfcc-sample-apps`
2525

26-
3. Copy the `api.example.mjs` file located at `/packages/storefront-lwc/scripts/`, save it as `api.mjs`, and make sure `api.mjs` is added to your `.gitignore` file.
26+
3. Copy the `api.example.js` file located at `/packages/storefront-lwc/app/`, save it as `api.js`, and make sure `api.js` is added to your `.gitignore` file.
2727

28-
4. In the `api.mjs` file, provide values for the following variables (you can obtain these values from your Account Executive (AE) or Customer Support Manager (CSM)):
28+
4. In the `api.js` file, provide values for the following variables (you can obtain these values from your Account Executive (AE) or Customer Support Manager (CSM)):
2929
<table>
3030
<tr><th>Variable</th><th>Description</th></tr>
31-
<tr><td><code>COMMERCE_CLIENT_API_SITE_ID</code></td><td>A unique site ID (for example, RefArch or SiteGenesis).</td></tr>
32-
<tr><td><code>COMMERCE_CLIENT_CLIENT_ID</code></td><td>A unique ID used exclusively for API access. See <a href="https://documentation.b2c.commercecloud.salesforce.com/DOC1/topic/com.demandware.dochelp/AccountManager/AccountManagerAddAPIClientID.html">Add a Client API</a> for more information.</td></tr>
33-
<tr><td><code>COMMERCE_CLIENT_REALM_ID</code></td><td>A unique four-character ID (for example, bblx).</td></tr>
34-
<tr><td><code>COMMERCE_CLIENT_INSTANCE_ID</code></td><td>Instance ID within a realm (for example, 015).</td></tr>
35-
<tr><td><code>COMMERCE_CLIENT_SHORT_CODE</code></td><td>Region-specific merchant identifier (for example, staging-001).</td></tr>
31+
<tr><td><code>COMMERCE_CLIENT_API_SITE_ID</code></td><td>Unique site ID (for example, RefArch or SiteGenesis).</td></tr>
32+
<tr><td><code>COMMERCE_CLIENT_CLIENT_ID</code></td><td>Unique ID used exclusively for API access. See <a href="https://documentation.b2c.commercecloud.salesforce.com/DOC1/topic/com.demandware.dochelp/AccountManager/AccountManagerAddAPIClientID.html">Add a Client API</a> for more information.</td></tr>
33+
<tr><td><code>COMMERCE_CLIENT_REALM_ID</code></td><td>Unique four-character realm ID (for example, bblx).</td></tr>
34+
<tr><td><code>COMMERCE_CLIENT_INSTANCE_ID</code></td><td>Unique instance ID within a realm (for example, 015).</td></tr>
35+
<tr><td><code>COMMERCE_CLIENT_SHORT_CODE</code></td><td>Unique region-specific merchant ID (for example, staging-001).</td></tr>
36+
<tr><td><code>COMMERCE_SESSION_SECRET</code></td><td>Unique ID for session management (for example, thisisasecretkey).</td></tr>
37+
<tr><td><code>COMMERCE_CORS</code></td><td>Optionally enable <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">CORS</a> for GraphQL on the defined domains (for example, enable all domains with "\*").</td></tr>
3638
</table>
39+
Note: If the COMMERCE_SESSION_SECRET key is not unique per customer application, session information can be unintentionally shared between ecommerce sites.
3740

3841
5. Install dependencies:
3942
`yarn`
@@ -45,7 +48,7 @@ To set up the sample application:
4548
`yarn start:dev` (development mode) or
4649
`yarn start` (production mode)
4750

48-
8. To access the sample application in development mode, open the browser to http://localhost:3000 (for production mode, open to http://localhost:3002).
51+
8. To access the application, open the browser to http://localhost:3000
4952

5053
You can optionally test the sample application:
5154
`yarn test`
@@ -55,7 +58,7 @@ You can optionally test the sample application:
5558
We recommend Visual Studio Code inbuilt debugger to troubleshoot the code. The `.vscode` launch configuration is included in the repo. To debug using VSCode, see [VS Code Debugging](https://code.visualstudio.com/docs/editor/debugging).
5659

5760
## Configuration
58-
* You can change the logging levels by modifying the `COMMERCE_LOG_LEVEL` property in `api.mjs`. The supported log levels are:
61+
* You can change the logging levels by modifying the `COMMERCE_LOG_LEVEL` property in `api.js`. The supported log levels are:
5962
* `TRACE`
6063
* `DEBUG`
6164
* `INFO`
@@ -74,6 +77,14 @@ We recommend Visual Studio Code inbuilt debugger to troubleshoot the code. The `
7477
* [Jest](https://jestjs.io/docs/en/getting-started)
7578
* [Visual Studio Code](https://code.visualstudio.com/docs)
7679

80+
## Library of Components
81+
The sample app currently includes the following components:
82+
* [Home Page](https://github.com/SalesforceCommerceCloud/sfcc-sample-apps/tree/master/packages/storefront-lwc/src/modules/commerce/home)
83+
* [Product Detail](https://github.com/SalesforceCommerceCloud/sfcc-sample-apps/tree/master/packages/storefront-lwc/src/modules/commerce/productDetail)
84+
* [Product Search Results](https://github.com/SalesforceCommerceCloud/sfcc-sample-apps/tree/master/packages/storefront-lwc/src/modules/commerce/productSearchResults)
85+
* [Basket](https://github.com/SalesforceCommerceCloud/sfcc-sample-apps/tree/integration/packages/storefront-lwc/src/modules/commerce/basket)
86+
87+
7788
## Contributing
7889

7990
* See [Contributing](CONTRIBUTING.md)

docs/SessionManagement.png

49 KB
Loading

docs/architecture.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@ Data source implementation for the Salesforce Commerce API. It includes the Grap
3030
#### storefront-lwc
3131
Front-end application, built with [lwc-services](https://www.npmjs.com/package/lwc-services).
3232

33+
## Session Management
34+
35+
To learn about session management in the sample app please see [session management](sessionManagement.md)
36+
3337
## Customizing and Extending
34-
When customizing or extending the sample app, do not modify the packages within `@sfcc-bff` and `@sfcc-core`. These packages will be published and consumed via NPM. Instead, create a new custom package within the monorepo that registers itself with `@sfcc-core` and provides access to data from a third-party service.
38+
When customizing or extending the sample app, do not modify the packages within `@sfcc-bff` and `@sfcc-core`. These packages will be published and consumed via NPM. Instead, create a new custom package within the monorepo that registers itself with `@sfcc-core` and provides access to data from a third-party service. For more information, see [Component Extension](docs/componentExtension.md).
3539

3640
![Sample App Project Layout](project-layout.png)
3741

@@ -40,7 +44,7 @@ The core-graphql module within `@sfcc-core` is responsible for getting all the r
4044
## What's Not Included?
4145
This is a sample application, and is not intended to be a full reference architecture. There are multiple components missing, some of which will be added in the future. Specifically, the app does not currently include:
4246

43-
1. **Authentication** - Required for a fully functional cart and checkout experience.
47+
1. **Authentication** - Required for a fully functional basket and checkout experience.
4448
2. **CMS Integration** - Required to customize the storefront experience per user.
4549
3. **Server-side Rendering** - Required for product listing search engine optimization.
46-
4. **Component Portability** - Work needs to be done to re-use components outside of the sample app context.
50+
4. **Component Portability** - Work needs to be done to re-use components outside of the sample app context.

docs/authenticationFlow.png

36.7 KB
Loading

docs/componentExtension.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
## Customizing and Extending Components
2+
3+
As mentioned in the [architecture document](architecture.md), when customizing or extending the sample app component, you should not modify the packages within `@sfcc-bff` and `@sfcc-core`. These packages will be published and consumed via `npm`. Instead, create a new custom package either within the monorepo or a new module that registers itself with `@sfcc-core\core` and provides access to data from a third-party service. Then we will need to extend the data model and extend the query for the client component.
4+
5+
6+
This example below shows how to create a product recommendations extension for the product details component:
7+
8+
Background: The Product Details Page shows the product name, product id, color swatches, images, price, and so on. Our goal is to extend this component to also show the product's recommendations.
9+
10+
1. In the storefront-lwc `app` directory, create a new extension called `productDetailExtension.js`
11+
12+
2. In the `productDetailExtension.js` file, register the extension with core using the `API_EXTENSIONS_KEY` key. Extensions can have multiple entries per extension key, so we can simply register a new extension with the existing key:
13+
14+
```
15+
core.registerExtension(API_EXTENSIONS_KEY, function (config) {
16+
return new ProductDetailExtensions();
17+
});
18+
```
19+
20+
3. To Extend the data model, define the Recommendation type and use it to extend the Product type:
21+
22+
```
23+
const productRecommendationTypeDef = gql`
24+
type Recommendation {
25+
productId: String
26+
productName: String
27+
image: Image
28+
}
29+
extend type Product {
30+
recommendations: [Recommendation]
31+
}
32+
`;
33+
```
34+
35+
4. Resolve the recommendations for a Product
36+
```
37+
const productRecommendationResolver = (config) => {
38+
return {
39+
Product: {
40+
recommendations: async (product) => {
41+
if (product.recommendations) {
42+
return Promise.all(product.recommendations.map( async recommendation => {
43+
const apiProduct = await getClientProduct(config, recommendation.recommendedItemId);
44+
return {productId: apiProduct.id, productName:apiProduct.name, image: new Image(apiProduct.imageGroups[2].images[0])};
45+
})
46+
)
47+
}
48+
}
49+
}
50+
}
51+
}
52+
```
53+
54+
5. Add the product recommendation extension to the Backend For Frontend (BFF) by importing the extension created in step 1 to the `sample-app.js` file.
55+
```
56+
import './extension/productDetailExtension';
57+
```
58+
59+
6. To Extend the query for client component, In the `productdetailadapator.js` file, specify the query for product recommendations.
60+
```
61+
recommendations {
62+
productId
63+
productName
64+
image {
65+
title
66+
link
67+
alt
68+
}
69+
}
70+
```
71+
72+
7. In the `productdetail.html` file, consume the recommendations data (if any) returned from the BFF.
73+
```
74+
<!-- Product Recommendations -->
75+
<template if:true={product.recommendations}>
76+
<div class="recommendation">
77+
<template for:each={product.recommendations} for:item="recommendation">
78+
<div class='col-6 col-sm-4 grid-gutter' key={recommendation.productId} >
79+
<div class='product' >
80+
<commerce-product-tile product={recommendation}></commerce-product-tile>
81+
</div>
82+
</div>
83+
</template>
84+
</div>
85+
</template>
86+
```

docs/sessionManagement.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Session Management
2+
3+
When the client loads the Sample App, the Sample App is initialized with the express authentication middleware, [passportjs](http://www.passportjs.org/). After initialization, `passport.session` is invoked to generate a session. A cookie is also generated (using [express-session](https://www.npmjs.com/package/express-session) to represent the session.
4+
5+
The Sample App uses `GraphQLLocalStrategy` from the [graphql-passport](https://www.npmjs.com/package/graphql-passport) package for its authentication strategy.
6+
7+
Authentication enables end users to perform actions like creating a basket.
8+
9+
After successful authentication, the anonymous user ID is stored in the session corresponding to the generated cookie.
10+
11+
12+
## Session Management and Authentication Flow
13+
14+
![session management and authentication flow](SessionManagement.png)
15+
16+
The Sample App uses the `express-session` module to generate a unique cookie that represents the session. The default cookie used for the session ID is `connect.sid`. When the cookie expires, the module automatically creates a new one.
17+
18+
Passport middleware provides functions to serialize and deserialize a user to and from the session. As stated in the [architecture document](architecture.md), the front-end client communicates with the BFF via GraphQL. In the Sample App, every query using GraphQL uses the `/api` route. GraphQL separates queries based on resolvers in Sample App.
19+
20+
An authentication request is needed to get an access token that allows the Sample App to perform certain actions, such as creating a basket or adding products to a basket. The Sample App uses the package `graphql-passport` to provide the functionality to authenticate with passport.
21+
22+
![authentication flow](authenticationFlow.png)
23+
24+
GraphQL provides a `context` object which is the third parameter passed to any resolver. The `context` object is generated per request and can store data used by the resolver. The Sample App populates this `context` object in the `[graphql.ts](../packages/@sfcc-core/core-graphql/src/graphql.ts)` file (which is in the `core-graphql` package). The `context` function defined in `graphql.ts` takes two parameters, request (req) and response (res).
25+
26+
```typescript
27+
this.apolloServer = new ApolloServer({
28+
schema,
29+
context: ({ req, res }) => ({
30+
...graphqlPassport.buildContext({ req, res }),
31+
setSessionProperty(key: string, value: string) {
32+
(req as Request).session[key] = value;
33+
},
34+
getSessionProperty(key: string) {
35+
return (req as Request).session[key];
36+
},
37+
}),
38+
});
39+
```
40+
41+
The request parameter is the same request object that express generates and is the actual web service call that contains the request headers, cookies, and so on. In the context function, the helper function `buildContext()` (which is provided by graphql-passport) helps build a context that is unique for each user, adding methods to the context to help authenticate using passport. After the `context` object is built, a resolver can ensure that the user is authenticated.
42+
43+
The resolvers in Sample App need to retrieve the user from the context. To help with this operation, Sample App defines a function `getUserFromContext()`. This function calls the `context.authenticate()` function provided by graphql-passport.
44+
45+
```typescript
46+
export async function getUserFromContext(context: AppContext) {
47+
let user = context.getUser();
48+
const token = user ? user.token : '';
49+
if (!token) {
50+
const res = await context.authenticate('graphql-local', { token });
51+
context.login(res.user);
52+
user = res.user;
53+
}
54+
return user;
55+
}
56+
```
57+
58+
The `context.authenticate` function calls the graphql-passport strategy configured in [runtime.js](../packages/storefront-lwc/scripts/runtime.js). This is the central location to perform the authentication logic.
59+
60+
```typescript
61+
passport.use(
62+
new graphqlPassport.GraphQLLocalStrategy(function(user, pass, done) {
63+
const clientConfig = getCommerceClientConfig(config);
64+
CommerceSdk.helpers
65+
.getShopperToken(clientConfig, { type: 'guest' })
66+
.then(token => {
67+
const customerId = JSON.parse(token.decodedToken.sub)
68+
.customer_info.customer_id;
69+
done(null, {
70+
id: customerId,
71+
token: token.getBearerHeader(),
72+
});
73+
})
74+
.catch(error => done(error));
75+
}),
76+
);
77+
```
78+
79+
In Sample App’s authentication configuration, the shopper token is retrieved from the Commerce SDK. From this token, the anonymous user customer ID is determined. If authentication is successful, a user is returned containing the id and the bearer token. Following successful authentication, the `getUserFromContext()` function calls `context.login()` -- which invokes `passport.serializeUser`:
80+
81+
```typescript
82+
passport.serializeUser(function(user, done) {
83+
users.set(user.id, user);
84+
done(null, user.id);
85+
});
86+
```
87+
88+
The above function is used to serialize the user to the in-memory `users` object for the session.

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"lerna": "2.11.0",
33
"exact": true,
4-
"version": "0.18.23",
4+
"version": "1.0.0-alpha.2",
55
"npmClient": "yarn",
66
"command": {
77
"init": {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"lint": "lerna run lint --stream",
1515
"lint:fix": "lerna run lint:fix --stream",
1616
"clean": "lerna run clean --stream",
17+
"clean:stats": "lerna run clean:stats --stream",
1718
"test": "lerna run test:unit --stream",
1819
"test:watch": "lerna run test:unit:watch --stream",
1920
"start": "yarn start:lwc",
@@ -66,6 +67,6 @@
6667
}
6768
},
6869
"lint-staged": {
69-
"*.{js}": "prettier --write"
70+
"*.{js,ts,mjs}": "prettier --write"
7071
}
7172
}

0 commit comments

Comments
 (0)