Skip to content

Commit 81f22bd

Browse files
committed
feat(maintenance): drop support for Node.js 16.x
1 parent 651224a commit 81f22bd

Some content is hidden

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

41 files changed

+48
-119
lines changed

.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

.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

.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

.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:

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 |

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 %}

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

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: {

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',

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

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',

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": {

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'",

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);

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",

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 &&

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",

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);

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

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",

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",

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,

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

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
);

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

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

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

packages/parser/src/errors.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,11 @@
33
* The cause of the error is included in the message, if possible.
44
*/
55
class ParseError extends Error {
6-
/**
7-
* we use the `cause` property, which is present in ES2022 or newer, to store the cause of the error.
8-
* because we have to support Node 16.x, we need to add this property ourselves.
9-
* We can remove this once we drop support for Node 16.x.
10-
* see: https://github.com/aws-powertools/powertools-lambda-typescript/issues/2223
11-
*
12-
* @see https://nodejs.org/api/errors.html#errors_error_cause
13-
*/
14-
public readonly cause: Error | undefined;
15-
16-
public constructor(message: string, cause?: Error) {
17-
const errorMessage = cause
18-
? `${message}. This error was caused by: ${cause.message}.`
6+
public constructor(message: string, options?: { cause?: Error }) {
7+
const errorMessage = options?.cause
8+
? `${message}. This error was caused by: ${options?.cause.message}.`
199
: message;
2010
super(errorMessage);
21-
this.cause = cause;
2211
this.name = 'ParseError';
2312
}
2413
}

packages/parser/src/parser.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ const parse = <T extends ZodSchema, E extends Envelope>(
4444
}
4545
try {
4646
return schema.parse(data);
47-
} catch (e) {
48-
throw new ParseError('Failed to parse schema', e as Error);
47+
} catch (error) {
48+
throw new ParseError('Failed to parse schema', { cause: error as Error });
4949
}
5050
};
5151

@@ -66,7 +66,9 @@ const safeParseSchema = <T extends ZodSchema>(
6666
? result
6767
: {
6868
success: false,
69-
error: new ParseError('Failed to parse schema safely', result.error),
69+
error: new ParseError('Failed to parse schema safely', {
70+
cause: result.error,
71+
}),
7072
originalEvent: data,
7173
};
7274
};

packages/testing/src/constants.ts

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const defaultRuntime = 'nodejs20x';
99
* The AWS Lambda runtimes that are supported by the project.
1010
*/
1111
const TEST_RUNTIMES = {
12-
nodejs16x: Runtime.NODEJS_16_X,
1312
nodejs18x: Runtime.NODEJS_18_X,
1413
[defaultRuntime]: Runtime.NODEJS_20_X,
1514
} as const;

packages/testing/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 &&

packages/tracer/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",

packages/tracer/tests/e2e/allFeatures.decorator.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ describe(`Tracer E2E tests, all features with decorator instantiation`, () => {
332332
expect(invocationSubsegment.error).toBe(true);
333333
expect(handlerSubsegment.error).toBe(true);
334334
// Assert that no error was captured on the subsegment
335-
expect(handlerSubsegment.hasOwnProperty('cause')).toBe(false);
335+
expect(Object.hasOwn(handlerSubsegment, 'cause')).toBe(false);
336336
}
337337
}
338338
},

packages/tracer/tests/e2e/allFeatures.middy.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ describe(`Tracer E2E tests, all features with middy instantiation`, () => {
325325
expect(invocationSubsegment.error).toBe(true);
326326
expect(handlerSubsegment.error).toBe(true);
327327
// Assert that no error was captured on the subsegment
328-
expect(handlerSubsegment.hasOwnProperty('cause')).toBe(false);
328+
expect(Object.hasOwn(handlerSubsegment, 'cause')).toBe(false);
329329
}
330330
}
331331
},

0 commit comments

Comments
 (0)