From c786483f8bebeed5b774ef29d47b60a404e0225d Mon Sep 17 00:00:00 2001 From: Krzysztof Wolski Date: Wed, 15 Feb 2023 12:32:33 +0100 Subject: [PATCH] Search: Split webhook subscription query (#151) * Split the search subscription query * Add changeset --- .changeset/nasty-avocados-drive.md | 5 + .../subscriptions/productCreated.graphql | 11 ++ .../subscriptions/productDeleted.graphql | 11 ++ .../subscriptions/productEdited.graphql | 41 ------- .../subscriptions/productUpdated.graphql | 11 ++ .../productVariantCreated.graphql | 11 ++ .../productVariantDeleted.graphql | 11 ++ .../productVariantUpdated.graphql | 11 ++ .../lib/algolia/getAlgoliaConfiguration.ts | 61 +++++++++++ .../src/pages/api/webhooks/saleor/_index.ts | 102 ------------------ .../api/webhooks/saleor/product_created.ts | 44 +++++++- .../api/webhooks/saleor/product_deleted.ts | 44 +++++++- .../api/webhooks/saleor/product_updated.ts | 44 +++++++- .../saleor/product_variant_created.ts | 50 +++++++-- .../saleor/product_variant_deleted.ts | 49 +++++++-- .../saleor/product_variant_updated.ts | 49 +++++++-- 16 files changed, 376 insertions(+), 179 deletions(-) create mode 100644 .changeset/nasty-avocados-drive.md create mode 100644 apps/search/graphql/subscriptions/productCreated.graphql create mode 100644 apps/search/graphql/subscriptions/productDeleted.graphql delete mode 100644 apps/search/graphql/subscriptions/productEdited.graphql create mode 100644 apps/search/graphql/subscriptions/productUpdated.graphql create mode 100644 apps/search/graphql/subscriptions/productVariantCreated.graphql create mode 100644 apps/search/graphql/subscriptions/productVariantDeleted.graphql create mode 100644 apps/search/graphql/subscriptions/productVariantUpdated.graphql create mode 100644 apps/search/src/lib/algolia/getAlgoliaConfiguration.ts delete mode 100644 apps/search/src/pages/api/webhooks/saleor/_index.ts diff --git a/.changeset/nasty-avocados-drive.md b/.changeset/nasty-avocados-drive.md new file mode 100644 index 0000000..74662e4 --- /dev/null +++ b/.changeset/nasty-avocados-drive.md @@ -0,0 +1,5 @@ +--- +"saleor-app-search": patch +--- + +Subscription queries for webhooks has been splitted to pass a new validation diff --git a/apps/search/graphql/subscriptions/productCreated.graphql b/apps/search/graphql/subscriptions/productCreated.graphql new file mode 100644 index 0000000..5f7fe4f --- /dev/null +++ b/apps/search/graphql/subscriptions/productCreated.graphql @@ -0,0 +1,11 @@ +subscription ProductCreated { + event { + __typename + ... on ProductCreated { + __typename + product { + ...ProductWebhookPayload + } + } + } +} diff --git a/apps/search/graphql/subscriptions/productDeleted.graphql b/apps/search/graphql/subscriptions/productDeleted.graphql new file mode 100644 index 0000000..1a8cea6 --- /dev/null +++ b/apps/search/graphql/subscriptions/productDeleted.graphql @@ -0,0 +1,11 @@ +subscription ProductDeleted { + event { + __typename + ... on ProductDeleted { + __typename + product { + ...ProductWebhookPayload + } + } + } +} diff --git a/apps/search/graphql/subscriptions/productEdited.graphql b/apps/search/graphql/subscriptions/productEdited.graphql deleted file mode 100644 index aebec08..0000000 --- a/apps/search/graphql/subscriptions/productEdited.graphql +++ /dev/null @@ -1,41 +0,0 @@ -subscription ProductEdited { - event { - __typename - ... on ProductUpdated { - __typename - product { - ...ProductWebhookPayload - } - } - ... on ProductCreated { - __typename - product { - ...ProductWebhookPayload - } - } - ... on ProductDeleted { - __typename - product { - ...ProductWebhookPayload - } - } - ... on ProductVariantCreated { - __typename - productVariant { - ...ProductVariantWebhookPayload - } - } - ... on ProductVariantUpdated { - __typename - productVariant { - ...ProductVariantWebhookPayload - } - } - ... on ProductVariantDeleted { - __typename - productVariant { - ...ProductVariantWebhookPayload - } - } - } -} diff --git a/apps/search/graphql/subscriptions/productUpdated.graphql b/apps/search/graphql/subscriptions/productUpdated.graphql new file mode 100644 index 0000000..c3f7528 --- /dev/null +++ b/apps/search/graphql/subscriptions/productUpdated.graphql @@ -0,0 +1,11 @@ +subscription ProductUpdated { + event { + __typename + ... on ProductUpdated { + __typename + product { + ...ProductWebhookPayload + } + } + } +} diff --git a/apps/search/graphql/subscriptions/productVariantCreated.graphql b/apps/search/graphql/subscriptions/productVariantCreated.graphql new file mode 100644 index 0000000..3e4c23e --- /dev/null +++ b/apps/search/graphql/subscriptions/productVariantCreated.graphql @@ -0,0 +1,11 @@ +subscription ProductVariantCreated { + event { + __typename + ... on ProductVariantCreated { + __typename + productVariant { + ...ProductVariantWebhookPayload + } + } + } +} diff --git a/apps/search/graphql/subscriptions/productVariantDeleted.graphql b/apps/search/graphql/subscriptions/productVariantDeleted.graphql new file mode 100644 index 0000000..715b470 --- /dev/null +++ b/apps/search/graphql/subscriptions/productVariantDeleted.graphql @@ -0,0 +1,11 @@ +subscription ProductVariantDeleted { + event { + __typename + ... on ProductVariantDeleted { + __typename + productVariant { + ...ProductVariantWebhookPayload + } + } + } +} diff --git a/apps/search/graphql/subscriptions/productVariantUpdated.graphql b/apps/search/graphql/subscriptions/productVariantUpdated.graphql new file mode 100644 index 0000000..16be24b --- /dev/null +++ b/apps/search/graphql/subscriptions/productVariantUpdated.graphql @@ -0,0 +1,11 @@ +subscription ProductVariantUpdated { + event { + __typename + ... on ProductVariantUpdated { + __typename + productVariant { + ...ProductVariantWebhookPayload + } + } + } +} diff --git a/apps/search/src/lib/algolia/getAlgoliaConfiguration.ts b/apps/search/src/lib/algolia/getAlgoliaConfiguration.ts new file mode 100644 index 0000000..abbb0ad --- /dev/null +++ b/apps/search/src/lib/algolia/getAlgoliaConfiguration.ts @@ -0,0 +1,61 @@ +import { AuthData } from "@saleor/app-sdk/APL"; +import { createDebug } from "../debug"; +import { createClient } from "../graphql"; +import { createSettingsManager } from "../metadata"; + +interface GetAlgoliaConfigurationArgs { + authData: AuthData; +} + +const debug = createDebug("getAlgoliaConfiguration"); + +export const getAlgoliaConfiguration = async ({ authData }: GetAlgoliaConfigurationArgs) => { + const client = createClient(authData.saleorApiUrl, async () => + Promise.resolve({ token: authData.token }) + ); + + const settings = createSettingsManager(client); + + try { + const secretKey = await settings.get("secretKey", authData.domain); + if (!secretKey?.length) { + return { + errors: [ + { + message: + "Missing secret key to the Algolia API. Please, configure the application first.", + }, + ], + }; + } + + const appId = await settings.get("appId", authData.domain); + if (!appId?.length) { + return { + errors: [ + { + message: "Missing App ID to the Algolia API. Please, configure the application first.", + }, + ], + }; + } + + const indexNamePrefix = (await settings.get("indexNamePrefix", authData.domain)) || ""; + debug("Configuration fetched"); + return { + settings: { + appId, + secretKey, + indexNamePrefix, + }, + }; + } catch (error) { + debug("Unexpected error during fetching the configuration"); + if (error instanceof Error) { + debug(error.message); + } + return { + errors: [{ message: "Couldn't fetch the settings from the API" }], + }; + } +}; diff --git a/apps/search/src/pages/api/webhooks/saleor/_index.ts b/apps/search/src/pages/api/webhooks/saleor/_index.ts deleted file mode 100644 index 6b2d323..0000000 --- a/apps/search/src/pages/api/webhooks/saleor/_index.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedSubscription } from "../../../../../generated/graphql"; -import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; -import { createDebug } from "../../../../lib/debug"; -import { createClient } from "../../../../lib/graphql"; -import { createSettingsManager } from "../../../../lib/metadata"; -import { AlgoliaConfigurationFields } from "../../../../lib/algolia/types"; - -const debug = createDebug("Webhooks handler"); - -export const handler: NextWebhookApiHandler = async ( - req, - res, - context -) => { - const { event, authData } = context; - debug( - `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 }) - ); - - const settings = createSettingsManager(client); - - const algoliaConfiguration: AlgoliaConfigurationFields = { - secretKey: (await settings.get("secretKey", authData.domain)) || "", - appId: (await settings.get("appId", authData.domain)) || "", - indexNamePrefix: (await settings.get("indexNamePrefix", authData.domain)) || "", - }; - - if (!algoliaConfiguration?.appId) { - debug("Missing AppID configuration - returning error response"); - return res.status(500).json({ - message: `Missing 'appId'`, - }); - } - if (!algoliaConfiguration.secretKey) { - debug("Missing SecretKey configuration - returning error response"); - return res.status(500).json({ - message: `Missing 'secretKey'`, - }); - } - - const searchProvider = new AlgoliaSearchProvider({ - appId: algoliaConfiguration.appId, - apiKey: algoliaConfiguration.secretKey, - indexNamePrefix: algoliaConfiguration.indexNamePrefix, - }); - - switch (context.payload?.__typename) { - case "ProductCreated": { - const { product } = context.payload; - if (product) { - await searchProvider.createProduct(product); - } - res.status(200).end(); - return; - } - case "ProductUpdated": { - const { product } = context.payload; - if (product) { - await searchProvider.updateProduct(product); - } - res.status(200).end(); - return; - } - case "ProductDeleted": { - const { product } = context.payload; - if (product) { - await searchProvider.deleteProduct(product); - } - res.status(200).end(); - return; - } - case "ProductVariantCreated": { - const { productVariant } = context.payload; - if (productVariant) { - await searchProvider.createProductVariant(productVariant); - } - res.status(200).end(); - return; - } - case "ProductVariantUpdated": { - const { productVariant } = context.payload; - if (productVariant) { - await searchProvider.updateProductVariant(productVariant); - } - res.status(200).end(); - return; - } - case "ProductVariantDeleted": { - const { productVariant } = context.payload; - if (productVariant) { - await searchProvider.deleteProductVariant(productVariant); - } - res.status(200).end(); - return; - } - } -}; diff --git a/apps/search/src/pages/api/webhooks/saleor/product_created.ts b/apps/search/src/pages/api/webhooks/saleor/product_created.ts index 9572b87..8d72126 100644 --- a/apps/search/src/pages/api/webhooks/saleor/product_created.ts +++ b/apps/search/src/pages/api/webhooks/saleor/product_created.ts @@ -1,7 +1,9 @@ -import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedDocument, ProductEditedSubscription } from "../../../../../generated/graphql"; +import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { ProductCreated, ProductCreatedDocument } from "../../../../../generated/graphql"; import { saleorApp } from "../../../../../saleor-app"; -import { handler } from "./_index"; +import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; +import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration"; +import { createDebug } from "../../../../lib/debug"; export const config = { api: { @@ -9,11 +11,43 @@ export const config = { }, }; -export const webhookProductCreated = new SaleorAsyncWebhook({ +export const webhookProductCreated = new SaleorAsyncWebhook({ webhookPath: "api/webhooks/saleor/product_created", asyncEvent: "PRODUCT_CREATED", apl: saleorApp.apl, - subscriptionQueryAst: ProductEditedDocument, + subscriptionQueryAst: ProductCreatedDocument, }); +export const handler: NextWebhookApiHandler = async (req, res, context) => { + const debug = createDebug(`Webhook handler - ${webhookProductCreated.asyncEvent}`); + + const { event, authData } = context; + debug( + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` + ); + + const { settings, errors } = await getAlgoliaConfiguration({ authData }); + + if (errors?.length || !settings) { + debug("Aborting due to lack of settings"); + debug(errors); + return res.status(400).json({ + message: errors[0].message, + }); + } + + const searchProvider = new AlgoliaSearchProvider({ + appId: settings.appId, + apiKey: settings.secretKey, + indexNamePrefix: settings.indexNamePrefix, + }); + + const { product } = context.payload; + if (product) { + await searchProvider.createProduct(product); + } + res.status(200).end(); + return; +}; + export default webhookProductCreated.createHandler(handler); diff --git a/apps/search/src/pages/api/webhooks/saleor/product_deleted.ts b/apps/search/src/pages/api/webhooks/saleor/product_deleted.ts index fb779ae..6450613 100644 --- a/apps/search/src/pages/api/webhooks/saleor/product_deleted.ts +++ b/apps/search/src/pages/api/webhooks/saleor/product_deleted.ts @@ -1,7 +1,9 @@ -import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedDocument, ProductEditedSubscription } from "../../../../../generated/graphql"; +import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { ProductDeleted, ProductDeletedDocument } from "../../../../../generated/graphql"; import { saleorApp } from "../../../../../saleor-app"; -import { handler } from "./_index"; +import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; +import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration"; +import { createDebug } from "../../../../lib/debug"; export const config = { api: { @@ -9,11 +11,43 @@ export const config = { }, }; -export const webhookProductDeleted = new SaleorAsyncWebhook({ +export const webhookProductDeleted = new SaleorAsyncWebhook({ webhookPath: "api/webhooks/saleor/product_deleted", asyncEvent: "PRODUCT_DELETED", apl: saleorApp.apl, - subscriptionQueryAst: ProductEditedDocument, + subscriptionQueryAst: ProductDeletedDocument, }); +export const handler: NextWebhookApiHandler = async (req, res, context) => { + const debug = createDebug(`Webhook handler - ${webhookProductDeleted.asyncEvent}`); + + const { event, authData } = context; + debug( + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` + ); + + const { settings, errors } = await getAlgoliaConfiguration({ authData }); + + if (errors?.length || !settings) { + debug("Aborting due to lack of settings"); + debug(errors); + return res.status(400).json({ + message: errors[0].message, + }); + } + + const searchProvider = new AlgoliaSearchProvider({ + appId: settings.appId, + apiKey: settings.secretKey, + indexNamePrefix: settings.indexNamePrefix, + }); + + const { product } = context.payload; + if (product) { + await searchProvider.deleteProduct(product); + } + res.status(200).end(); + return; +}; + export default webhookProductDeleted.createHandler(handler); diff --git a/apps/search/src/pages/api/webhooks/saleor/product_updated.ts b/apps/search/src/pages/api/webhooks/saleor/product_updated.ts index bbcbd55..d096939 100644 --- a/apps/search/src/pages/api/webhooks/saleor/product_updated.ts +++ b/apps/search/src/pages/api/webhooks/saleor/product_updated.ts @@ -1,7 +1,9 @@ -import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedDocument, ProductEditedSubscription } from "../../../../../generated/graphql"; +import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { ProductUpdated, ProductUpdatedDocument } from "../../../../../generated/graphql"; import { saleorApp } from "../../../../../saleor-app"; -import { handler } from "./_index"; +import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; +import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration"; +import { createDebug } from "../../../../lib/debug"; export const config = { api: { @@ -9,11 +11,43 @@ export const config = { }, }; -export const webhookProductUpdated = new SaleorAsyncWebhook({ +export const webhookProductUpdated = new SaleorAsyncWebhook({ webhookPath: "api/webhooks/saleor/product_updated", asyncEvent: "PRODUCT_UPDATED", apl: saleorApp.apl, - subscriptionQueryAst: ProductEditedDocument, + subscriptionQueryAst: ProductUpdatedDocument, }); +export const handler: NextWebhookApiHandler = async (req, res, context) => { + const debug = createDebug(`Webhook handler - ${webhookProductUpdated.asyncEvent}`); + + const { event, authData } = context; + debug( + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` + ); + + const { settings, errors } = await getAlgoliaConfiguration({ authData }); + + if (errors?.length || !settings) { + debug("Aborting due to lack of settings"); + debug(errors); + return res.status(400).json({ + message: errors[0].message, + }); + } + + const searchProvider = new AlgoliaSearchProvider({ + appId: settings.appId, + apiKey: settings.secretKey, + indexNamePrefix: settings.indexNamePrefix, + }); + + const { product } = context.payload; + if (product) { + await searchProvider.updateProduct(product); + } + res.status(200).end(); + return; +}; + export default webhookProductUpdated.createHandler(handler); diff --git a/apps/search/src/pages/api/webhooks/saleor/product_variant_created.ts b/apps/search/src/pages/api/webhooks/saleor/product_variant_created.ts index e5e169e..537480b 100644 --- a/apps/search/src/pages/api/webhooks/saleor/product_variant_created.ts +++ b/apps/search/src/pages/api/webhooks/saleor/product_variant_created.ts @@ -1,20 +1,56 @@ -import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedDocument, ProductEditedSubscription } from "../../../../../generated/graphql"; +import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { + ProductVariantCreated, + ProductVariantCreatedDocument, +} from "../../../../../generated/graphql"; import { saleorApp } from "../../../../../saleor-app"; -import { handler } from "./_index"; +import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; +import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration"; +import { createDebug } from "../../../../lib/debug"; + export const config = { api: { bodyParser: false, }, }; -export const webhookProductVariantCreated = new SaleorAsyncWebhook< - ProductEditedSubscription["event"] ->({ +export const webhookProductVariantCreated = new SaleorAsyncWebhook({ webhookPath: "api/webhooks/saleor/product_variant_created", asyncEvent: "PRODUCT_VARIANT_CREATED", apl: saleorApp.apl, - subscriptionQueryAst: ProductEditedDocument, + subscriptionQueryAst: ProductVariantCreatedDocument, }); +export const handler: NextWebhookApiHandler = async (req, res, context) => { + const debug = createDebug(`Webhook handler - ${webhookProductVariantCreated.asyncEvent}`); + + const { event, authData } = context; + debug( + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` + ); + + const { settings, errors } = await getAlgoliaConfiguration({ authData }); + + if (errors?.length || !settings) { + debug("Aborting due to lack of settings"); + debug(errors); + return res.status(400).json({ + message: errors[0].message, + }); + } + + const searchProvider = new AlgoliaSearchProvider({ + appId: settings.appId, + apiKey: settings.secretKey, + indexNamePrefix: settings.indexNamePrefix, + }); + + const { productVariant } = context.payload; + if (productVariant) { + await searchProvider.createProductVariant(productVariant); + } + res.status(200).end(); + return; +}; + export default webhookProductVariantCreated.createHandler(handler); diff --git a/apps/search/src/pages/api/webhooks/saleor/product_variant_deleted.ts b/apps/search/src/pages/api/webhooks/saleor/product_variant_deleted.ts index 57e2067..84dc44d 100644 --- a/apps/search/src/pages/api/webhooks/saleor/product_variant_deleted.ts +++ b/apps/search/src/pages/api/webhooks/saleor/product_variant_deleted.ts @@ -1,7 +1,12 @@ -import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedDocument, ProductEditedSubscription } from "../../../../../generated/graphql"; +import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { + ProductVariantDeleted, + ProductVariantDeletedDocument, +} from "../../../../../generated/graphql"; import { saleorApp } from "../../../../../saleor-app"; -import { handler } from "./_index"; +import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; +import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration"; +import { createDebug } from "../../../../lib/debug"; export const config = { api: { @@ -9,13 +14,43 @@ export const config = { }, }; -export const webhookProductVariantDeleted = new SaleorAsyncWebhook< - ProductEditedSubscription["event"] ->({ +export const webhookProductVariantDeleted = new SaleorAsyncWebhook({ webhookPath: "api/webhooks/saleor/product_variant_deleted", asyncEvent: "PRODUCT_VARIANT_DELETED", apl: saleorApp.apl, - subscriptionQueryAst: ProductEditedDocument, + subscriptionQueryAst: ProductVariantDeletedDocument, }); +export const handler: NextWebhookApiHandler = async (req, res, context) => { + const debug = createDebug(`Webhook handler - ${webhookProductVariantDeleted.asyncEvent}`); + + const { event, authData } = context; + debug( + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` + ); + + const { settings, errors } = await getAlgoliaConfiguration({ authData }); + + if (errors?.length || !settings) { + debug("Aborting due to lack of settings"); + debug(errors); + return res.status(400).json({ + message: errors[0].message, + }); + } + + const searchProvider = new AlgoliaSearchProvider({ + appId: settings.appId, + apiKey: settings.secretKey, + indexNamePrefix: settings.indexNamePrefix, + }); + + const { productVariant } = context.payload; + if (productVariant) { + await searchProvider.deleteProductVariant(productVariant); + } + res.status(200).end(); + return; +}; + export default webhookProductVariantDeleted.createHandler(handler); diff --git a/apps/search/src/pages/api/webhooks/saleor/product_variant_updated.ts b/apps/search/src/pages/api/webhooks/saleor/product_variant_updated.ts index 9e4f7c7..6d0d10e 100644 --- a/apps/search/src/pages/api/webhooks/saleor/product_variant_updated.ts +++ b/apps/search/src/pages/api/webhooks/saleor/product_variant_updated.ts @@ -1,7 +1,12 @@ -import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; -import { ProductEditedDocument, ProductEditedSubscription } from "../../../../../generated/graphql"; +import { NextWebhookApiHandler, SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { + ProductVariantUpdated, + ProductVariantUpdatedDocument, +} from "../../../../../generated/graphql"; import { saleorApp } from "../../../../../saleor-app"; -import { handler } from "./_index"; +import { AlgoliaSearchProvider } from "../../../../lib/algolia/algoliaSearchProvider"; +import { getAlgoliaConfiguration } from "../../../../lib/algolia/getAlgoliaConfiguration"; +import { createDebug } from "../../../../lib/debug"; export const config = { api: { @@ -9,13 +14,43 @@ export const config = { }, }; -export const webhookProductVariantUpdated = new SaleorAsyncWebhook< - ProductEditedSubscription["event"] ->({ +export const webhookProductVariantUpdated = new SaleorAsyncWebhook({ webhookPath: "api/webhooks/saleor/product_variant_updated", asyncEvent: "PRODUCT_VARIANT_UPDATED", apl: saleorApp.apl, - subscriptionQueryAst: ProductEditedDocument, + subscriptionQueryAst: ProductVariantUpdatedDocument, }); +export const handler: NextWebhookApiHandler = async (req, res, context) => { + const debug = createDebug(`Webhook handler - ${webhookProductVariantUpdated.asyncEvent}`); + + const { event, authData } = context; + debug( + `New event ${event} (${context.payload?.__typename}) from the ${authData.domain} domain has been received!` + ); + + const { settings, errors } = await getAlgoliaConfiguration({ authData }); + + if (errors?.length || !settings) { + debug("Aborting due to lack of settings"); + debug(errors); + return res.status(400).json({ + message: errors[0].message, + }); + } + + const searchProvider = new AlgoliaSearchProvider({ + appId: settings.appId, + apiKey: settings.secretKey, + indexNamePrefix: settings.indexNamePrefix, + }); + + const { productVariant } = context.payload; + if (productVariant) { + await searchProvider.updateProductVariant(productVariant); + } + res.status(200).end(); + return; +}; + export default webhookProductVariantUpdated.createHandler(handler);