Skip to content

bluestone-commercetools

@evolve-framework/bluestone-commercetools · v1.0.0

Keeps a commercetools catalog in step with Bluestone PIM, by syncing the categories, products, variants and related products that changed after each Bluestone publish.

When to use

Use it when a shop on @evolve-framework/commercetools gets its product data from Bluestone PIM. The package writes to commercetools:

  • Categories: the subtree under BLUESTONE_CATEGORY_WEBSHOP_ID, with the category custom type COMMERCETOOLS_CATEGORY_TYPE_KEY.
  • Products and variants: keyed by the Bluestone product number, with a product type from BLUESTONE_PRODUCT_TYPE_MAPPING and the tax category COMMERCETOOLS_TAX_CATEGORY_KEY. Products are published.
  • Specifications: the Bluestone attributes of each variant, as a custom object in the COMMERCETOOLS_PRODUCT_SPECIFICATIONS_CONTAINER container.
  • Related products: the related-products attribute.

The commercetools project must already have the category custom type, the product types and the tax category. The product types need the variant attributes syncId, syncDate, specifications and related-products, and the category type needs the fields syncId and syncDate. Every product must be in a category that BLUESTONE_PRODUCT_TYPE_MAPPING maps to a product type.

A shop on Medusa uses @evolve-framework/medusa-plugin-bluestone instead.

Get started

  1. Install the package. It comes from the Evolve registry, which needs a one-time sign-in.

    pnpm add @evolve-framework/bluestone-commercetools

For example:

import { createSyncContext } from "@evolve-framework/bluestone-commercetools";
import { BluestoneCommercetoolsConfig } from "@evolve-framework/bluestone-commercetools/config";
import { handleProductSyncDone } from "@evolve-framework/bluestone-commercetools/events/product-sync-done";
import { webhookPayloadSchema } from "@evolve-framework/bluestone-commercetools/messages";
import { BluestoneCommercetoolsModule } from "@evolve-framework/bluestone-commercetools/module";
import { createSQSHandler, SqsPublisher } from "@evolve-framework/cloud-adapter-aws";
import { createApplication } from "@evolve-framework/core";
const config = await BluestoneCommercetoolsConfig.load();
// The web service: it checks Bluestone's webhook and queues the payload.
const publisher = new SqsPublisher(config.BLUESTONE_WEBHOOK_TARGET);
const app = await createApplication({
name: "bluestone-commercetools",
module: new BluestoneCommercetoolsModule({
config: {
webhookSecret: config.BLUESTONE_WEBHOOK_SECRET,
validateSignature: config.BLUESTONE_WEBHOOK_VALIDATE_SIGNATURE,
},
publishMessage: (payload) => publisher.publish(payload),
}),
http: { address: { host: "0.0.0.0", port: 8080 } },
});
await app.start();
// The queue consumer, usually a separate function: it runs the sync.
const ctx = await createSyncContext(config);
export const handler = createSQSHandler(
(payload) => handleProductSyncDone(ctx, payload),
(message) => webhookPayloadSchema.parse(message),
);

Modules

BluestoneCommercetoolsModule

The HTTP module that receives Bluestone's webhook.

  • POST /product-sync-done verifies the signature and the payload, passes the payload to publishMessage and answers 201. It answers 401 for a bad signature or payload, and 500 when publishMessage throws.
  • GET /healthcheck answers 200 with the component name.

It does not run the sync: a queue consumer does that with handleProductSyncDone, so Bluestone gets its answer at once.

import { BluestoneCommercetoolsModule } from "@evolve-framework/bluestone-commercetools";
new BluestoneCommercetoolsModule(options: BluestoneCommercetoolsModuleOptions)
OptionTypeDescription
configBluestoneCommercetoolsModuleConfig

How the webhook checks its calls, and what the healthcheck reports.

publishMessage(payload: { timestamp: number; events: { changes: { eventType: "PRODUCT_SYNC_DONE"; entityIds: string[]; syncDoneData: { field: string; value: string; context: …

Called with the payload once its signature and shape are valid. It usually publishes to a queue, with a MessagePublisher from a cloud adapter. A test or a single-process deployment can call handleProductSyncDone directly instead, but then Bluestone waits for the whole sync.

BluestoneCommercetoolsModuleConfig3The fields of config.
FieldTypeDescription
webhookSecretstring

HMAC-SHA256 secret used to verify the x-bs-signature header.

validateSignature?boolean

Whether to verify the x-bs-signature header. Defaults to true. Set it to false only for local development against a Bluestone tenant that does not send signatures.

componentName?string

Reported by GET /healthcheck. Defaults to bluestone-commercetools.

Extends AbstractModule<unknown>.

Testing

Test helpers in /testing. What they are for

Entry points

@evolve-framework/bluestone-commercetoolsEverything below except ./testing, plus SyncContext and createSyncContext14 exports
@evolve-framework/bluestone-commercetools/clientBluestonePimClient and createBluestonePimClient, the Bluestone PIM API client, which retries when it is rate limited2 exports
@evolve-framework/bluestone-commercetools/commercetoolscreateCtClient, the commercetools request builder for the sync1 export
@evolve-framework/bluestone-commercetools/configBluestoneCommercetoolsConfig, the environment configuration that a service loads or extends1 export
@evolve-framework/bluestone-commercetools/core/syncsync, which applies one Bluestone sync to commercetools1 export
@evolve-framework/bluestone-commercetools/events/product-sync-donehandleProductSyncDone, the queue consumer for a webhook payload1 export
@evolve-framework/bluestone-commercetools/messageswebhookPayloadSchema and the webhook payload types3 exports
@evolve-framework/bluestone-commercetools/moduleBluestoneCommercetoolsModule, the HTTP module with POST /product-sync-done and GET /healthcheck, and its option types2 exports
@evolve-framework/bluestone-commercetools/processes/fullfullSync, which copies the complete webshop tree1 export
@evolve-framework/bluestone-commercetools/testingFixtures for Bluestone and commercetools data, and an MSW server with the mocked commercetools project142 exports