From 081d15e168171f8ec5a721fd13c5cdfa21b22cb8 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Fri, 10 Feb 2023 11:13:59 +0100 Subject: [PATCH] Add prettier on pre-commit & reformat codebase (#137) * Run prettier on project * Install lint-staged * Add Husky --- .husky/.gitignore | 1 + .husky/pre-commit | 4 + .prettierignore | 1 + README.md | 2 +- apps/data-importer/README.md | 2 +- apps/data-importer/saleor-app.ts | 2 +- .../customers-importer-view.tsx | 4 +- .../customers-importing-results.tsx | 6 +- apps/data-importer/src/pages/importer.tsx | 3 +- apps/data-importer/src/setup-tests.ts | 2 +- apps/invoices/README.md | 9 +- .../app-config-input-schema.test.ts | 90 +++++++++---------- .../invoice-number-generator.ts | 25 +++--- apps/search/saleor-app.ts | 2 +- .../components/AlgoliaConfigurationCard.tsx | 2 +- .../src/components/ConfigurationView.tsx | 2 +- .../components/ImportProductsToAlgolia.tsx | 2 +- apps/search/src/components/SearchBox.tsx | 50 +++++------ .../src/lib/algolia/algoliaSearchProvider.ts | 10 +-- apps/search/src/lib/algolia/algoliaUtils.ts | 2 +- apps/search/src/lib/graphql.ts | 2 +- apps/search/src/lib/metadata.ts | 2 +- apps/search/src/pages/api/configuration.ts | 6 +- .../src/pages/api/webhooks/saleor/_index.ts | 6 +- apps/search/src/pages/search/index.tsx | 2 +- apps/search/src/providers/GraphQLProvider.tsx | 2 +- package.json | 12 ++- packages/shared/src/is-in-iframe.ts | 2 +- packages/shared/src/title-bar/title-bar.tsx | 2 +- pnpm-lock.yaml | 2 + 30 files changed, 140 insertions(+), 119 deletions(-) create mode 100644 .husky/.gitignore create mode 100755 .husky/pre-commit diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..c37466e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index f7a6984..6260ee5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,3 +2,4 @@ **/pnpm-lock.yaml **/graphql/schema.graphql **/generated +.changeset/ \ No newline at end of file diff --git a/README.md b/README.md index f7234f2..fba69c2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ This repository serves as a starting point in the exploration of Saleor apps. > _Saleor apps are separate applications that use GraphQL to talk to the Saleor server and receive webhooks with event notifications from Saleor._ -> +> > [docs.saleor.io](https://docs.saleor.io/docs/3.x/developer/extending/apps/key-concepts) From here, you can visit: diff --git a/apps/data-importer/README.md b/apps/data-importer/README.md index 437057c..7ab85b4 100644 --- a/apps/data-importer/README.md +++ b/apps/data-importer/README.md @@ -2,4 +2,4 @@ # Saleor App: Data Importer -Description TBD \ No newline at end of file +Description TBD diff --git a/apps/data-importer/saleor-app.ts b/apps/data-importer/saleor-app.ts index 94573f2..e121e2c 100644 --- a/apps/data-importer/saleor-app.ts +++ b/apps/data-importer/saleor-app.ts @@ -1,5 +1,5 @@ import { SaleorApp } from "@saleor/app-sdk/saleor-app"; -import {APL, FileAPL, SaleorCloudAPL, UpstashAPL, VercelAPL} from "@saleor/app-sdk/APL"; +import { APL, FileAPL, SaleorCloudAPL, UpstashAPL, VercelAPL } from "@saleor/app-sdk/APL"; /** * By default auth data are stored in the `.auth-data.json` (FileAPL). diff --git a/apps/data-importer/src/modules/customers/customers-importer-nuvo/customers-importer-view.tsx b/apps/data-importer/src/modules/customers/customers-importer-nuvo/customers-importer-view.tsx index 6ed7c29..2d1c671 100644 --- a/apps/data-importer/src/modules/customers/customers-importer-nuvo/customers-importer-view.tsx +++ b/apps/data-importer/src/modules/customers/customers-importer-nuvo/customers-importer-view.tsx @@ -46,8 +46,8 @@ const nuvoSettings: SettingsAPI = { color: "#fff", }, }, - loader:{ - loadAnimationColor: '#000' + loader: { + loadAnimationColor: "#000", }, header: { description: { diff --git a/apps/data-importer/src/modules/customers/customers-results/customers-importing-results.tsx b/apps/data-importer/src/modules/customers/customers-results/customers-importing-results.tsx index 39ff28a..cae3fd7 100644 --- a/apps/data-importer/src/modules/customers/customers-results/customers-importing-results.tsx +++ b/apps/data-importer/src/modules/customers/customers-results/customers-importing-results.tsx @@ -13,7 +13,9 @@ export const CustomersImportingResults = ({ return (
- Customers rows from imported file + + Customers rows from imported file + Lines will be imported one by one. Failed imports can be retried, but performed operations @@ -33,7 +35,7 @@ export const CustomersImportingResults = ({ )} - +
{importedLines.map((row) => ( ({ @@ -36,7 +35,7 @@ const ImporterPage: NextPage = () => {
} + icon={} name="Data Importer" author="By Saleor Commerce" rightColumnContent={ diff --git a/apps/data-importer/src/setup-tests.ts b/apps/data-importer/src/setup-tests.ts index 5046278..5f1e198 100644 --- a/apps/data-importer/src/setup-tests.ts +++ b/apps/data-importer/src/setup-tests.ts @@ -3,4 +3,4 @@ * * https://vitest.dev/config/#setupfiles */ -export {} +export {}; diff --git a/apps/invoices/README.md b/apps/invoices/README.md index 880b7dc..5c24636 100644 --- a/apps/invoices/README.md +++ b/apps/invoices/README.md @@ -71,28 +71,31 @@ pnpm dev ### Without CLI 1. Install the dependencies by running: + ``` pnpm install ``` 2. Start the local server with: + ``` pnpm dev ``` 3. Expose local environment using tunnel: -Use tunneling tools like [localtunnel](https://github.com/localtunnel/localtunnel) or [ngrok](https://ngrok.com/). + Use tunneling tools like [localtunnel](https://github.com/localtunnel/localtunnel) or [ngrok](https://ngrok.com/). 4. Install aplication at your dashboard: If you use Saleor Cloud or your local server is exposed, you can install your app by following this link: + ``` [YOUR_SALEOR_DASHBOARD_URL]/apps/install?manifestUrl=[YOUR_APP_TUNNEL_MANIFEST_URL] ``` + This template host manifest at `/api/manifest` - -You can also install application using GQL or command line. Follow the guide [how to install your app](https://docs.saleor.io/docs/3.x/developer/extending/apps/installing-apps#installation-using-graphql-api) to learn more. +You can also install application using GQL or command line. Follow the guide [how to install your app](https://docs.saleor.io/docs/3.x/developer/extending/apps/installing-apps#installation-using-graphql-api) to learn more. ### Generated schema and typings diff --git a/apps/invoices/src/modules/app-configuration/app-config-input-schema.test.ts b/apps/invoices/src/modules/app-configuration/app-config-input-schema.test.ts index 5f880cb..ab839f3 100644 --- a/apps/invoices/src/modules/app-configuration/app-config-input-schema.test.ts +++ b/apps/invoices/src/modules/app-configuration/app-config-input-schema.test.ts @@ -1,49 +1,49 @@ -import {describe, it, expect} from "vitest"; -import {appConfigInputSchema} from "./app-config-input-schema"; -import {AppConfig, SellerShopConfig} from "./app-config"; -import {getMockAddress} from "../../fixtures/mock-address"; +import { describe, it, expect } from "vitest"; +import { appConfigInputSchema } from "./app-config-input-schema"; +import { AppConfig, SellerShopConfig } from "./app-config"; +import { getMockAddress } from "../../fixtures/mock-address"; describe("appConfigInputSchema", () => { - it('Passes with no channels at all', () => { - expect(() => - appConfigInputSchema.parse({ - shopConfigPerChannel: {} - } satisfies AppConfig) - ).not.to.throw() - }) + it("Passes with no channels at all", () => { + expect(() => + appConfigInputSchema.parse({ + shopConfigPerChannel: {}, + } satisfies AppConfig) + ).not.to.throw(); + }); - it('Passes with all address fields empty', () => { - expect(() => - appConfigInputSchema.parse({ - shopConfigPerChannel: { - channel: { - address: { - city: "", - cityArea: "", - companyName: "", - country: "", - countryArea: "", - firstName: "", - lastName: "", - postalCode: "", - streetAddress1: "", - streetAddress2: "" + it("Passes with all address fields empty", () => { + expect(() => + appConfigInputSchema.parse({ + shopConfigPerChannel: { + channel: { + address: { + city: "", + cityArea: "", + companyName: "", + country: "", + countryArea: "", + firstName: "", + lastName: "", + postalCode: "", + streetAddress1: "", + streetAddress2: "", + }, + }, + }, + } satisfies AppConfig) + ).not.to.throw(); + }); - } - } - } - } satisfies AppConfig) - ).not.to.throw() - }) - - it('Passes with partial address', () => { - expect(() => - appConfigInputSchema.parse({ - shopConfigPerChannel: { - channel: { - address: getMockAddress() } - } - } satisfies AppConfig) - ).not.to.throw() - }) -}) \ No newline at end of file + it("Passes with partial address", () => { + expect(() => + appConfigInputSchema.parse({ + shopConfigPerChannel: { + channel: { + address: getMockAddress(), + }, + }, + } satisfies AppConfig) + ).not.to.throw(); + }); +}); diff --git a/apps/invoices/src/modules/invoice-number-generator/invoice-number-generator.ts b/apps/invoices/src/modules/invoice-number-generator/invoice-number-generator.ts index ab84cff..25de828 100644 --- a/apps/invoices/src/modules/invoice-number-generator/invoice-number-generator.ts +++ b/apps/invoices/src/modules/invoice-number-generator/invoice-number-generator.ts @@ -1,19 +1,22 @@ -import {OrderPayloadFragment} from "../../../generated/graphql"; +import { OrderPayloadFragment } from "../../../generated/graphql"; interface IInvoiceNumberGenerationStrategy { - (order: OrderPayloadFragment): string; + (order: OrderPayloadFragment): string; } export const InvoiceNumberGenerationStrategy = { - localizedDate: (locale: string) => (order: Pick) => { - const orderCreatedDate = new Date(order.created); + localizedDate: (locale: string) => (order: Pick) => { + const orderCreatedDate = new Date(order.created); - return Intl.DateTimeFormat(locale,).format(orderCreatedDate) - } -} satisfies Record IInvoiceNumberGenerationStrategy> + return Intl.DateTimeFormat(locale).format(orderCreatedDate); + }, +} satisfies Record IInvoiceNumberGenerationStrategy>; export class InvoiceNumberGenerator { - generateFromOrder(order: OrderPayloadFragment, strategy: IInvoiceNumberGenerationStrategy): string { - return strategy(order) - } -} \ No newline at end of file + generateFromOrder( + order: OrderPayloadFragment, + strategy: IInvoiceNumberGenerationStrategy + ): string { + return strategy(order); + } +} diff --git a/apps/search/saleor-app.ts b/apps/search/saleor-app.ts index 755d573..59689fc 100644 --- a/apps/search/saleor-app.ts +++ b/apps/search/saleor-app.ts @@ -39,7 +39,7 @@ switch (aplType) { if (!process.env.SECRET_KEY && process.env.NODE_ENV === "production") { throw new Error( - "For production deployment SECRET_KEY is mandatory to use EncryptedSettingsManager.", + "For production deployment SECRET_KEY is mandatory to use EncryptedSettingsManager." ); } diff --git a/apps/search/src/components/AlgoliaConfigurationCard.tsx b/apps/search/src/components/AlgoliaConfigurationCard.tsx index 7449ff6..04f39b4 100644 --- a/apps/search/src/components/AlgoliaConfigurationCard.tsx +++ b/apps/search/src/components/AlgoliaConfigurationCard.tsx @@ -80,7 +80,7 @@ export const AlgoliaConfigurationCard = () => { }, }); }, - }, + } ); const onFormSubmit = handleSubmit(async (conf) => mutate(conf)); diff --git a/apps/search/src/components/ConfigurationView.tsx b/apps/search/src/components/ConfigurationView.tsx index 0f53ff1..d376666 100644 --- a/apps/search/src/components/ConfigurationView.tsx +++ b/apps/search/src/components/ConfigurationView.tsx @@ -1,4 +1,4 @@ -import {Card, CardContent, CardHeader} from "@material-ui/core"; +import { Card, CardContent, CardHeader } from "@material-ui/core"; import { ImportProductsToAlgolia } from "./ImportProductsToAlgolia"; import AlgoliaConfigurationCard from "./AlgoliaConfigurationCard"; import { makeStyles, PageTab, PageTabs } from "@saleor/macaw-ui"; diff --git a/apps/search/src/components/ImportProductsToAlgolia.tsx b/apps/search/src/components/ImportProductsToAlgolia.tsx index a82b260..bd03fb6 100644 --- a/apps/search/src/components/ImportProductsToAlgolia.tsx +++ b/apps/search/src/components/ImportProductsToAlgolia.tsx @@ -19,7 +19,7 @@ export const ImportProductsToAlgolia = () => { const { appBridgeState } = useAppBridge(); const algoliaConfiguration = useConfiguration( appBridgeState?.saleorApiUrl, - appBridgeState?.token, + appBridgeState?.token ); const searchProvider = useMemo(() => { diff --git a/apps/search/src/components/SearchBox.tsx b/apps/search/src/components/SearchBox.tsx index febaf28..2bba1c6 100644 --- a/apps/search/src/components/SearchBox.tsx +++ b/apps/search/src/components/SearchBox.tsx @@ -5,28 +5,28 @@ import { useSearchBox } from "react-instantsearch-hooks-web"; import styles from "../styles/search.module.css"; export function SearchBox() { - const { query, refine } = useSearchBox(); - - const handleChange = (e: ChangeEvent) => { - refine(e.target.value); - }; - return ( -
- - - - ), - }} - value={query} - onChange={handleChange} - placeholder={"Search products..."} - inputProps={{ style: { padding: "16px" } }} - className={styles.textField} - /> -
- ); - } \ No newline at end of file + const { query, refine } = useSearchBox(); + + const handleChange = (e: ChangeEvent) => { + refine(e.target.value); + }; + return ( +
+ + + + ), + }} + value={query} + onChange={handleChange} + placeholder={"Search products..."} + inputProps={{ style: { padding: "16px" } }} + className={styles.textField} + /> +
+ ); +} diff --git a/apps/search/src/lib/algolia/algoliaSearchProvider.ts b/apps/search/src/lib/algolia/algoliaSearchProvider.ts index bd9f308..f4daad0 100644 --- a/apps/search/src/lib/algolia/algoliaSearchProvider.ts +++ b/apps/search/src/lib/algolia/algoliaSearchProvider.ts @@ -35,7 +35,7 @@ export class AlgoliaSearchProvider implements SearchProvider { Object.entries(groupedByIndex).map(([indexName, objects]) => { const index = this.#algolia.initIndex(indexName); return index.saveObjects(objects); - }), + }) ); } @@ -46,7 +46,7 @@ export class AlgoliaSearchProvider implements SearchProvider { Object.entries(groupedByIndex).map(([indexName, objects]) => { const index = this.#algolia.initIndex(indexName); return index.deleteObjects(objects.map((o) => o.objectID)); - }), + }) ); } @@ -141,7 +141,7 @@ const groupVariantByIndexName = ( { visibleInListings, indexNamePrefix, - }: { visibleInListings: true | false | null; indexNamePrefix: string | undefined }, + }: { visibleInListings: true | false | null; indexNamePrefix: string | undefined } ) => { if (!productVariant.product.channelListings) { return null; @@ -150,7 +150,7 @@ const groupVariantByIndexName = ( const objectsToSaveByIndexName = productVariant.product.channelListings .filter((channelListing) => // don't filter if `visibleInListings` is null - visibleInListings === null ? true : channelListing.visibleInListings === visibleInListings, + visibleInListings === null ? true : channelListing.visibleInListings === visibleInListings ) .map((channelListing) => { const object = productAndVariantToAlgolia({ @@ -176,7 +176,7 @@ const groupProductsByIndexName = ( { visibleInListings, indexNamePrefix, - }: { visibleInListings: true | false | null; indexNamePrefix: string | undefined }, + }: { visibleInListings: true | false | null; indexNamePrefix: string | undefined } ) => { debug(`groupProductsByIndexName called`); const batchesAndIndices = productsBatch diff --git a/apps/search/src/lib/algolia/algoliaUtils.ts b/apps/search/src/lib/algolia/algoliaUtils.ts index 8a77445..2a49b10 100644 --- a/apps/search/src/lib/algolia/algoliaUtils.ts +++ b/apps/search/src/lib/algolia/algoliaUtils.ts @@ -10,7 +10,7 @@ type PartialChannelListing = { export function channelListingToAlgoliaIndexId( channelListing: PartialChannelListing, - indexNamePrefix: string | undefined, + indexNamePrefix: string | undefined ) { const nameSegments = [ indexNamePrefix, diff --git a/apps/search/src/lib/graphql.ts b/apps/search/src/lib/graphql.ts index 8711480..4eee5c4 100644 --- a/apps/search/src/lib/graphql.ts +++ b/apps/search/src/lib/graphql.ts @@ -51,7 +51,7 @@ export const nextClient = (url: string, getAuth: AuthConfig["getAuth url, exchanges: getExchanges(getAuth), }, - false, + false ); }; diff --git a/apps/search/src/lib/metadata.ts b/apps/search/src/lib/metadata.ts index 3ce4db6..ee78a65 100644 --- a/apps/search/src/lib/metadata.ts +++ b/apps/search/src/lib/metadata.ts @@ -37,7 +37,7 @@ export async function mutateMetadata(client: Client, metadata: MetadataEntry[]) if (idQueryError) { console.debug("Could not fetch the app id: ", idQueryError); throw new Error( - "Could not fetch the app id. Please check if auth data for the client are valid.", + "Could not fetch the app id. Please check if auth data for the client are valid." ); } diff --git a/apps/search/src/pages/api/configuration.ts b/apps/search/src/pages/api/configuration.ts index 93ec5fd..9caa881 100644 --- a/apps/search/src/pages/api/configuration.ts +++ b/apps/search/src/pages/api/configuration.ts @@ -20,7 +20,7 @@ const sendResponse = async ( res: NextApiResponse, statusCode: number, settings: SettingsManager, - domain: string, + domain: string ) => { res.status(statusCode).json({ success: statusCode === 200, @@ -36,7 +36,7 @@ const sendResponse = async ( export const handler = async ( req: NextApiRequest, res: NextApiResponse, - ctx: ProtectedHandlerContext, + ctx: ProtectedHandlerContext ) => { debug("Configuration handler received request"); @@ -54,7 +54,7 @@ export const handler = async ( } else if (req.method === "POST") { debug("Updating the configuration"); const { appId, searchKey, secretKey, indexNamePrefix } = JSON.parse( - req.body, + req.body ) as AlgoliaConfigurationFields; await settings.set([ { key: "secretKey", value: secretKey || "", domain }, diff --git a/apps/search/src/pages/api/webhooks/saleor/_index.ts b/apps/search/src/pages/api/webhooks/saleor/_index.ts index 85b1658..6b2d323 100644 --- a/apps/search/src/pages/api/webhooks/saleor/_index.ts +++ b/apps/search/src/pages/api/webhooks/saleor/_index.ts @@ -11,15 +11,15 @@ const debug = createDebug("Webhooks handler"); export const handler: NextWebhookApiHandler = async ( req, res, - context, + context ) => { const { event, authData } = context; debug( - `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`, + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` ); const client = createClient(authData.saleorApiUrl, async () => - Promise.resolve({ token: authData.token }), + Promise.resolve({ token: authData.token }) ); const settings = createSettingsManager(client); diff --git a/apps/search/src/pages/search/index.tsx b/apps/search/src/pages/search/index.tsx index f773be0..1ef0e52 100644 --- a/apps/search/src/pages/search/index.tsx +++ b/apps/search/src/pages/search/index.tsx @@ -37,7 +37,7 @@ function Search() { const [indexName, setIndexName] = useState(); const algoliaConfiguration = useConfiguration( appBridgeState?.saleorApiUrl, - appBridgeState?.token, + appBridgeState?.token ); const searchClient = useMemo(() => { diff --git a/apps/search/src/providers/GraphQLProvider.tsx b/apps/search/src/providers/GraphQLProvider.tsx index e217484..4767d19 100644 --- a/apps/search/src/providers/GraphQLProvider.tsx +++ b/apps/search/src/providers/GraphQLProvider.tsx @@ -13,7 +13,7 @@ function GraphQLProvider(props: PropsWithChildren<{}>) { } const client = createClient(saleorApiUrl, async () => - Promise.resolve({ token: appBridgeState?.token! }), + Promise.resolve({ token: appBridgeState?.token! }) ); return ; diff --git a/package.json b/package.json index a9deba8..dafb877 100644 --- a/package.json +++ b/package.json @@ -14,17 +14,23 @@ "test": "turbo run test", "test:ci": "turbo run test:ci", "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "generate": "turbo run generate" + "generate": "turbo run generate", + "prepare": "husky install" }, "devDependencies": { "@changesets/cli": "^2.26.0", "eslint-config-saleor": "workspace:*", "prettier": "^2.8.3", "turbo": "^1.7.4", - "eslint": "^8.33.0" + "eslint": "^8.33.0", + "husky": "^8.0.3" }, "engines": { "node": ">=18.0.0" }, - "packageManager": "pnpm@7.26.2" + "packageManager": "pnpm@7.26.2", + "lint-staged": { + "*.{js,ts,tsx}": "eslint --cache --fix", + "*.{ts,tsx,md}": "prettier --write" + } } \ No newline at end of file diff --git a/packages/shared/src/is-in-iframe.ts b/packages/shared/src/is-in-iframe.ts index 9299619..e1f481c 100644 --- a/packages/shared/src/is-in-iframe.ts +++ b/packages/shared/src/is-in-iframe.ts @@ -4,4 +4,4 @@ export function isInIframe() { } catch (e) { return true; } -} \ No newline at end of file +} diff --git a/packages/shared/src/title-bar/title-bar.tsx b/packages/shared/src/title-bar/title-bar.tsx index ab7842c..0c3efb0 100644 --- a/packages/shared/src/title-bar/title-bar.tsx +++ b/packages/shared/src/title-bar/title-bar.tsx @@ -80,4 +80,4 @@ export function TitleBar({ ); } -TitleBar.height = height; \ No newline at end of file +TitleBar.height = height; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfd6af8..36cd901 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,12 +7,14 @@ importers: '@changesets/cli': ^2.26.0 eslint: ^8.33.0 eslint-config-saleor: workspace:* + husky: ^8.0.3 prettier: ^2.8.3 turbo: ^1.7.4 devDependencies: '@changesets/cli': 2.26.0 eslint: 8.33.0 eslint-config-saleor: link:packages/eslint-config-saleor + husky: 8.0.3 prettier: 2.8.3 turbo: 1.7.4