Apply recent ESLint rules on the codebase (#404)

* Add lint:fix script

* Reformat CRM app with eslint fix

* Apply eslint fix on data importer codebase

* Apply eslint fix on Invoices codebase

* Apply eslint fix on Klaviyo codebase

* Apply eslint fix on products-feed codebase

* Apply eslint fix on monitoring codebase

* Apply eslint fix on Search codebase

* Apply eslint fix on Slack codebase

* cleanup
This commit is contained in:
Lukasz Ostrowski 2023-04-18 15:10:00 +02:00 committed by GitHub
parent 57f6d41bc4
commit 2c0df91351
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
96 changed files with 612 additions and 364 deletions

View file

@ -0,0 +1,16 @@
---
"saleor-app-emails-and-messages": patch
"saleor-app-data-importer": patch
"saleor-app-products-feed": patch
"saleor-app-monitoring": patch
"@saleor/apps-shared": patch
"saleor-app-invoices": patch
"saleor-app-klaviyo": patch
"saleor-app-search": patch
"saleor-app-slack": patch
"saleor-app-taxes": patch
"saleor-app-cms": patch
"saleor-app-crm": patch
---
Added lint:fix script, so `eslint --fix` can be run deliberately

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest"
@ -63,9 +64,5 @@
"prettier": "^2.7.1",
"typescript": "4.9",
"vitest": "^0.30.1"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest"
@ -65,9 +66,5 @@
"eslint-config-saleor": "workspace:*",
"prettier": "^2.8.2",
"typescript": "4.9.4"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -90,9 +90,11 @@ export async function mutateMetadata(
export const createSettingsManager = (
client: Pick<Client, "query" | "mutation">
): SettingsManager => {
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.
* If your use case require plain text values, you can use MetadataManager.
*/
return new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: process.env.SECRET_KEY!,

View file

@ -4,6 +4,7 @@ import { createLogger } from "../../../../lib/logger";
export const getBaseUrl = (headers: { [name: string]: string | string[] | undefined }): string => {
const { host, "x-forwarded-proto": protocol = "http" } = headers;
return `${protocol}://${host}`;
};

View file

@ -6,6 +6,7 @@ import { SALEOR_API_URL_HEADER, SALEOR_AUTHORIZATION_BEARER_HEADER } from "@sale
export const getBaseUrl = (headers: { [name: string]: string | string[] | undefined }): string => {
const { host, "x-forwarded-proto": protocol = "http" } = headers;
return `${protocol}://${host}`;
};
@ -38,6 +39,7 @@ const handler: NextApiHandler = async (req, res) => {
});
const redirectUri = `${getBaseUrl(req.headers)}/api/auth/mailchimp/callback`;
logger.debug({ redirectUri }, "Resolved redirect uri");
const qs = new URLSearchParams({

View file

@ -1,7 +1,9 @@
// This file sets a custom webpack configuration to use your Next.js app
// with Sentry.
// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
/*
* This file sets a custom webpack configuration to use your Next.js app
* with Sentry.
* https://nextjs.org/docs/api-reference/next.config.js/introduction
* https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
*/
const { withSentryConfig } = require("@sentry/nextjs");
const isSentryPropertiesInEnvironment =

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest",
@ -61,9 +62,5 @@
"eslint": "^8.33.0",
"eslint-config-saleor": "workspace:*",
"typescript": "4.9.5"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the browser.
* The config you add here will be used whenever a page is visited.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever middleware or an Edge route handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever middleware or an Edge route handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever the server handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -86,8 +86,10 @@ const generateAddressColumns = (labelNamespace: string, keyNamespace: string): C
// TODO - enable address columns when mapped
const allColumns: ColumnAPI[] = [
...customerColumns,
// ...generateAddressColumns("Default Billing Address", "defaultBillingAddress"),
// ...generateAddressColumns("Default Shipping Address", "defaultShippingAddress"),
/*
* ...generateAddressColumns("Default Billing Address", "defaultBillingAddress"),
* ...generateAddressColumns("Default Shipping Address", "defaultShippingAddress"),
*/
];
export const getCustomersModelColumns = () => allColumns;
@ -116,8 +118,10 @@ export const getResultModelSchema = () =>
email: z.string(),
note: z.string().nullish(),
externalReference: z.string().nullish(),
// defaultBillingAddress: zodAddressSchema,
// defaultShippingAddress: zodAddressSchema,
/*
* defaultBillingAddress: zodAddressSchema,
* defaultShippingAddress: zodAddressSchema,
*/
}),
});

View file

@ -57,6 +57,7 @@ function NextApp({ Component, pageProps }: AppProps) {
*/
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -20,16 +20,20 @@ import * as Sentry from "@sentry/nextjs";
import NextErrorComponent from "next/error";
const CustomErrorComponent = (props) => {
// If you're using a Nextjs version prior to 12.2.1, uncomment this to
// compensate for https://github.com/vercel/next.js/issues/8592
// Sentry.captureUnderscoreErrorException(props);
/*
* If you're using a Nextjs version prior to 12.2.1, uncomment this to
* compensate for https://github.com/vercel/next.js/issues/8592
* Sentry.captureUnderscoreErrorException(props);
*/
return <NextErrorComponent statusCode={props.statusCode} />;
};
CustomErrorComponent.getInitialProps = async (contextData) => {
// In case this is running in a serverless function, await this in order to give Sentry
// time to send the error before the lambda exits
/*
* In case this is running in a serverless function, await this in order to give Sentry
* time to send the error before the lambda exits
*/
await Sentry.captureUnderscoreErrorException(contextData);
// This will contain the status code of the response

View file

@ -16,7 +16,11 @@
"REST_APL_TOKEN",
"NEXT_PUBLIC_VERCEL_ENV",
"VERCEL_URL",
"PORT"
"PORT",
"SENTRY_AUTH_TOKEN",
"SENTRY_PROJECT",
"SENTRY_ORG",
"SENTRY_DSN"
]
}
}

View file

@ -6,7 +6,8 @@
"dev": "pnpm generate && NODE_OPTIONS='--inspect' next dev",
"build": "pnpm generate && next build",
"start": "next start",
"lint": "pnpm generate && prettier --loglevel warn --write . && eslint --fix .",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest"
@ -78,9 +79,5 @@
"eslint-config-saleor": "workspace:*",
"prettier": "^2.8.2",
"typescript": "4.9.4"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -1,7 +1,9 @@
// This file sets a custom webpack configuration to use your Next.js app
// with Sentry.
// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file sets a custom webpack configuration to use your Next.js app
* with Sentry.
* https://nextjs.org/docs/api-reference/next.config.js/introduction
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
const { withSentryConfig } = require("@sentry/nextjs");
@ -13,12 +15,14 @@ const isSentryPropertiesInEnvironment =
*/
const moduleExports = {
sentry: {
// Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
// for client-side builds. (This will be the default starting in
// `@sentry/nextjs` version 8.0.0.) See
// https://webpack.js.org/configuration/devtool/ and
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
// for more information.
/*
* Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
* for client-side builds. (This will be the default starting in
* `@sentry/nextjs` version 8.0.0.) See
* https://webpack.js.org/configuration/devtool/ and
* https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
* for more information.
*/
hideSourceMaps: true,
disableServerWebpackPlugin: !isSentryPropertiesInEnvironment,
disableClientWebpackPlugin: !isSentryPropertiesInEnvironment,
@ -31,17 +35,23 @@ const moduleExports = {
};
const sentryWebpackPluginOptions = {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore
/*
* Additional config options for the Sentry Webpack plugin. Keep in mind that
* the following options are set automatically, and overriding them is not
* recommended:
* release, url, org, project, authToken, configFile, stripPrefix,
* urlPrefix, include, ignore
*/
silent: true, // Suppresses all logs
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
/*
* For all available options, see:
* https://github.com/getsentry/sentry-webpack-plugin#options.
*/
};
// Make sure adding Sentry options is the last code to run before exporting, to
// ensure that your source maps include changes from all other Webpack plugins
/*
* Make sure adding Sentry options is the last code to run before exporting, to
* ensure that your source maps include changes from all other Webpack plugins
*/
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest",
@ -70,10 +71,6 @@
"typescript": "4.9.5",
"vite": "^4.2.1",
"vitest": "^0.30.1",
"@types/semver": "^7.3.13"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
"@types/semver": "^7.3.13"
}
}

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the browser.
* The config you add here will be used whenever a page is visited.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN;
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever middleware or an Edge route handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever middleware or an Edge route handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever the server handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -81,9 +81,11 @@ export async function mutateMetadata(client: Client, metadata: MetadataEntry[])
}
export const createSettingsManager = (client: Client) => {
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.
* If your use case require plain text values, you can use MetadataManager.
*/
return new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: process.env.SECRET_KEY!,

View file

@ -19,13 +19,15 @@ export class MicroinvoiceInvoiceGenerator implements InvoiceGenerator {
const microinvoiceInstance = new Microinvoice({
style: {
// header: {
// image: {
// path: "./examples/logo.png",
// width: 50,
// height: 19,
// },
// },
/*
* header: {
* image: {
* path: "./examples/logo.png",
* width: 50,
* height: 19,
* },
* },
*/
},
data: {
invoice: {
@ -60,10 +62,12 @@ export class MicroinvoiceInvoiceGenerator implements InvoiceGenerator {
order.billingAddress?.country.country,
],
},
// {
// label: "Tax Identifier",
// value: "todo",
// },
/*
* {
* label: "Tax Identifier",
* value: "todo",
* },
*/
],
seller: [
@ -79,23 +83,27 @@ export class MicroinvoiceInvoiceGenerator implements InvoiceGenerator {
companyAddressData.countryArea,
],
},
// {
// label: "Tax Identifier",
// value: "todo",
// },
/*
* {
* label: "Tax Identifier",
* value: "todo",
* },
*/
],
legal: [
// {
// value: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
// weight: "bold",
// color: "primary",
// },
// {
// value: "sed do eiusmod tempor incididunt ut labore et dolore magna.",
// weight: "bold",
// color: "secondary",
// },
/*
* {
* value: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
* weight: "bold",
* color: "primary",
* },
* {
* value: "sed do eiusmod tempor incididunt ut labore et dolore magna.",
* weight: "bold",
* color: "secondary",
* },
*/
],
details: {

View file

@ -22,6 +22,7 @@ function NextApp({ Component, pageProps }: AppProps) {
*/
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -20,16 +20,20 @@ import * as Sentry from '@sentry/nextjs';
import NextErrorComponent from 'next/error';
const CustomErrorComponent = props => {
// If you're using a Nextjs version prior to 12.2.1, uncomment this to
// compensate for https://github.com/vercel/next.js/issues/8592
// Sentry.captureUnderscoreErrorException(props);
/*
* If you're using a Nextjs version prior to 12.2.1, uncomment this to
* compensate for https://github.com/vercel/next.js/issues/8592
* Sentry.captureUnderscoreErrorException(props);
*/
return <NextErrorComponent statusCode={props.statusCode} />;
};
CustomErrorComponent.getInitialProps = async contextData => {
// In case this is running in a serverless function, await this in order to give Sentry
// time to send the error before the lambda exits
/*
* In case this is running in a serverless function, await this in order to give Sentry
* time to send the error before the lambda exits
*/
await Sentry.captureUnderscoreErrorException(contextData);
// This will contain the status code of the response

View file

@ -174,6 +174,7 @@ export const handler: NextWebhookApiHandler<InvoiceRequestedPayloadFragment> = a
);
const hashedInvoiceName = hashInvoiceFilename(invoiceName, orderId);
logger.debug({ hashedInvoiceName });
const hashedInvoiceFileName = `${hashedInvoiceName}.pdf`;

View file

@ -14,7 +14,11 @@
"ALLOWED_DOMAIN_PATTERN",
"NEXT_PUBLIC_VERCEL_ENV",
"REST_APL_ENDPOINT",
"REST_APL_TOKEN"
"REST_APL_TOKEN",
"SENTRY_PROJECT",
"SENTRY_DSN",
"SENTRY_ORG",
"SENTRY_AUTH_TOKEN"
]
}
}

View file

@ -28,17 +28,23 @@ const nextConfig = {
};
const sentryWebpackPluginOptions = {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore
/*
* Additional config options for the Sentry Webpack plugin. Keep in mind that
* the following options are set automatically, and overriding them is not
* recommended:
* release, url, org, project, authToken, configFile, stripPrefix,
* urlPrefix, include, ignore
*/
silent: true, // Suppresses all logs
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
/*
* For all available options, see:
* https://github.com/getsentry/sentry-webpack-plugin#options.
*/
};
// Make sure adding Sentry options is the last code to run before exporting, to
// ensure that your source maps include changes from all other Webpack plugins
/*
* Make sure adding Sentry options is the last code to run before exporting, to
* ensure that your source maps include changes from all other Webpack plugins
*/
module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions);

View file

@ -7,7 +7,8 @@
"dev": "pnpm generate && NODE_OPTIONS='--inspect' next dev",
"build": "pnpm generate && next build",
"start": "next start",
"lint": "pnpm generate && prettier --loglevel warn --write . && eslint --fix .",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen"
},

View file

@ -1,6 +1,8 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the browser.
* The config you add here will be used whenever a page is visited.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
@ -10,8 +12,10 @@ Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,6 +1,8 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever the server handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
@ -10,8 +12,10 @@ Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -39,6 +39,7 @@ export const useAppApi = ({ url, options, skip }: UseFetchProps) => {
}
const json = await res.json();
setData(json);
} catch (e) {
setError(e as unknown);

View file

@ -5,6 +5,7 @@ interface EmailServiceProvider {
export const Klaviyo = (token: string): EmailServiceProvider => ({
send: async (event, recipient, context) => {
const formParams = new URLSearchParams();
formParams.append(
"data",
JSON.stringify({

View file

@ -8,10 +8,12 @@ import {
} from "../../generated/graphql";
import { settingsManagerSecretKey } from "../../saleor-app";
// Function is using urql graphql client to fetch all available metadata.
// Before returning query result, we are transforming response to list of objects with key and value fields
// which can be used by the manager.
// Result of this query is cached by the manager.
/*
* Function is using urql graphql client to fetch all available metadata.
* Before returning query result, we are transforming response to list of objects with key and value fields
* which can be used by the manager.
* Result of this query is cached by the manager.
*/
export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]> {
const { error, data } = await client
.query<FetchAppDetailsQuery>(FetchAppDetailsDocument, {})
@ -25,9 +27,11 @@ export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]>
return data?.app?.privateMetadata.map((md) => ({ key: md.key, value: md.value })) || [];
}
// Mutate function takes urql client and metadata entries, and construct mutation to the API.
// Before data are send, additional query for required App ID is made.
// The manager will use updated entries returned by this mutation to update it's cache.
/*
* Mutate function takes urql client and metadata entries, and construct mutation to the API.
* Before data are send, additional query for required App ID is made.
* The manager will use updated entries returned by this mutation to update it's cache.
*/
export async function mutateMetadata(client: Client, appId: string, metadata: MetadataEntry[]) {
const { error: mutationError, data: mutationData } = await client
.mutation(UpdateAppMetadataDocument, {
@ -50,9 +54,11 @@ export async function mutateMetadata(client: Client, appId: string, metadata: Me
}
export const createSettingsManager = (client: Client, appId: string) =>
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.
* If your use case require plain text values, you can use MetadataManager.
*/
new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: settingsManagerSecretKey,

View file

@ -73,6 +73,7 @@ function SaleorApp({ Component, pageProps }: AppLayoutProps) {
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -15,10 +15,12 @@ interface AppErrorProps extends ErrorProps {
function MyError({ statusCode, hasGetInitialPropsRun, err }: ErrorPageProps) {
if (!hasGetInitialPropsRun && err) {
// getInitialProps is not called when an exception is thrown
// at the top level of a module while it is being loaded.
// As a workaround, we pass err via _app.js so it can be captured
// Read more: https://github.com/vercel/next.js/issues/8592.
/*
* getInitialProps is not called when an exception is thrown
* at the top level of a module while it is being loaded.
* As a workaround, we pass err via _app.js so it can be captured
* Read more: https://github.com/vercel/next.js/issues/8592.
*/
Sentry.captureException(err);
// Flushing is not required in this case as it only happens on the client
}
@ -31,8 +33,10 @@ MyError.getInitialProps = async (context: NextPageContext) => {
const { res, err, asPath } = context;
// Workaround for https://github.com/vercel/next.js/issues/8592, mark when
// getInitialProps has run
/*
* Workaround for https://github.com/vercel/next.js/issues/8592, mark when
* getInitialProps has run
*/
errorInitialProps.hasGetInitialPropsRun = true;
// Returning early because we don't want to log 404 errors to Sentry.
@ -40,32 +44,38 @@ MyError.getInitialProps = async (context: NextPageContext) => {
return errorInitialProps;
}
// Running on the server, the response object (`res`) is available.
//
// Next.js will pass an err on the server if a page's data fetching methods
// threw or returned a Promise that rejected
//
// Running on the client (browser), Next.js will provide an err if:
//
// - a page's `getInitialProps` threw or returned a Promise that rejected
// - an exception was thrown somewhere in the React lifecycle (render,
// componentDidMount, etc) that was caught by Next.js's React Error
// Boundary. Read more about what types of exceptions are caught by Error
// Boundaries: https://reactjs.org/docs/error-boundaries.html
/*
* Running on the server, the response object (`res`) is available.
*
* Next.js will pass an err on the server if a page's data fetching methods
* threw or returned a Promise that rejected
*
* Running on the client (browser), Next.js will provide an err if:
*
* - a page's `getInitialProps` threw or returned a Promise that rejected
* - an exception was thrown somewhere in the React lifecycle (render,
* componentDidMount, etc) that was caught by Next.js's React Error
* Boundary. Read more about what types of exceptions are caught by Error
* Boundaries: https://reactjs.org/docs/error-boundaries.html
*/
if (err) {
Sentry.captureException(err);
// Flushing before returning is necessary if deploying to Vercel, see
// https://vercel.com/docs/platform/limits#streaming-responses
/*
* Flushing before returning is necessary if deploying to Vercel, see
* https://vercel.com/docs/platform/limits#streaming-responses
*/
await Sentry.flush(2000);
return errorInitialProps;
}
// If this point is reached, getInitialProps was called without any
// information about what the error might be. This is unexpected and may
// indicate a bug introduced in Next.js, so record it in Sentry
/*
* If this point is reached, getInitialProps was called without any
* information about what the error might be. This is unexpected and may
* indicate a bug introduced in Next.js, so record it in Sentry
*/
Sentry.captureException(new Error(`_error.js getInitialProps missing data at path: ${asPath}`));
await Sentry.flush(2000);

View file

@ -91,6 +91,7 @@ const handler: NextWebhookApiHandler<CustomerCreatedWebhookPayloadFragment> = as
if (klaviyoResponse.status !== 200) {
const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || "";
console.debug("Klaviyo returned error: ", klaviyoMessage);
return res.status(500).json({

View file

@ -96,6 +96,7 @@ const handler: NextWebhookApiHandler<FulfillmentCreatedWebhookPayloadFragment> =
if (klaviyoResponse.status !== 200) {
const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || "";
console.debug("Klaviyo returned error: ", klaviyoMessage);
return res.status(500).json({

View file

@ -67,6 +67,7 @@ const handler: NextWebhookApiHandler<OrderCreatedWebhookPayloadFragment> = async
if (klaviyoResponse.status !== 200) {
const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || "";
console.debug("Klaviyo returned error: ", klaviyoMessage);
return res.status(500).json({
success: false,

View file

@ -67,6 +67,7 @@ const handler: NextWebhookApiHandler<OrderFullyPaidWebhookPayloadFragment> = asy
if (klaviyoResponse.status !== 200) {
const klaviyoMessage = ` Message: ${(await klaviyoResponse.json())?.message}.` || "";
console.debug("Klaviyo returned error: ", klaviyoMessage);
return res.status(500).json({

View file

@ -171,6 +171,7 @@ function Configuration() {
const onChange = (event: ChangeEvent) => {
const { name, value } = event.target as HTMLInputElement;
setConfiguration((prev) =>
prev!.map((prevField) => (prevField.key === name ? { ...prevField, value } : prevField))
);

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"generate": "graphql-codegen",
"test": "vitest"
},
@ -55,9 +56,5 @@
"eslint-config-saleor": "workspace:*",
"prettier": "^2.8.2",
"typescript": "4.9.4"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -69,6 +69,7 @@ function NextApp({ Component, pageProps }: AppProps) {
*/
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest"
@ -69,9 +70,5 @@
"eslint-config-saleor": "workspace:*",
"prettier": "^2.8.2",
"typescript": "4.9.4"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -86,5 +86,6 @@ export const generateGoogleXmlFeed = ({
},
},
];
return builder.build(data);
};

View file

@ -81,9 +81,11 @@ export async function mutateMetadata(client: Client, metadata: MetadataEntry[])
}
export const createSettingsManager = (client: Client) => {
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.
* If your use case require plain text values, you can use MetadataManager.
*/
return new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: process.env.SECRET_KEY!,

View file

@ -36,6 +36,7 @@ export const FeedPreviewCard = ({ channelSlug }: FeedPreviewCardProps) => {
const openUrlInNewTab = async (url: string) => {
await appBridge?.dispatch(actions.Redirect({ to: url, newContext: true }));
};
return (
<Paper elevation={0} className={styles.instructionsContainer}>
<Typography paragraph variant="h3">

View file

@ -65,6 +65,7 @@ export const SideMenu: React.FC<SideMenuProps> = ({
const classes = useStyles();
const isNoItems = !items || !items.length;
return (
<Card className={classes.menu}>
<CardHeader title={title} action={headerToolbar} />

View file

@ -38,6 +38,7 @@ export const categoryMappingRouter = router({
.input(SetCategoryMappingInputSchema)
.mutation(async ({ ctx, input }) => {
const logger = pinoLogger.child({ saleorApiUrl: ctx.saleorApiUrl });
logger.debug("categoriesRouter.setCategoryMapping called");
const { error } = await ctx.apiClient
.mutation(UpdateCategoryMappingDocument, {

View file

@ -28,10 +28,12 @@ export const ConfigurationPageBaseLayout = ({ children }: Props) => {
const navigateToTab = (value: string) => {
const redirectionUrl = tabs.find((tab) => tab.key === value)?.url;
if (redirectionUrl) {
router.push(redirectionUrl);
}
};
return (
<div className={styles.appContainer}>
<PageTabs value={activePath} onChange={navigateToTab}>

View file

@ -63,6 +63,7 @@ const generateClassName = createGenerateClassName({
* Ensure instance is a singleton.
* TODO: This is React 18 issue, consider hiding this workaround inside app-sdk
*/
export const appBridgeInstance = typeof window !== "undefined" ? new AppBridge() : undefined;
/**
@ -78,6 +79,7 @@ function NextApp({ Component, pageProps }: AppProps) {
*/
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -22,6 +22,7 @@ export const handler = async (req: NextApiRequest, res: NextApiResponse) => {
channel,
route: "api/feed/{url}/{channel}/google.xml",
});
logger.debug("Feed route visited");
if (!url.length) {
@ -59,8 +60,10 @@ export const handler = async (req: NextApiRequest, res: NextApiResponse) => {
let storefrontUrl: string;
let productStorefrontUrl: string;
try {
const settings = await getGoogleFeedSettings({ authData, channel });
storefrontUrl = settings.storefrontUrl;
productStorefrontUrl = settings.productStorefrontUrl;
} catch (error) {
@ -72,8 +75,10 @@ export const handler = async (req: NextApiRequest, res: NextApiResponse) => {
let shopName: string;
let shopDescription: string | undefined;
try {
const shopDetails = await fetchShopData({ client, channel });
shopName = shopDetails.shopName;
shopDescription = shopDetails.shopDescription;
} catch (error) {

View file

@ -1,7 +1,9 @@
// This file sets a custom webpack configuration to use your Next.js app
// with Sentry.
// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file sets a custom webpack configuration to use your Next.js app
* with Sentry.
* https://nextjs.org/docs/api-reference/next.config.js/introduction
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
const { withSentryConfig } = require("@sentry/nextjs");
@ -23,12 +25,14 @@ const moduleExports = {
},
transpilePackages: ["@saleor/apps-shared"],
sentry: {
// Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
// for client-side builds. (This will be the default starting in
// `@sentry/nextjs` version 8.0.0.) See
// https://webpack.js.org/configuration/devtool/ and
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
// for more information.
/*
* Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
* for client-side builds. (This will be the default starting in
* `@sentry/nextjs` version 8.0.0.) See
* https://webpack.js.org/configuration/devtool/ and
* https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
* for more information.
*/
hideSourceMaps: true,
disableServerWebpackPlugin: !isSentryPropertiesInEnvironment,
disableClientWebpackPlugin: !isSentryPropertiesInEnvironment,
@ -36,17 +40,23 @@ const moduleExports = {
};
const sentryWebpackPluginOptions = {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore
/*
* Additional config options for the Sentry Webpack plugin. Keep in mind that
* the following options are set automatically, and overriding them is not
* recommended:
* release, url, org, project, authToken, configFile, stripPrefix,
* urlPrefix, include, ignore
*/
silent: true, // Suppresses all logs
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
/*
* For all available options, see:
* https://github.com/getsentry/sentry-webpack-plugin#options.
*/
};
// Make sure adding Sentry options is the last code to run before exporting, to
// ensure that your source maps include changes from all other Webpack plugins
/*
* Make sure adding Sentry options is the last code to run before exporting, to
* ensure that your source maps include changes from all other Webpack plugins
*/
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen"
},
@ -58,9 +59,5 @@
"eslint-config-saleor": "workspace:*",
"prettier": "^2.7.1",
"typescript": "4.8.4"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the browser.
* The config you add here will be used whenever a page is visited.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from '@sentry/nextjs';
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever middleware or an Edge route handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever middleware or an Edge route handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from '@sentry/nextjs';
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,17 +1,21 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever the server handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from '@sentry/nextjs';
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -49,8 +49,10 @@ export const AlgoliaConfigurationCard = () => {
},
body: JSON.stringify(conf),
});
if (resp.status >= 200 && resp.status < 300) {
const data = (await resp.json()) as { data?: AlgoliaConfigurationFields };
return data.data;
}
throw new Error(`Server responded with status code ${resp.status}`);

View file

@ -20,6 +20,7 @@ function Hit(props: { hit: any }) {
export function Hits() {
const { hits } = useHits();
return (
<div className={styles.hitsWrapper}>
{hits.map((hit) => (

View file

@ -10,6 +10,7 @@ export function SearchBox() {
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
refine(e.target.value);
};
return (
<div className={styles.textFieldContainer}>
<TextField

View file

@ -66,6 +66,7 @@ export const useQueryAllProducts = (paused: boolean) => {
(async () => {
const channels = await getChannels();
// get all products for each channel
await channels.data?.channels?.reduce(async (acc, channel) => {
await acc;
await getProducts(channel.slug, "");

View file

@ -34,6 +34,7 @@ export class AlgoliaSearchProvider implements SearchProvider {
return Promise.all(
Object.entries(groupedByIndex).map(([indexName, objects]) => {
const index = this.#algolia.initIndex(indexName);
return index.saveObjects(objects);
})
);
@ -45,6 +46,7 @@ export class AlgoliaSearchProvider implements SearchProvider {
return Promise.all(
Object.entries(groupedByIndex).map(([indexName, objects]) => {
const index = this.#algolia.initIndex(indexName);
return index.deleteObjects(objects.map((o) => o.objectID));
})
);
@ -57,6 +59,7 @@ export class AlgoliaSearchProvider implements SearchProvider {
visibleInListings: true,
indexNamePrefix: this.#indexNamePrefix,
});
await this.saveGroupedByIndex(groupedByIndex);
}
@ -128,6 +131,7 @@ export class AlgoliaSearchProvider implements SearchProvider {
visibleInListings: null,
indexNamePrefix: this.#indexNamePrefix,
});
if (groupedByIndexToDelete) {
await this.deleteGroupedByIndex(groupedByIndexToDelete);
}
@ -157,6 +161,7 @@ const groupVariantByIndexName = (
variant: productVariant,
channel: channelListing.channel.slug,
});
return {
object,
indexName: channelListingToAlgoliaIndexId(channelListing, indexNamePrefix),
@ -190,5 +195,6 @@ const groupProductsByIndexName = (
acc[indexName].push(...objects);
return acc;
}, {} as GroupedByIndex);
return groupedByIndex;
};

View file

@ -21,6 +21,7 @@ export function channelListingToAlgoliaIndexId(
channelListing.channel.currencyCode,
"products",
];
return nameSegments.filter(isNotNil).join(".");
}
@ -85,6 +86,7 @@ export function productAndVariantToAlgolia({
const attributes = {
...product.attributes.reduce((acc, attr, idx) => {
const preparedAttr = mapSelectedAttributesToRecord(attr);
if (!preparedAttr) {
return acc;
}
@ -95,6 +97,7 @@ export function productAndVariantToAlgolia({
}, {}),
...variant.attributes.reduce((acc, attr, idx) => {
const preparedAttr = mapSelectedAttributesToRecord(attr);
if (!preparedAttr) {
return acc;
}
@ -123,6 +126,7 @@ export function productAndVariantToAlgolia({
collections: product.collections?.map((collection) => collection.name) || [],
metadata: formatMetadata(variant),
};
return document;
}

View file

@ -18,6 +18,7 @@ export const getAlgoliaConfiguration = async ({ authData }: GetAlgoliaConfigurat
try {
const secretKey = await settings.get("secretKey", authData.domain);
if (!secretKey?.length) {
return {
errors: [
@ -30,6 +31,7 @@ export const getAlgoliaConfiguration = async ({ authData }: GetAlgoliaConfigurat
}
const appId = await settings.get("appId", authData.domain);
if (!appId?.length) {
return {
errors: [
@ -41,6 +43,7 @@ export const getAlgoliaConfiguration = async ({ authData }: GetAlgoliaConfigurat
}
const indexNamePrefix = (await settings.get("indexNamePrefix", authData.domain)) || "";
debug("Configuration fetched");
return {
settings: {

View file

@ -9,6 +9,7 @@ export const fetchConfiguration = async (saleorApiUrl: string, token: string) =>
},
});
const data = (await res.json()) as { data?: AlgoliaConfigurationFields };
return data.data;
};

View file

@ -8,10 +8,12 @@ import {
} from "../../generated/graphql";
import { settingsManagerSecretKey } from "../../saleor-app";
// Function is using urql graphql client to fetch all available metadata.
// Before returning query result, we are transforming response to list of objects with key and value fields
// which can be used by the manager.
// Result of this query is cached by the manager.
/*
* Function is using urql graphql client to fetch all available metadata.
* Before returning query result, we are transforming response to list of objects with key and value fields
* which can be used by the manager.
* Result of this query is cached by the manager.
*/
export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]> {
const { error, data } = await client
.query<FetchAppDetailsQuery>(FetchAppDetailsDocument, {})
@ -25,9 +27,11 @@ export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]>
return data?.app?.privateMetadata.map((md) => ({ key: md.key, value: md.value })) || [];
}
// Mutate function takes urql client and metadata entries, and construct mutation to the API.
// Before data are send, additional query for required App ID is made.
// The manager will use updated entries returned by this mutation to update it's cache.
/*
* Mutate function takes urql client and metadata entries, and construct mutation to the API.
* Before data are send, additional query for required App ID is made.
* The manager will use updated entries returned by this mutation to update it's cache.
*/
export async function mutateMetadata(client: Client, metadata: MetadataEntry[]) {
// to update the metadata, ID is required
const { error: idQueryError, data: idQueryData } = await client
@ -69,9 +73,11 @@ export async function mutateMetadata(client: Client, metadata: MetadataEntry[])
}
export const createSettingsManager = (client: Client) => {
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.
* If your use case require plain text values, you can use MetadataManager.
*/
return new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: settingsManagerSecretKey,

View file

@ -35,6 +35,7 @@ const queryClient = new QueryClient({
},
},
});
type PalettesOverride = Record<"light" | "dark", SaleorThemeColors>;
/**
@ -73,6 +74,7 @@ function NextApp({ Component, pageProps }: AppProps) {
*/
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -20,16 +20,20 @@ import * as Sentry from '@sentry/nextjs';
import NextErrorComponent from 'next/error';
const CustomErrorComponent = props => {
// If you're using a Nextjs version prior to 12.2.1, uncomment this to
// compensate for https://github.com/vercel/next.js/issues/8592
// Sentry.captureUnderscoreErrorException(props);
/*
* If you're using a Nextjs version prior to 12.2.1, uncomment this to
* compensate for https://github.com/vercel/next.js/issues/8592
* Sentry.captureUnderscoreErrorException(props);
*/
return <NextErrorComponent statusCode={props.statusCode} />;
};
CustomErrorComponent.getInitialProps = async contextData => {
// In case this is running in a serverless function, await this in order to give Sentry
// time to send the error before the lambda exits
/*
* In case this is running in a serverless function, await this in order to give Sentry
* time to send the error before the lambda exits
*/
await Sentry.captureUnderscoreErrorException(contextData);
// This will contain the status code of the response

View file

@ -58,6 +58,7 @@ export const handler = async (
const { appId, searchKey, secretKey, indexNamePrefix } = JSON.parse(
req.body
) as AlgoliaConfigurationFields;
await settings.set([
{ key: "secretKey", value: secretKey || "", domain },
{ key: "searchKey", value: searchKey || "", domain },

View file

@ -22,6 +22,7 @@ export const handler: NextWebhookApiHandler<ProductCreated> = async (req, res, c
const debug = createDebug(`Webhook handler - ${webhookProductCreated.event}`);
const { event, authData } = context;
debug(
`New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`
);
@ -43,6 +44,7 @@ export const handler: NextWebhookApiHandler<ProductCreated> = async (req, res, c
});
const { product } = context.payload;
if (product) {
await searchProvider.createProduct(product);
}

View file

@ -22,6 +22,7 @@ export const handler: NextWebhookApiHandler<ProductDeleted> = async (req, res, c
const debug = createDebug(`Webhook handler - ${webhookProductDeleted.event}`);
const { event, authData } = context;
debug(
`New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`
);
@ -43,6 +44,7 @@ export const handler: NextWebhookApiHandler<ProductDeleted> = async (req, res, c
});
const { product } = context.payload;
if (product) {
await searchProvider.deleteProduct(product);
}

View file

@ -22,6 +22,7 @@ export const handler: NextWebhookApiHandler<ProductUpdated> = async (req, res, c
const debug = createDebug(`Webhook handler - ${webhookProductUpdated.event}`);
const { event, authData } = context;
debug(
`New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`
);
@ -43,6 +44,7 @@ export const handler: NextWebhookApiHandler<ProductUpdated> = async (req, res, c
});
const { product } = context.payload;
if (product) {
await searchProvider.updateProduct(product);
}

View file

@ -25,6 +25,7 @@ export const handler: NextWebhookApiHandler<ProductVariantCreated> = async (req,
const debug = createDebug(`Webhook handler - ${webhookProductVariantCreated.event}`);
const { event, authData } = context;
debug(
`New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`
);
@ -46,6 +47,7 @@ export const handler: NextWebhookApiHandler<ProductVariantCreated> = async (req,
});
const { productVariant } = context.payload;
if (productVariant) {
await searchProvider.createProductVariant(productVariant);
}

View file

@ -25,6 +25,7 @@ export const handler: NextWebhookApiHandler<ProductVariantDeleted> = async (req,
const debug = createDebug(`Webhook handler - ${webhookProductVariantDeleted.event}`);
const { event, authData } = context;
debug(
`New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`
);
@ -46,6 +47,7 @@ export const handler: NextWebhookApiHandler<ProductVariantDeleted> = async (req,
});
const { productVariant } = context.payload;
if (productVariant) {
await searchProvider.deleteProductVariant(productVariant);
}

View file

@ -25,6 +25,7 @@ export const handler: NextWebhookApiHandler<ProductVariantUpdated> = async (req,
const debug = createDebug(`Webhook handler - ${webhookProductVariantUpdated.event}`);
const { event, authData } = context;
debug(
`New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!`
);
@ -46,6 +47,7 @@ export const handler: NextWebhookApiHandler<ProductVariantUpdated> = async (req,
});
const { productVariant } = context.payload;
if (productVariant) {
await searchProvider.updateProductVariant(productVariant);
}

View file

@ -11,6 +11,10 @@
"ALLOWED_DOMAIN_PATTERN",
"REST_APL_ENDPOINT",
"REST_APL_TOKEN",
"SENTRY_AUTH_TOKEN",
"SENTRY_PROJECT",
"SENTRY_DSN",
"SENTRY_ORG",
"NEXT_PUBLIC_VERCEL_ENV"
]
}

View file

@ -1,7 +1,9 @@
// This file sets a custom webpack configuration to use your Next.js app
// with Sentry.
// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file sets a custom webpack configuration to use your Next.js app
* with Sentry.
* https://nextjs.org/docs/api-reference/next.config.js/introduction
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
const { withSentryConfig } = require("@sentry/nextjs");
@ -18,28 +20,36 @@ const moduleExports = {
sentry: {
disableServerWebpackPlugin: !isSentryPropertiesInEnvironment,
disableClientWebpackPlugin: !isSentryPropertiesInEnvironment,
// Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
// for client-side builds. (This will be the default starting in
// `@sentry/nextjs` version 8.0.0.) See
// https://webpack.js.org/configuration/devtool/ and
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
// for more information.
/*
* Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
* for client-side builds. (This will be the default starting in
* `@sentry/nextjs` version 8.0.0.) See
* https://webpack.js.org/configuration/devtool/ and
* https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
* for more information.
*/
hideSourceMaps: true,
},
};
const sentryWebpackPluginOptions = {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore
/*
* Additional config options for the Sentry Webpack plugin. Keep in mind that
* the following options are set automatically, and overriding them is not
* recommended:
* release, url, org, project, authToken, configFile, stripPrefix,
* urlPrefix, include, ignore
*/
silent: true, // Suppresses all logs
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
/*
* For all available options, see:
* https://github.com/getsentry/sentry-webpack-plugin#options.
*/
};
// Make sure adding Sentry options is the last code to run before exporting, to
// ensure that your source maps include changes from all other Webpack plugins
/*
* Make sure adding Sentry options is the last code to run before exporting, to
* ensure that your source maps include changes from all other Webpack plugins
*/
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);

View file

@ -6,7 +6,8 @@
"dev": "pnpm generate && NODE_OPTIONS='--inspect' next dev",
"build": "pnpm generate && next build",
"start": "next start",
"lint": "pnpm generate && prettier --loglevel warn --write . && eslint --fix .",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen"
},
@ -54,9 +55,5 @@
"postcss": "^8.4.14",
"pretty-quick": "^3.1.3",
"typescript": "4.8.3"
},
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix",
"*.{js,ts,tsx,css,md,json}": "prettier --write"
}
}

View file

@ -1,6 +1,8 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the browser.
* The config you add here will be used whenever a page is visited.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
@ -10,8 +12,10 @@ Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,6 +1,8 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever middleware or an Edge route handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever middleware or an Edge route handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
@ -10,8 +12,10 @@ Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -1,6 +1,8 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
/*
* This file configures the initialization of Sentry on the server.
* The config you add here will be used whenever the server handles a request.
* https://docs.sentry.io/platforms/javascript/guides/nextjs/
*/
import * as Sentry from "@sentry/nextjs";
@ -10,8 +12,10 @@ Sentry.init({
dsn: SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
/*
* ...
* Note: if you want to override the automatic release value, do not set a
* `release` value here - use the environment variable `SENTRY_RELEASE`, so
* that it will also get attached to your source maps
*/
});

View file

@ -12,10 +12,12 @@ function _ThemeSynchronizer() {
const { appBridgeState, appBridge } = useAppBridge();
const { setTheme, themeType } = useTheme();
// todo - replace this hook to appBridge.subscribe and react only only on initial theme event
// useEffect(() =>{
// appBridge?.subscribe('theme',console.log)
// },[appBridge])
/*
* todo - replace this hook to appBridge.subscribe and react only only on initial theme event
* useEffect(() =>{
* appBridge?.subscribe('theme',console.log)
* },[appBridge])
*/
useEffect(() => {
if (!setTheme || !appBridgeState?.theme) {

View file

@ -39,6 +39,7 @@ export const useAppApi = <D>({ url, options, skip }: UseFetchProps) => {
}
const json = await res.json();
setData(json);
} catch (e) {
setError(e as unknown);

View file

@ -8,10 +8,12 @@ import {
} from "../../generated/graphql";
import { settingsManagerSecretKey } from "./saleor-app";
// Function is using urql graphql client to fetch all available metadata.
// Before returning query result, we are transforming response to list of objects with key and value fields
// which can be used by the manager.
// Result of this query is cached by the manager.
/*
* Function is using urql graphql client to fetch all available metadata.
* Before returning query result, we are transforming response to list of objects with key and value fields
* which can be used by the manager.
* Result of this query is cached by the manager.
*/
export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]> {
const { error, data } = await client
.query<FetchAppDetailsQuery>(FetchAppDetailsDocument, {})
@ -25,9 +27,11 @@ export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]>
return data?.app?.privateMetadata.map((md) => ({ key: md.key, value: md.value })) || [];
}
// Mutate function takes urql client and metadata entries, and construct mutation to the API.
// Before data are send, additional query for required App ID is made.
// The manager will use updated entries returned by this mutation to update it's cache.
/*
* Mutate function takes urql client and metadata entries, and construct mutation to the API.
* Before data are send, additional query for required App ID is made.
* The manager will use updated entries returned by this mutation to update it's cache.
*/
export async function mutateMetadata(client: Client, appId: string, metadata: MetadataEntry[]) {
const { error: mutationError, data: mutationData } = await client
.mutation(UpdateAppMetadataDocument, {
@ -50,9 +54,11 @@ export async function mutateMetadata(client: Client, appId: string, metadata: Me
}
export const createSettingsManager = (client: Client, appId: string) =>
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
/*
* EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
* We recommend it for production, because all values are encrypted.
* If your use case require plain text values, you can use MetadataManager.
*/
new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: settingsManagerSecretKey,

View file

@ -10,6 +10,7 @@ import { SaleorApp } from "@saleor/app-sdk/saleor-app";
*/
let apl: APL;
switch (process.env.APL) {
case "upstash":
// Require `UPSTASH_URL` and `UPSTASH_TOKEN` environment variables
@ -30,12 +31,14 @@ switch (process.env.APL) {
apl = new FileAPL();
}
// TODO: Investigate why no-ssr-wrapper does not prevent this code from execution during the build time
// if (!process.env.SECRET_KEY && process.env.NODE_ENV === "production") {
// throw new Error(
// "For production deployment SECRET_KEY is mandatory to use EncryptedSettingsManager."
// );
// }
/*
* TODO: Investigate why no-ssr-wrapper does not prevent this code from execution during the build time
* if (!process.env.SECRET_KEY && process.env.NODE_ENV === "production") {
* throw new Error(
* "For production deployment SECRET_KEY is mandatory to use EncryptedSettingsManager."
* );
* }
*/
// Use placeholder value for the development
export const settingsManagerSecretKey = process.env.SECRET_KEY || "CHANGE_ME";

View file

@ -73,6 +73,7 @@ function SaleorApp({ Component, pageProps }: AppLayoutProps) {
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}

View file

@ -20,16 +20,20 @@ import * as Sentry from "@sentry/nextjs";
import NextErrorComponent from "next/error";
const CustomErrorComponent = (props) => {
// If you're using a Nextjs version prior to 12.2.1, uncomment this to
// compensate for https://github.com/vercel/next.js/issues/8592
// Sentry.captureUnderscoreErrorException(props);
/*
* If you're using a Nextjs version prior to 12.2.1, uncomment this to
* compensate for https://github.com/vercel/next.js/issues/8592
* Sentry.captureUnderscoreErrorException(props);
*/
return <NextErrorComponent statusCode={props.statusCode} />;
};
CustomErrorComponent.getInitialProps = async (contextData) => {
// In case this is running in a serverless function, await this in order to give Sentry
// time to send the error before the lambda exits
/*
* In case this is running in a serverless function, await this in order to give Sentry
* time to send the error before the lambda exits
*/
await Sentry.captureUnderscoreErrorException(contextData);
// This will contain the status code of the response

View file

@ -15,10 +15,12 @@ interface AppErrorProps extends ErrorProps {
function MyError({ statusCode, hasGetInitialPropsRun, err }: ErrorPageProps) {
if (!hasGetInitialPropsRun && err) {
// getInitialProps is not called when an exception is thrown
// at the top level of a module while it is being loaded.
// As a workaround, we pass err via _app.js so it can be captured
// Read more: https://github.com/vercel/next.js/issues/8592.
/*
* getInitialProps is not called when an exception is thrown
* at the top level of a module while it is being loaded.
* As a workaround, we pass err via _app.js so it can be captured
* Read more: https://github.com/vercel/next.js/issues/8592.
*/
Sentry.captureException(err);
// Flushing is not required in this case as it only happens on the client
}
@ -31,8 +33,10 @@ MyError.getInitialProps = async (context: NextPageContext) => {
const { res, err, asPath } = context;
// Workaround for https://github.com/vercel/next.js/issues/8592, mark when
// getInitialProps has run
/*
* Workaround for https://github.com/vercel/next.js/issues/8592, mark when
* getInitialProps has run
*/
errorInitialProps.hasGetInitialPropsRun = true;
// Returning early because we don't want to log 404 errors to Sentry.
@ -40,32 +44,38 @@ MyError.getInitialProps = async (context: NextPageContext) => {
return errorInitialProps;
}
// Running on the server, the response object (`res`) is available.
//
// Next.js will pass an err on the server if a page's data fetching methods
// threw or returned a Promise that rejected
//
// Running on the client (browser), Next.js will provide an err if:
//
// - a page's `getInitialProps` threw or returned a Promise that rejected
// - an exception was thrown somewhere in the React lifecycle (render,
// componentDidMount, etc) that was caught by Next.js's React Error
// Boundary. Read more about what types of exceptions are caught by Error
// Boundaries: https://reactjs.org/docs/error-boundaries.html
/*
* Running on the server, the response object (`res`) is available.
*
* Next.js will pass an err on the server if a page's data fetching methods
* threw or returned a Promise that rejected
*
* Running on the client (browser), Next.js will provide an err if:
*
* - a page's `getInitialProps` threw or returned a Promise that rejected
* - an exception was thrown somewhere in the React lifecycle (render,
* componentDidMount, etc) that was caught by Next.js's React Error
* Boundary. Read more about what types of exceptions are caught by Error
* Boundaries: https://reactjs.org/docs/error-boundaries.html
*/
if (err) {
Sentry.captureException(err);
// Flushing before returning is necessary if deploying to Vercel, see
// https://vercel.com/docs/platform/limits#streaming-responses
/*
* Flushing before returning is necessary if deploying to Vercel, see
* https://vercel.com/docs/platform/limits#streaming-responses
*/
await Sentry.flush(2000);
return errorInitialProps;
}
// If this point is reached, getInitialProps was called without any
// information about what the error might be. This is unexpected and may
// indicate a bug introduced in Next.js, so record it in Sentry
/*
* If this point is reached, getInitialProps was called without any
* information about what the error might be. This is unexpected and may
* indicate a bug introduced in Next.js, so record it in Sentry
*/
Sentry.captureException(new Error(`_error.js getInitialProps missing data at path: ${asPath}`));
await Sentry.flush(2000);

View file

@ -34,6 +34,7 @@ export const handler = async (
case "POST": {
const reqBody = req.body as PostRequestBody;
const newWebhookUrl = (await reqBody.data?.find((entry) => entry.key === WEBHOOK_URL))?.value;
if (!newWebhookUrl) {
console.error("New value for the webhook URL has not been found");
res.status(400).json({

View file

@ -8,6 +8,7 @@ const handler = createAppRegisterHandler({
(url) => {
if (allowedUrlsPattern) {
const regex = new RegExp(allowedUrlsPattern);
if (regex.test(url)) {
console.debug(`Registration from the URL ${url} has been accepted`);
return true;

View file

@ -107,6 +107,7 @@ const handler: NextWebhookApiHandler<OrderCreatedWebhookPayloadFragment> = async
if (response.status !== 200) {
const errorMessage = await response.text();
console.error(`Slack API responded with code ${response.status}: ${errorMessage}`);
return res.status(500).send({

View file

@ -79,6 +79,7 @@ function Configuration() {
const onChange = (event: ChangeEvent) => {
const { name, value } = event.target as HTMLInputElement;
setConfiguration((prev) =>
prev!.map((prevField) => (prevField.key === name ? { ...prevField, value } : prevField))
);
@ -129,6 +130,7 @@ function Instructions() {
});
const slackUrl = new URL("https://api.slack.com/apps");
slackUrl.searchParams.append("new_app", "1");
slackUrl.searchParams.append("manifest_json", JSON.stringify(data));

View file

@ -7,6 +7,7 @@
"build": "pnpm generate && next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "eslint --fix .",
"fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql",
"generate": "graphql-codegen",
"test": "vitest"

View file

@ -20,4 +20,5 @@ module.exports = {
},
},
],
ignorePatterns: ["next-env.d.ts"],
};

View file

@ -20,5 +20,8 @@
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"scripts": {
"lint:fix": "eslint --fix ."
},
"main": "index.ts"
}

View file

@ -24,6 +24,7 @@
},
"generate": {
"outputs": ["generated/"]
}
},
"lint:fix": {}
}
}