Skip to content

Commit e4eee73

Browse files
authored
feat(maintenance): drop support for Node.js 16.x (#2717)
1 parent 4ec3dcd commit e4eee73

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+142
-242
lines changed

Diff for: .github/ISSUE_TEMPLATE/bug_report.yml

-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ body:
6969
options:
7070
- 20.x
7171
- 18.x
72-
- 16.x
7372
validations:
7473
required: true
7574
- type: dropdown

Diff for: .github/actions/cached-node-modules/action.yml

-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ outputs:
1414
runs:
1515
using: "composite"
1616
steps:
17-
- name: Install npm
18-
# We need to keep this npm version until we drop Node.js 16 support because Node.js 16 doesn't support npm 10
19-
run: npm i -g npm@next-9
20-
shell: bash
2117
- name: Cache node modules
2218
id: cache-node-modules
2319
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0

Diff for: .github/workflows/reusable-run-linting-check-and-unit-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
NODE_ENV: dev
1414
strategy:
1515
matrix:
16-
version: [16, 18, 20]
16+
version: [18, 20]
1717
fail-fast: false
1818
steps:
1919
- name: Checkout code

Diff for: .github/workflows/run-e2e-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
packages/parameters,
3333
packages/idempotency,
3434
]
35-
version: [16, 18, 20]
35+
version: [18, 20]
3636
arch: [x86_64, arm64]
3737
fail-fast: false
3838
steps:

Diff for: docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ You can use Powertools for AWS Lambda (TypeScript) by installing it with your fa
250250

251251
[Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html){target="_blank"} is a `.zip` file archive that can contain additional code, pre-packaged dependencies, data, or configuration files. We compile and optimize [all dependencies](#install) to achieve an optimal build.
252252

253-
You can use the Lambda Layer both with CommonJS and ESM (ECMAScript modules) for Node.js 18.x and newer runtimes. **If you are using the managed Node.js 16.x runtime and cannot upgrade, you should use the CommonJS version only**.
253+
You can use the Lambda Layer both with CommonJS and ESM (ECMAScript modules) for Node.js 18.x and newer runtimes.
254254

255255
??? note "Click to expand and copy any regional Lambda Layer ARN"
256256
| Region | Layer ARN |

Diff for: docs/overrides/main.html

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
{% endblock %}
99

1010
{% block announce %}
11-
Starting from July 1, 2024 we will end support for Node.js 16. Learn more <a
12-
href="https://github.com/aws-powertools/powertools-lambda-typescript/issues/2223" target="_blank">here</a>.
11+
On September 1st, 2024 v1 of Powertools for AWS Lambda (TypeScript) <a
12+
href="https://github.com/aws-powertools/powertools-lambda-typescript/issues/2224" target="_blank">will reach
13+
End-of-Life</a>. We recommend you to <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/upgrade/"
14+
target="_blank">upgrade to v2</a>.
1315
{% endblock %}

Diff for: docs/upgrade.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ V2 is focused on official support for ESM (ECMAScript modules). We've made other
3131

3232
Before you start, we suggest making a copy of your current working project or create a new git branch.
3333

34-
1. Upgrade Node.js to v16 or higher, Node.js v20 is recommended.
34+
1. Upgrade Node.js to v18 or higher, Node.js v20 is recommended.
3535
2. Ensure that you have the latest Powertools for AWS Lambda (TypeScript) version via [Lambda Layer](./index.md#lambda-layer) or npm.
3636
3. Review the following sections to confirm whether they apply to your codebase.
3737

Diff for: layers/src/canary-stack.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class CanaryStack extends Stack {
4141
'../tests/e2e/layerPublisher.class.test.functionCode.ts'
4242
),
4343
handler: 'handler',
44-
runtime: Runtime.NODEJS_16_X,
44+
runtime: Runtime.NODEJS_18_X,
4545
functionName: `canary-${suffix}`,
4646
timeout: Duration.seconds(30),
4747
bundling: {

Diff for: layers/src/layer-publisher-stack.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,7 @@ export class LayerPublisherStack extends Stack {
3636
this.lambdaLayerVersion = new LayerVersion(this, 'LambdaPowertoolsLayer', {
3737
layerVersionName: props?.layerName,
3838
description: `Powertools for AWS Lambda (TypeScript) version ${powertoolsPackageVersion}`,
39-
compatibleRuntimes: [
40-
Runtime.NODEJS_16_X,
41-
Runtime.NODEJS_18_X,
42-
Runtime.NODEJS_20_X,
43-
],
39+
compatibleRuntimes: [Runtime.NODEJS_18_X, Runtime.NODEJS_20_X],
4440
license: 'MIT-0',
4541
// This is needed because the following regions do not support the compatibleArchitectures property #1400
4642
// ...(![ 'eu-south-2', 'eu-central-2', 'ap-southeast-4' ].includes(Stack.of(this).region) ? { compatibleArchitectures: [Architecture.X86_64] } : {}),
@@ -105,7 +101,7 @@ export class LayerPublisherStack extends Stack {
105101
'node_modules/@aws-sdk/**/README.md ',
106102
];
107103
const buildCommands: string[] = [];
108-
// We need these modules because they are not included in the nodejs16x runtimes
104+
// We install these to get the latest version of the packages
109105
const modulesToInstall: string[] = [
110106
'@aws-sdk/client-dynamodb',
111107
'@aws-sdk/util-dynamodb',

Diff for: layers/tests/e2e/layerPublisher.test.ts

+1-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
TestInvocationLogs,
1212
invokeFunctionOnce,
1313
generateTestUniqueName,
14-
getRuntimeKey,
1514
} from '@aws-lambda-powertools/testing-utils';
1615
import { TestNodejsFunction } from '@aws-lambda-powertools/testing-utils/resources/lambda';
1716
import {
@@ -48,13 +47,7 @@ describe(`Layers E2E tests`, () => {
4847
},
4948
});
5049

51-
/**
52-
* Node.js 16.x does not support importing ESM modules from Lambda Layers reliably.
53-
*
54-
* The feature is available in Node.js 18.x and later.
55-
* @see https://aws.amazon.com/blogs/compute/node-js-18-x-runtime-now-available-in-aws-lambda/
56-
*/
57-
const cases = getRuntimeKey() === 'nodejs16x' ? ['CJS'] : ['CJS', 'ESM'];
50+
const cases = ['CJS', 'ESM'];
5851
const invocationLogsMap: Map<(typeof cases)[number], TestInvocationLogs> =
5952
new Map();
6053

Diff for: layers/tests/unit/layer-publisher.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe('Class: LayerPublisherStack', () => {
2525
// Assess
2626
template.resourceCountIs('AWS::Lambda::LayerVersion', 1);
2727
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
28-
CompatibleRuntimes: ['nodejs16.x', 'nodejs18.x', 'nodejs20.x'],
28+
CompatibleRuntimes: ['nodejs18.x', 'nodejs20.x'],
2929
LicenseInfo: 'MIT-0',
3030
/* CompatibleArchitectures: [
3131
'x86_64',

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"*.md": "markdownlint-cli2 --fix"
8181
},
8282
"engines": {
83-
"node": ">=16"
83+
"node": ">=18"
8484
},
8585
"overrides": {
8686
"lerna": {

Diff for: packages/batch/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"test": "npm run test:unit",
1414
"test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose",
1515
"jest": "jest --detectOpenHandles --verbose",
16-
"test:e2e:nodejs16x": "echo 'Not Implemented'",
1716
"test:e2e:nodejs18x": "echo 'Not Implemented'",
1817
"test:e2e:nodejs20x": "echo 'Not Implemented'",
1918
"test:e2e": "echo 'Not Implemented'",

Diff for: packages/commons/src/middleware/cleanupMiddlewares.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const cleanupMiddlewares = async (request: MiddyLikeRequest): Promise<void> => {
6969
IDEMPOTENCY_KEY,
7070
];
7171
for (const functionName of cleanupFunctionNames) {
72-
if (Object(request.internal).hasOwnProperty(functionName)) {
72+
if (Object.hasOwn(request.internal, functionName)) {
7373
const functionReference = request.internal[functionName];
7474
if (isFunction(functionReference)) {
7575
await functionReference(request);

Diff for: packages/idempotency/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"test": "npm run test:unit",
1414
"test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose",
1515
"jest": "jest --detectOpenHandles --verbose",
16-
"test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e",
1716
"test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e",
1817
"test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e",
1918
"test:e2e": "jest --group=e2e",

Diff for: packages/idempotency/tests/helpers/populateEnvironmentVariables.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Reserved variables
22
process.env._X_AMZN_TRACE_ID = '1-abcdef12-3456abcdef123456abcdef12';
33
process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-lambda-function';
4-
process.env.AWS_EXECUTION_ENV = 'nodejs16.x';
4+
process.env.AWS_EXECUTION_ENV = 'nodejs20.x';
55
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128';
66
if (
77
process.env.AWS_REGION === undefined &&

Diff for: packages/jmespath/src/errors.ts

-7
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,6 @@ class ParseError extends JMESPathError {
108108
* Error thrown when an incomplete expression is encountered during parsing.
109109
*/
110110
class IncompleteExpressionError extends ParseError {
111-
/**
112-
* Expression that was being parsed when the error occurred.
113-
*
114-
* Can be set by whatever catches the error.
115-
*/
116-
public expression?: string;
117-
118111
public constructor(options: {
119112
lexPosition: number;
120113
tokenValue: Token['value'];

Diff for: packages/logger/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"test": "npm run test:unit",
1414
"test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose",
1515
"jest": "jest --detectOpenHandles --verbose",
16-
"test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e",
1716
"test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e",
1817
"test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e",
1918
"test:e2e": "jest --group=e2e",

Diff for: packages/logger/src/Logger.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ class Logger extends Utility implements LoggerInterface {
491491
logger.addContext(context);
492492

493493
let shouldLogEvent = undefined;
494-
if (options && options.hasOwnProperty('logEvent')) {
494+
if (options && Object.hasOwn(options, 'logEvent')) {
495495
shouldLogEvent = options.logEvent;
496496
}
497497
logger.logEventIfEnabled(event, shouldLogEvent);

Diff for: packages/logger/src/formatter/LogFormatter.ts

+3-20
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,6 @@ import type {
77
import type { UnformattedAttributes } from '../types/Logger.js';
88
import { LogItem } from './LogItem.js';
99

10-
/**
11-
* Typeguard to monkey patch Error to add a cause property.
12-
*
13-
* This is needed because the `cause` property is present in ES2022 or newer.
14-
* Since we want to be able to format errors in Node 16.x, we need to
15-
* add this property ourselves. We can remove this once we drop support
16-
* for Node 16.x.
17-
*
18-
* @see https://nodejs.org/api/errors.html#errors_error_cause
19-
*/
20-
const isErrorWithCause = (
21-
error: Error
22-
): error is Error & { cause: unknown } => {
23-
return 'cause' in error;
24-
};
25-
2610
/**
2711
* This class defines and implements common methods for the formatting of log attributes.
2812
*
@@ -65,11 +49,10 @@ abstract class LogFormatter implements LogFormatterInterface {
6549
location: this.getCodeLocation(error.stack),
6650
message: error.message,
6751
stack: error.stack,
68-
cause: isErrorWithCause(error)
69-
? error.cause instanceof Error
52+
cause:
53+
error.cause instanceof Error
7054
? this.formatError(error.cause)
71-
: error.cause
72-
: undefined,
55+
: error.cause,
7356
};
7457
}
7558

Diff for: packages/metrics/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"scripts": {
1313
"test": "npm run test:unit",
1414
"test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose",
15-
"test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e",
1615
"test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e",
1716
"test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e",
1817
"test:e2e": "jest --group=e2e",

Diff for: packages/parameters/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"test": "npm run test:unit",
1414
"test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose",
1515
"jest": "jest --detectOpenHandles --verbose",
16-
"test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e",
1716
"test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e",
1817
"test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e",
1918
"test:e2e": "jest --group=e2e",

Diff for: packages/parameters/src/appconfig/getAppConfig.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ const getAppConfig = <
153153
| AppConfigGetOutput<ExplicitUserProvidedType, InferredFromOptionsType>
154154
| undefined
155155
> => {
156-
if (!DEFAULT_PROVIDERS.hasOwnProperty('appconfig')) {
156+
if (!Object.hasOwn(DEFAULT_PROVIDERS, 'appconfig')) {
157157
DEFAULT_PROVIDERS.appconfig = new AppConfigProvider({
158158
application: options?.application,
159159
environment: options.environment,

Diff for: packages/parameters/src/secrets/getSecret.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const getSecret = async <
118118
| SecretsGetOutput<ExplicitUserProvidedType, InferredFromOptionsType>
119119
| undefined
120120
> => {
121-
if (!DEFAULT_PROVIDERS.hasOwnProperty('secrets')) {
121+
if (!Object.hasOwn(DEFAULT_PROVIDERS, 'secrets')) {
122122
DEFAULT_PROVIDERS.secrets = new SecretsProvider();
123123
}
124124

Diff for: packages/parameters/src/ssm/SSMProvider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ class SSMProvider extends BaseProvider {
845845
reservedParameter: string,
846846
throwOnError: boolean
847847
): void {
848-
if (!throwOnError && parameters.hasOwnProperty(reservedParameter)) {
848+
if (!throwOnError && Object.hasOwn(parameters, reservedParameter)) {
849849
throw new GetParameterError(
850850
`You cannot fetch a parameter named ${reservedParameter} in graceful error mode.`
851851
);

Diff for: packages/parameters/src/ssm/getParameter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ const getParameter = async <
146146
): Promise<
147147
SSMGetOutput<ExplicitUserProvidedType, InferredFromOptionsType> | undefined
148148
> => {
149-
if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) {
149+
if (!Object.hasOwn(DEFAULT_PROVIDERS, 'ssm')) {
150150
DEFAULT_PROVIDERS.ssm = new SSMProvider();
151151
}
152152

Diff for: packages/parameters/src/ssm/getParameters.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ const getParameters = async <
153153
| SSMGetMultipleOutput<ExplicitUserProvidedType, InferredFromOptionsType>
154154
| undefined
155155
> => {
156-
if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) {
156+
if (!Object.hasOwn(DEFAULT_PROVIDERS, 'ssm')) {
157157
DEFAULT_PROVIDERS.ssm = new SSMProvider();
158158
}
159159

Diff for: packages/parameters/src/ssm/getParametersByName.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ const getParametersByName = async <ExplicitUserProvidedType = undefined>(
166166
parameters: Record<string, SSMGetParametersByNameOptions>,
167167
options?: SSMGetParametersByNameOptions
168168
): Promise<SSMGetParametersByNameOutput<ExplicitUserProvidedType>> => {
169-
if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) {
169+
if (!Object.hasOwn(DEFAULT_PROVIDERS, 'ssm')) {
170170
DEFAULT_PROVIDERS.ssm = new SSMProvider();
171171
}
172172

Diff for: packages/parser/src/envelopes/apigw.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ export class ApiGatewayEnvelope extends Envelope {
2323
if (!parsedEnvelope.success) {
2424
return {
2525
success: false,
26-
error: new ParseError(
27-
'Failed to parse ApiGatewayEnvelope',
28-
parsedEnvelope.error
29-
),
26+
error: new ParseError('Failed to parse ApiGatewayEnvelope', {
27+
cause: parsedEnvelope.error,
28+
}),
3029
originalEvent: data,
3130
};
3231
}
@@ -36,10 +35,9 @@ export class ApiGatewayEnvelope extends Envelope {
3635
if (!parsedBody.success) {
3736
return {
3837
success: false,
39-
error: new ParseError(
40-
'Failed to parse ApiGatewayEnvelope body',
41-
parsedBody.error
42-
),
38+
error: new ParseError('Failed to parse ApiGatewayEnvelope body', {
39+
cause: parsedBody.error,
40+
}),
4341
originalEvent: data,
4442
};
4543
}

Diff for: packages/parser/src/envelopes/apigwv2.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ export class ApiGatewayV2Envelope extends Envelope {
2323
if (!parsedEnvelope.success) {
2424
return {
2525
success: false,
26-
error: new ParseError(
27-
'Failed to parse API Gateway V2 envelope',
28-
parsedEnvelope.error
29-
),
26+
error: new ParseError('Failed to parse API Gateway V2 envelope', {
27+
cause: parsedEnvelope.error,
28+
}),
3029
originalEvent: data,
3130
};
3231
}
@@ -36,10 +35,9 @@ export class ApiGatewayV2Envelope extends Envelope {
3635
if (!parsedBody.success) {
3736
return {
3837
success: false,
39-
error: new ParseError(
40-
'Failed to parse API Gateway V2 envelope body',
41-
parsedBody.error
42-
),
38+
error: new ParseError('Failed to parse API Gateway V2 envelope body', {
39+
cause: parsedBody.error,
40+
}),
4341
originalEvent: data,
4442
};
4543
}

Diff for: packages/parser/src/envelopes/cloudwatch.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,9 @@ export class CloudWatchEnvelope extends Envelope {
3434
if (!parsedEnvelope.success) {
3535
return {
3636
success: false,
37-
error: new ParseError(
38-
'Failed to parse CloudWatch envelope',
39-
parsedEnvelope.error
40-
),
37+
error: new ParseError('Failed to parse CloudWatch envelope', {
38+
cause: parsedEnvelope.error,
39+
}),
4140
originalEvent: data,
4241
};
4342
}
@@ -48,10 +47,9 @@ export class CloudWatchEnvelope extends Envelope {
4847
if (!parsedMessage.success) {
4948
return {
5049
success: false,
51-
error: new ParseError(
52-
'Failed to parse CloudWatch log event',
53-
parsedMessage.error
54-
),
50+
error: new ParseError('Failed to parse CloudWatch log event', {
51+
cause: parsedMessage.error,
52+
}),
5553
originalEvent: data,
5654
};
5755
} else {

0 commit comments

Comments
 (0)