Skip to content
This repository was archived by the owner on Jun 10, 2025. It is now read-only.

Commit 6b3a13d

Browse files
authored
Release/v1.0.0 beta.3 (#139)
fix: npm audit vulnerability feat: enable retries on commercetools client feat: add correlation id header on extension and notifications
1 parent c03b942 commit 6b3a13d

File tree

26 files changed

+464
-58
lines changed

26 files changed

+464
-58
lines changed

docs/Deployment.md

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,28 @@ Commercetools Mollie integration requires 1 environment variable to start. This
2828

2929
Here is a table to show which environment variables are necessary, and which are optional:
3030

31-
| Env variable name | Required | Notes |
32-
| ------------------ | -------- | ----------------------------------------------------------------------------------------------------------- |
33-
| `CT_MOLLIE_CONFIG` | YES | Contains the commercetools & mollie project variables |
34-
| `mollie` | YES | Contains Mollie-specific project variables |
35-
| `apiKey` | YES | API key for interacting with mollie, [found on the mollie dashboard](https://www.mollie.com/dashboard/) |
36-
| `commercetools` | YES | Contains commercetools-specific project variables |
37-
| `projectKey` | YES | Commercetools project key |
38-
| `clientId` | YES | Commercetools client id, unique to the client |
39-
| `clientSecret` | YES | Commercetools client secret, unique to the client |
40-
| `authUrl` | YES | Commercetools authentication URL, something like https://auth.{LOCATION}.{CLOUD_PLATFORM}.commercetools.com |
41-
| `host` | YES | Commercetools host, something like https://api.{LOCATION}.{CLOUD_PLATFORM}.commercetools.com |
42-
| `scopes` | NO | Constrains endpoints the client has access to in commercetools |
43-
| `authentication` | NO | CommerceTools Authentication variables |
44-
| `isBasicAuth` | NO | Enable/Disable basic authentication. Default is false |
45-
| `username` | NO | Username as configured in Commercetools |
46-
| `password` | NO | Password as configured in Commercetools |
47-
| `service` | NO | Contains service-specific project variables |
48-
| `locale` | NO | Locale language tag, in `aa_AA` format, based on tags mollie supports \* |
49-
| `port` | NO | Defaults to 3000 (extension) and 3001 (notifications) |
50-
| `logLevel` | NO | Specifies how verbose logs should be. Options are listed below. |
51-
| `logTransports` | NO | Specifies where the logs are written to/stored. Options listed below |
31+
| Env variable name | Required | Notes |
32+
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------- |
33+
| `CT_MOLLIE_CONFIG` | YES | Contains the commercetools & mollie project variables |
34+
| `mollie` | YES | Contains Mollie-specific project variables |
35+
| `apiKey` | YES | API key for interacting with mollie, [found on the mollie dashboard](https://www.mollie.com/dashboard/) |
36+
| `commercetools` | YES | Contains commercetools-specific project variables |
37+
| `projectKey` | YES | Commercetools project key |
38+
| `clientId` | YES | Commercetools client id, unique to the client |
39+
| `clientSecret` | YES | Commercetools client secret, unique to the client |
40+
| `authUrl` | YES | Commercetools authentication URL, something like `https://auth.{LOCATION}.{CLOUD_PLATFORM}.commercetools.com` |
41+
| `host` | YES | Commercetools host, something like `https://api.{LOCATION}.{CLOUD_PLATFORM}.commercetools.com` |
42+
| `scopes` | NO | Constrains endpoints the client has access to in commercetools |
43+
| `authentication` | NO | CommerceTools Authentication variables |
44+
| `isBasicAuth` | NO | Enable/Disable basic authentication. Default is false |
45+
| `username` | NO | Username as configured in Commercetools |
46+
| `password` | NO | Password as configured in Commercetools |
47+
| `enableRetry` | NO | [Retry policy for Commercetools](https://commercetools.github.io/nodejs/sdk/api/sdkMiddlewareHttp.html#retrying-requests) on 500 or network error. Default is true |
48+
| `service` | NO | Contains service-specific project variables |
49+
| `locale` | NO | Locale language tag, in `aa_AA` format, based on tags mollie supports \* |
50+
| `port` | NO | Defaults to 3000 (extension) and 3001 (notifications) |
51+
| `logLevel` | NO | Specifies how verbose logs should be. Options are listed below. |
52+
| `logTransports` | NO | Specifies where the logs are written to/stored. Options listed below |
5253

5354
- Valid tags are available here on mollie's documentation under [locale](https://docs.mollie.com/reference/v2/orders-api/create-order).
5455

@@ -71,7 +72,8 @@ Below is an example of how these should be formatted:
7172
"isBasicAuth": true,
7273
"username": "username",
7374
"password": "password"
74-
}
75+
},
76+
"enableRetry": true,
7577
},
7678
"service": {
7779
"port": 3050,

extension/azureHandler.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { HandleRequestInput, HandleRequestSuccess } from './src/types';
44
loadSettings();
55

66
import handleRequest from './src/requestHandlers/handleRequest';
7+
import { createCorrelationId } from './src/utils';
78

89
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
910
/*
@@ -15,11 +16,13 @@ const httpTrigger: AzureFunction = async function (context: Context, req: HttpRe
1516
const result = await handleRequest(requestInput);
1617
if (result instanceof HandleRequestSuccess) {
1718
context.res = {
19+
headers: { ...context?.res?.headers, 'x-correlation-id': req.headers['x-correlation-id'] ?? createCorrelationId() },
1820
status: result.status,
1921
body: { actions: result.actions },
2022
};
2123
} else {
2224
context.res = {
25+
headers: { ...context?.res?.headers, 'x-correlation-id': req.headers['x-correlation-id'] ?? createCorrelationId() },
2326
status: result.status,
2427
body: { errors: result.errors },
2528
};

extension/config/config-model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface Config {
1414
username?: string;
1515
password?: string;
1616
};
17+
enableRetry?: boolean;
1718
};
1819
service: {
1920
port: number | string;

extension/config/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export function loadConfig(ctMollieConfig: string | undefined) {
3838
envConfig.service?.locale && envConfig.service.locale.match(localeRegex) && { locale: envConfig.service.locale },
3939
);
4040
Object.assign(config.commercetools, envConfig.commercetools?.authentication ? { authentication: envConfig.commercetools.authentication } : { authentication: { isBasicAuth: false } });
41+
Object.assign(config.commercetools, { enableRetry: envConfig.commercetools.enableRetry ?? true });
4142

4243
const { valid, message } = isConfigValid(config);
4344

extension/expressHandler.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { Request, Response } from 'express';
22
import handleRequest from './src/requestHandlers/handleRequest';
33
import { HandleRequestInput, HandleRequestSuccess } from './src/types';
4+
import { createCorrelationId } from './src/utils';
45

56
export default async function handler(req: Request, res: Response) {
67
const headers = new Map([['authorization', req?.headers?.authorization ?? '']]);
78
const requestInput = new HandleRequestInput(req.path, req.method, req.body, headers);
89

910
const result = await handleRequest(requestInput);
11+
res.setHeader('x-correlation-id', req?.headers?.['x-correlation-id'] ?? createCorrelationId());
1012
if (result instanceof HandleRequestSuccess) {
1113
if (result.actions && result.actions.length > 0) {
1214
return res.status(result.status).send({ actions: result.actions });

extension/gcpFunctionHandler.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { Request, Response } from 'express';
22
import handleRequest from './src/requestHandlers/handleRequest';
33
import { HandleRequestInput, HandleRequestSuccess } from './src/types';
4+
import { createCorrelationId } from './src/utils';
45

56
exports.handler = async (req: Request, res: Response) => {
67
const headers = new Map([['authorization', req?.headers?.authorization ?? '']]);
78
const requestInput = new HandleRequestInput(req.path, req.method, req.body, headers);
89
const result = await handleRequest(requestInput);
10+
res.setHeader('x-correlation-id', req?.headers?.['x-correlation-id'] ?? createCorrelationId());
911
if (result instanceof HandleRequestSuccess) {
1012
if (result.actions && result.actions.length > 0) {
1113
return res.status(result.status).send({ actions: result.actions });

extension/lambdaHandler.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { APIGatewayProxyEvent } from 'aws-lambda';
2+
import { createCorrelationId } from './src/utils';
23
import handleRequest from './src/requestHandlers/handleRequest';
34
import { HandleRequestInput, HandleRequestSuccess } from './src/types';
45

@@ -12,6 +13,7 @@ exports.handler = async (event: APIGatewayProxyEvent) => {
1213

1314
if (result instanceof HandleRequestSuccess) {
1415
return {
16+
headers: { ...event.headers, 'x-correlation-id': event.headers['x-correlation-id'] ?? createCorrelationId() },
1517
statusCode: result.status,
1618
body: JSON.stringify({
1719
responseType: 'UpdateRequest',
@@ -20,6 +22,7 @@ exports.handler = async (event: APIGatewayProxyEvent) => {
2022
};
2123
} else {
2224
return {
25+
headers: { ...event.headers, 'x-correlation-id': event.headers['x-correlation-id'] ?? createCorrelationId() },
2326
statusCode: result.status,
2427
body: JSON.stringify({
2528
responseType: 'FailedValidation',

extension/package-lock.json

Lines changed: 36 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extension/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mollie-commercetools-extension-module",
3-
"version": "1.0.0-beta.2",
3+
"version": "1.0.0-beta.3",
44
"author": "Mollie",
55
"description": "Integration between commercetools and mollie payment service provider",
66
"license": "MIT",
@@ -38,6 +38,7 @@
3838
"@types/supertest": "2.0.11",
3939
"@types/uuid": "8.3.4",
4040
"axios": "0.24.0",
41+
"dotenv": "16.0.0",
4142
"jest": "27.4.7",
4243
"nock": "13.2.2",
4344
"node-mocks-http": "1.11.0",
@@ -53,6 +54,7 @@
5354
"@commercetools/platform-sdk": "2.1.0",
5455
"@commercetools/sdk-client": "2.1.2",
5556
"@commercetools/sdk-middleware-auth": "6.2.0",
57+
"@commercetools/sdk-middleware-correlation-id": "2.1.4",
5658
"@commercetools/sdk-middleware-http": "6.1.0",
5759
"@commercetools/sdk-middleware-user-agent": "2.1.5",
5860
"@mollie/api-client": "3.6.0-beta.3",

extension/src/client/initialiseCommercetoolsClient.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import fetch from 'node-fetch-commonjs';
22
import { createAuthMiddlewareForClientCredentialsFlow } from '@commercetools/sdk-middleware-auth';
3+
import { createCorrelationIdMiddleware } from '@commercetools/sdk-middleware-correlation-id';
34
import { createHttpMiddleware } from '@commercetools/sdk-middleware-http';
45
import { createUserAgentMiddleware } from '@commercetools/sdk-middleware-user-agent';
56
import { createClient } from '@commercetools/sdk-client';
67

78
import config from '../../config/config';
9+
import { createCorrelationId } from '../utils';
810
import { version } from '../../package.json';
911

1012
export default function initialiseCommercetoolsClient(): any {
1113
const {
12-
commercetools: { projectKey, clientId, clientSecret, host, authUrl, scopes },
14+
commercetools: { projectKey, clientId, clientSecret, host, authUrl, scopes, enableRetry },
1315
} = config;
1416

1517
const userAgentMiddleware = createUserAgentMiddleware({
@@ -28,11 +30,21 @@ export default function initialiseCommercetoolsClient(): any {
2830
fetch,
2931
});
3032

31-
const ctHttpMiddleWare = createHttpMiddleware({
33+
// Retries are enabled with exponential backoff (recommended to prevent spamming of the server)
34+
// The maxDelay sets an upper limit on long to wait before retrying, useful when the delay time grows
35+
// exponentialy more than reasonable.
36+
// https://commercetools.github.io/nodejs/sdk/api/sdkMiddlewareHttp.html#named-arguments-options
37+
const httpOptions = {
3238
host,
39+
enableRetry,
3340
fetch,
41+
};
42+
enableRetry && Object.assign(httpOptions, { retryConfig: { maxDelay: 10000 } });
43+
const ctHttpMiddleWare = createHttpMiddleware(httpOptions);
44+
const correlationIdMiddleWare = createCorrelationIdMiddleware({
45+
generate: createCorrelationId,
3446
});
3547

36-
const commercetoolsClient = createClient({ middlewares: [userAgentMiddleware, ctAuthMiddleware, ctHttpMiddleWare] });
48+
const commercetoolsClient = createClient({ middlewares: [userAgentMiddleware, ctAuthMiddleware, correlationIdMiddleWare, ctHttpMiddleWare] });
3749
return commercetoolsClient;
3850
}

0 commit comments

Comments
 (0)