diff --git a/packages/commons/package.json b/packages/commons/package.json index d3d7506ab8..d6004e6a97 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -53,6 +53,10 @@ "import": "./lib/esm/unmarshallDynamoDB.js", "require": "./lib/cjs/unmarshallDynamoDB.js" }, + "./utils/env": { + "import": "./lib/esm/envUtils.js", + "require": "./lib/cjs/envUtils.js" + }, "./types": { "import": "./lib/esm/types/index.js", "require": "./lib/cjs/types/index.js" @@ -76,6 +80,10 @@ "lib/cjs/unmarshallDynamoDB.d.ts", "lib/esm/unmarshallDynamoDB.d.ts" ], + "utils/env": [ + "lib/cjs/envUtils.d.ts", + "lib/esm/envUtils.d.ts" + ], "types": [ "lib/cjs/types/index.d.ts", "lib/esm/types/index.d.ts" diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index d9d45d8f88..a4bfaa2bc4 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -1,3 +1,9 @@ +import { + getServiceName, + getXRayTraceIdFromEnv, + isDevMode, + isRequestXRaySampled, +} from '../envUtils.js'; import type { ConfigServiceInterface } from '../types/ConfigServiceInterface.js'; /** @@ -46,7 +52,7 @@ class EnvironmentVariablesService implements ConfigServiceInterface { * Get the value of the `POWERTOOLS_SERVICE_NAME` environment variable. */ public getServiceName(): string { - return this.get(this.serviceNameVariable); + return getServiceName(); } /** @@ -58,9 +64,7 @@ class EnvironmentVariablesService implements ConfigServiceInterface { * The actual Trace ID is: `1-5759e988-bd862e3fe1be46a994272793`. */ public getXrayTraceId(): string | undefined { - const xRayTraceData = this.getXrayTraceData(); - - return xRayTraceData?.Root; + return getXRayTraceIdFromEnv(); } /** @@ -70,16 +74,14 @@ class EnvironmentVariablesService implements ConfigServiceInterface { * `Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1`, */ public getXrayTraceSampled(): boolean { - const xRayTraceData = this.getXrayTraceData(); - - return xRayTraceData?.Sampled === '1'; + return isRequestXRaySampled(); } /** * Determine if the current invocation is running in a development environment. */ public isDevMode(): boolean { - return this.isValueTrue(this.get(this.devModeVariable)); + return isDevMode(); } /** @@ -103,29 +105,6 @@ class EnvironmentVariablesService implements ConfigServiceInterface { return falsyValues.includes(value.toLowerCase()); } - - /** - * Get the AWS X-Ray Trace data from the environment variable. - * - * The method parses the environment variable `_X_AMZN_TRACE_ID` and returns an object with the key-value pairs. - */ - private getXrayTraceData(): Record | undefined { - const xRayTraceEnv = this.get(this.xRayTraceIdVariable); - - if (xRayTraceEnv === '') return undefined; - - if (!xRayTraceEnv.includes('=')) return { Root: xRayTraceEnv }; - - const xRayTraceData: Record = {}; - - for (const field of xRayTraceEnv.split(';')) { - const [key, value] = field.split('='); - - xRayTraceData[key] = value; - } - - return xRayTraceData; - } } export { EnvironmentVariablesService }; diff --git a/packages/commons/src/constants.ts b/packages/commons/src/constants.ts new file mode 100644 index 0000000000..6a7a3eb7bf --- /dev/null +++ b/packages/commons/src/constants.ts @@ -0,0 +1,9 @@ +const POWERTOOLS_DEV_ENV_VAR = 'POWERTOOLS_DEV' as const; +const POWERTOOLS_SERVICE_NAME_ENV_VAR = 'POWERTOOLS_SERVICE_NAME' as const; +const XRAY_TRACE_ID_ENV_VAR = '_X_AMZN_TRACE_ID' as const; + +export { + POWERTOOLS_DEV_ENV_VAR, + POWERTOOLS_SERVICE_NAME_ENV_VAR, + XRAY_TRACE_ID_ENV_VAR, +}; diff --git a/packages/commons/src/envUtils.ts b/packages/commons/src/envUtils.ts new file mode 100644 index 0000000000..3c561187ae --- /dev/null +++ b/packages/commons/src/envUtils.ts @@ -0,0 +1,369 @@ +import { + POWERTOOLS_DEV_ENV_VAR, + POWERTOOLS_SERVICE_NAME_ENV_VAR, + XRAY_TRACE_ID_ENV_VAR, +} from './constants.js'; +import type { + GetBooleanFromEnvOptions, + GetNumberFromEnvOptions, + GetStringFromEnvOptions, +} from './types/envUtils.js'; + +/** + * Get a string from the environment variables. + * + * @example + * ```ts + * import { getStringFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getStringFromEnv({ + * key: 'MY_ENV_VAR', + * errorMessage: 'MY_ENV_VAR is required for this function', + * }); + * ``` + * + * By default, the value is trimmed and always required. + * + * You can also provide a default value, which will be returned if the environment variable is not set instead of throwing an error. + * + * @example + * ```ts + * import { getStringFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getStringFromEnv({ + * key: 'MY_ENV_VAR', + * defaultValue: 'defaultValue', + * }); + * ``` + * + * @param options - The options for getting the string. + * @param options.key - The key of the environment variable. + * @param options.defaultValue - Optional default value to return if the environment variable is not set. + * @param options.errorMessage - Optional error message to throw if the environment variable is not set and no default value is provided. Defaults to `"Environment variable is required"`. + */ +const getStringFromEnv = ({ + key, + defaultValue, + errorMessage, +}: GetStringFromEnvOptions): string => { + const value = process.env[key]; + + if (value === undefined) { + if (defaultValue !== undefined) { + return defaultValue; + } + if (errorMessage) { + throw new Error(errorMessage); + } + throw new Error(`Environment variable ${key} is required`); + } + + return value.trim(); +}; + +/** + * Get a number from the environment variables. + * + * @example + * ```ts + * import { getNumberFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getNumberFromEnv({ + * key: 'MY_ENV_VAR', + * errorMessage: 'MY_ENV_VAR is required for this function', + * }); + * ``` + * + * By default, the value is trimmed before being converted to a number and always required. + * + * You can also provide a default value, which will be returned if the environment variable is not set instead of throwing an error. + * + * @example + * ```ts + * import { getNumberFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getNumberFromEnv({ + * key: 'MY_ENV_VAR', + * defaultValue: 42, + * }); + * ``` + * + * @param options - The options for getting the number. + * @param options.key - The key of the environment variable. + * @param options.defaultValue - The default value to return if the environment variable is not set. + * @param options.errorMessage - Optional error message to throw if the environment variable is not set and no default value is provided. Defaults to `"Environment variable is required"`. + */ +const getNumberFromEnv = ({ + key, + defaultValue, + errorMessage, +}: GetNumberFromEnvOptions): number => { + const value = getStringFromEnv({ + key, + defaultValue: String(defaultValue), + errorMessage, + }); + + const parsedValue = Number(value); + + if (Number.isNaN(parsedValue)) { + throw new Error(`Environment variable ${key} must be a number`); + } + + return parsedValue; +}; + +/** + * Get a boolean from the environment variables. + * + * @example + * ```ts + * import { getBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getBooleanFromEnv({ + * key: 'MY_ENV_VAR', + * errorMessage: 'MY_ENV_VAR is required for this function', + * }); + * ``` + * + * By default, the value is trimmed before being converted to a boolean and always required. + * + * You can also provide a default value, which will be returned if the environment variable is not set instead of throwing an error. + * + * @example + * ```ts + * import { getBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getBooleanFromEnv({ + * key: 'MY_ENV_VAR', + * defaultValue: true, + * }); + * ``` + * + * @param options - The options for getting the boolean. + * @param options.key - The key of the environment variable. + * @param options.defaultValue - The default value to return if the environment variable is not set. + * @param options.errorMessage - Optional error message to throw if the environment variable is not set and no default value is provided. Defaults to `"Environment variable is required"`. + */ +const getBooleanFromEnv = ({ + key, + defaultValue, + errorMessage, +}: GetBooleanFromEnvOptions): boolean => { + const value = getStringFromEnv({ + key, + defaultValue: String(defaultValue), + errorMessage, + }); + + const parsedValue = value.toLowerCase(); + + if (parsedValue !== 'true' && parsedValue !== 'false') { + throw new Error(`Environment variable ${key} must be a boolean`); + } + + return parsedValue === 'true'; +}; + +const truthyValues = new Set(['1', 'y', 'yes', 't', 'true', 'on']); + +/** + * Get a truthy boolean from the environment variables. + * + * Truthy values are: `1`, `y`, `yes`, `t`, `true`, `on`. + * + * @example + * ```ts + * import { getTruthyBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getTruthyBooleanFromEnv({ + * key: 'MY_ENV_VAR', + * errorMessage: 'MY_ENV_VAR is required for this function', + * }); + * ``` + * + * By default, the value is trimmed before being converted to a boolean and always required. + * + * You can also provide a default value, which will be returned if the environment variable is not set instead of throwing an error. + * + * @example + * ```ts + * import { getTruthyBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getTruthyBooleanFromEnv({ + * key: 'MY_ENV_VAR', + * defaultValue: true, + * }); + * ``` + * + * @param options - The options for getting the truthy boolean. + * @param options.key - The key of the environment variable. + * @param options.defaultValue - The default value to return if the environment variable is not set. + * @param options.errorMessage - Optional error message to throw if the environment variable is not set and no default value is provided. Defaults to `"Environment variable is required"`. + */ +const getTruthyBooleanFromEnv = ({ + key, + defaultValue, + errorMessage, +}: GetBooleanFromEnvOptions): boolean => { + const value = getStringFromEnv({ + key, + defaultValue: String(defaultValue), + errorMessage, + }); + + return truthyValues.has(value.toLowerCase()); +}; + +const falsyValues = new Set(['0', 'n', 'no', 'f', 'false', 'off']); + +/** + * Get a falsy boolean from the environment variables. + * + * Falsy values are: `0`, `n`, `no`, `f`, `false`, `off`. + * + * @example + * ```ts + * import { getFalsyBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getFalsyBooleanFromEnv({ + * key: 'MY_ENV_VAR', + * errorMessage: 'MY_ENV_VAR is required for this function', + * }); + * ``` + * + * By default, the value is trimmed before being converted to a boolean and always required. + * + * You can also provide a default value, which will be returned if the environment variable is not set instead of throwing an error. + * + * @example + * ```ts + * import { getFalsyBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env'; + * + * const myEnvVar = getFalsyBooleanFromEnv({ + * key: 'MY_ENV_VAR', + * defaultValue: false, + * }); + * ``` + * + * @param options - The options for getting the falsy boolean. + * @param options.key - The key of the environment variable. + * @param options.defaultValue - The default value to return if the environment variable is not set. + * @param options.errorMessage - Optional error message to throw if the environment variable is not set and no default value is provided. Defaults to `"Environment variable is required"`. + */ +const getFalsyBooleanFromEnv = ({ + key, + defaultValue, + errorMessage, +}: GetBooleanFromEnvOptions): boolean => { + const value = getStringFromEnv({ + key, + defaultValue: String(defaultValue), + errorMessage, + }); + return falsyValues.has(value.toLowerCase()); +}; + +/** + * Check if the current invocation is running in a development environment. + * + * This is determined by the `POWERTOOLS_DEV` environment variable. + * + * @example + * ```ts + * import { isDevMode } from '@aws-lambda-powertools/commons/utils/env'; + * + * const isDev = isDevMode(); + * ``` + */ +const isDevMode = (): boolean => { + return getTruthyBooleanFromEnv({ + key: POWERTOOLS_DEV_ENV_VAR, + defaultValue: false, + }); +}; + +/** + * Get the service name from the environment variables. + * + * This is determined by the `POWERTOOLS_SERVICE_NAME` environment variable. + * + * @example + * ```ts + * import { getServiceName } from '@aws-lambda-powertools/commons/utils/env'; + * + * const serviceName = getServiceName(); + * ``` + */ +const getServiceName = (): string => { + return getStringFromEnv({ + key: POWERTOOLS_SERVICE_NAME_ENV_VAR, + defaultValue: '', + }); +}; + +/** + * Get the AWS X-Ray Trace data from the environment variable. + * + * The method parses the environment variable `_X_AMZN_TRACE_ID` and returns an object with the key-value pairs. + */ +const getXrayTraceDataFromEnv = (): Record | undefined => { + const xRayTraceEnv = getStringFromEnv({ + key: XRAY_TRACE_ID_ENV_VAR, + defaultValue: '', + }); + if (xRayTraceEnv === '') { + return undefined; + } + if (!xRayTraceEnv.includes('=')) { + return { + Root: xRayTraceEnv, + }; + } + const xRayTraceData: Record = {}; + + for (const field of xRayTraceEnv.split(';')) { + const [key, value] = field.split('='); + + xRayTraceData[key] = value; + } + + return xRayTraceData; +}; + +/** + * Determine if the current invocation is part of a sampled X-Ray trace. + * + * The AWS X-Ray Trace data available in the environment variable has this format: + * `Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1`, + */ +const isRequestXRaySampled = (): boolean => { + const xRayTraceData = getXrayTraceDataFromEnv(); + return xRayTraceData?.Sampled === '1'; +}; + +/** + * Get the value of the `_X_AMZN_TRACE_ID` environment variable. + * + * The AWS X-Ray Trace data available in the environment variable has this format: + * `Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1`, + * + * The actual Trace ID is: `1-5759e988-bd862e3fe1be46a994272793`. + */ +const getXRayTraceIdFromEnv = (): string | undefined => { + const xRayTraceData = getXrayTraceDataFromEnv(); + return xRayTraceData?.Root; +}; + +export { + getStringFromEnv, + getNumberFromEnv, + getBooleanFromEnv, + getTruthyBooleanFromEnv, + getFalsyBooleanFromEnv, + isDevMode, + getServiceName, + getXrayTraceDataFromEnv, + isRequestXRaySampled, + getXRayTraceIdFromEnv, +}; diff --git a/packages/commons/src/types/envUtils.ts b/packages/commons/src/types/envUtils.ts new file mode 100644 index 0000000000..b7ab42c3af --- /dev/null +++ b/packages/commons/src/types/envUtils.ts @@ -0,0 +1,56 @@ +type GetStringFromEnvOptions = { + /** + * The key of the environment variable. + */ + key: string; + /** + * Optional default value to return if the environment variable is not set. + * @default "" + */ + defaultValue?: string; + /** + * Optional error message to throw if the environment variable is not set and no default value is provided. + * @default "Environment variable is required" + */ + errorMessage?: string; +}; + +type GetNumberFromEnvOptions = { + /** + * The key of the environment variable. + */ + key: string; + /** + * The default value to return if the environment variable is not set. + * @default undefined + */ + defaultValue?: number; + /** + * Optional error message to throw if the environment variable is not set and no default value is provided. + * @default "Environment variable is required" + */ + errorMessage?: string; +}; + +type GetBooleanFromEnvOptions = { + /** + * The key of the environment variable. + */ + key: string; + /** + * The default value to return if the environment variable is not set. + * @default undefined + */ + defaultValue?: boolean; + /** + * Optional error message to throw if the environment variable is not set and no default value is provided. + * @default "Environment variable is required" + */ + errorMessage?: string; +}; + +export type { + GetStringFromEnvOptions, + GetNumberFromEnvOptions, + GetBooleanFromEnvOptions, +}; diff --git a/packages/commons/src/types/index.ts b/packages/commons/src/types/index.ts index 080d13ed12..de3d07f01b 100644 --- a/packages/commons/src/types/index.ts +++ b/packages/commons/src/types/index.ts @@ -20,3 +20,8 @@ export type { HandlerMethodDecorator, } from './LambdaInterface.js'; export type { ConfigServiceInterface } from './ConfigServiceInterface.js'; +export type { + GetStringFromEnvOptions, + GetBooleanFromEnvOptions, + GetNumberFromEnvOptions, +} from './envUtils.js'; diff --git a/packages/commons/tests/unit/EnvironmentVariablesService.test.ts b/packages/commons/tests/unit/EnvironmentVariablesService.test.ts index fcf9974527..6f0c50dca0 100644 --- a/packages/commons/tests/unit/EnvironmentVariablesService.test.ts +++ b/packages/commons/tests/unit/EnvironmentVariablesService.test.ts @@ -65,30 +65,6 @@ describe('Class: EnvironmentVariablesService', () => { // Assess expect(value).toEqual('abcd123456789'); }); - it('returns the value of the Root X-Ray segment ID properly formatted', () => { - // Prepare - process.env._X_AMZN_TRACE_ID = - 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getXrayTraceId(); - - // Assess - expect(value).toEqual('1-5759e988-bd862e3fe1be46a994272793'); - }); - - it('returns the value of the Root X-Ray segment ID properly formatted', () => { - // Prepare - process.env._X_AMZN_TRACE_ID = undefined; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getXrayTraceId(); - - // Assess - expect(value).toEqual(undefined); - }); }); describe('Method: getXrayTraceSampled', () => { @@ -104,31 +80,6 @@ describe('Class: EnvironmentVariablesService', () => { // Assess expect(value).toEqual(true); }); - - it('returns false if the Sampled flag is not set in the _X_AMZN_TRACE_ID environment variable', () => { - // Prepare - process.env._X_AMZN_TRACE_ID = - 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getXrayTraceSampled(); - - // Assess - expect(value).toEqual(false); - }); - - it('returns false when no _X_AMZN_TRACE_ID environment variable is present', () => { - // Prepare - process.env._X_AMZN_TRACE_ID = undefined; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getXrayTraceSampled(); - - // Assess - expect(value).toEqual(false); - }); }); describe('Method: isValueTrue', () => { diff --git a/packages/commons/tests/unit/envUtils.test.ts b/packages/commons/tests/unit/envUtils.test.ts new file mode 100644 index 0000000000..a58fd8e61d --- /dev/null +++ b/packages/commons/tests/unit/envUtils.test.ts @@ -0,0 +1,404 @@ +import { beforeEach, describe, expect, it } from 'vitest'; +import { + getBooleanFromEnv, + getFalsyBooleanFromEnv, + getNumberFromEnv, + getServiceName, + getStringFromEnv, + getTruthyBooleanFromEnv, + getXRayTraceIdFromEnv, + isDevMode, + isRequestXRaySampled, +} from '../../src/envUtils.js'; + +describe('Functions: envUtils', () => { + const env = process.env; + + beforeEach(() => { + process.env = { ...env }; + }); + + describe('Function: getStringFromEnv', () => { + it('returns the value of the environment variable', () => { + // Prepare + process.env.TEST_ENV = 'testValue'; + + // Act + const result = getStringFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe('testValue'); + }); + + it('returns the default value if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act + const result = getStringFromEnv({ + key: 'TEST_ENV', + defaultValue: 'defaultValue', + }); + + // Assess + expect(result).toBe('defaultValue'); + }); + + it('throws an error if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act & Assess + expect(() => getStringFromEnv({ key: 'TEST_ENV' })).toThrowError( + 'Environment variable TEST_ENV is required' + ); + }); + + it('returns the trimmed value of the environment variable', () => { + // Prepare + process.env.TEST_ENV = ' testValue '; + + // Act + const result = getStringFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe('testValue'); + }); + + it('uses the provided error message if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act & Assess + expect(() => + getStringFromEnv({ + key: 'TEST_ENV', + errorMessage: 'Custom error message', + }) + ).toThrowError('Custom error message'); + }); + }); + + describe('Function: getNumberFromEnv', () => { + it('returns the value of the environment variable as a number', () => { + // Prepare + process.env.TEST_ENV = '123'; + + // Act + const result = getNumberFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(123); + }); + + it('returns the default value if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act + const result = getNumberFromEnv({ + key: 'TEST_ENV', + defaultValue: 456, + }); + + // Assess + expect(result).toBe(456); + }); + + it('throws an error if the environment variable is not a number', () => { + // Prepare + process.env.TEST_ENV = 'notANumber'; + + // Act & Assess + expect(() => getNumberFromEnv({ key: 'TEST_ENV' })).toThrowError( + 'Environment variable TEST_ENV must be a number' + ); + }); + }); + + describe('Function: getBooleanFromEnv', () => { + it('returns true if the environment variable is set to a truthy value', () => { + // Prepare + process.env.TEST_ENV = 'true'; + + // Act + const result = getBooleanFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(true); + }); + + it('returns false if the environment variable is set to a falsy value', () => { + // Prepare + process.env.TEST_ENV = 'false'; + + // Act + const result = getBooleanFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(false); + }); + + it('returns the default value if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act + const result = getBooleanFromEnv({ + key: 'TEST_ENV', + defaultValue: true, + }); + + // Assess + expect(result).toBe(true); + }); + + it('throws an error if the environment variable value is not a boolean', () => { + // Prepare + process.env.TEST_ENV = 'notABoolean'; + + // Act & Assess + expect(() => getBooleanFromEnv({ key: 'TEST_ENV' })).toThrowError( + 'Environment variable TEST_ENV must be a boolean' + ); + }); + }); + + describe('Function: getTruthyBooleanFromEnv', () => { + it.each([ + ['1', true], + ['y', true], + ['yes', true], + ['t', true], + ['TRUE', true], + ['on', true], + ])( + 'returns true if the environment variable is set to a truthy value: %s', + (value, expected) => { + // Prepare + process.env.TEST_ENV = value; + + // Act + const result = getTruthyBooleanFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(expected); + } + ); + + it.each([ + ['', false], + ['false', false], + ['fasle', false], + ['somethingsilly', false], + ['0', false], + ])( + 'returns false if the environment variable is set to a falsy value: %s', + (value, expected) => { + // Prepare + process.env.TEST_ENV = value; + + // Act + const result = getTruthyBooleanFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(expected); + } + ); + + it('returns the default value if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act + const result = getTruthyBooleanFromEnv({ + key: 'TEST_ENV', + defaultValue: true, + }); + + // Assess + expect(result).toBe(true); + }); + }); + + describe('Function: getFalsyBooleanFromEnv', () => { + it.each([ + ['0', true], + ['n', true], + ['no', true], + ['f', true], + ['FALSE', true], + ['off', true], + ])( + 'returns true if the environment variable is set to a truthy value: %s', + (value, expected) => { + // Prepare + process.env.TEST_ENV = value; + + // Act + const result = getFalsyBooleanFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(expected); + } + ); + + it.each([ + ['1', false], + ['y', false], + ['yes', false], + ['t', false], + ['TRUE', false], + ['on', false], + ['', false], + ['somethingsilly', false], + ])( + 'returns false if the environment variable is set to a falsy value: %s', + (value, expected) => { + // Prepare + process.env.TEST_ENV = value; + + // Act + const result = getFalsyBooleanFromEnv({ key: 'TEST_ENV' }); + + // Assess + expect(result).toBe(expected); + } + ); + + it('returns the default value if the environment variable is not set', () => { + // Prepare + process.env.TEST_ENV = undefined; + + // Act + const result = getFalsyBooleanFromEnv({ + key: 'TEST_ENV', + defaultValue: false, + }); + + // Assess + expect(result).toBe(true); + }); + }); + + describe('Function: isDevMode', () => { + it('returns true if the environment variable is set to a truthy value', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'true'; + + // Act + const result = isDevMode(); + + // Assess + expect(result).toBe(true); + }); + + it('returns false if the environment variable is set to a falsy value', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'false'; + + // Act + const result = isDevMode(); + + // Assess + expect(result).toBe(false); + }); + + it('returns false if the environment variable is not set', () => { + // Prepare + process.env.POWERTOOLS_DEV = undefined; + + // Act + const result = isDevMode(); + + // Assess + expect(result).toBe(false); + }); + }); + + describe('Function: getServiceName', () => { + it('returns the service name from the environment variable', () => { + // Prepare + process.env.POWERTOOLS_SERVICE_NAME = 'testService'; + + // Act + const result = getServiceName(); + + // Assess + expect(result).toBe('testService'); + }); + + it('returns an empty string if the environment variable is not set', () => { + // Prepare + process.env.POWERTOOLS_SERVICE_NAME = undefined; + + // Act + const result = getServiceName(); + + // Assess + expect(result).toBe(''); + }); + }); + + describe('Function: getXrayTraceIdFromEnv', () => { + it('returns the value of the environment variable _X_AMZN_TRACE_ID', () => { + // Prepare + process.env._X_AMZN_TRACE_ID = 'abcd123456789'; + + // Act + const value = getXRayTraceIdFromEnv(); + + // Assess + expect(value).toEqual('abcd123456789'); + }); + + it('returns the value of the Root X-Ray segment ID properly formatted', () => { + // Prepare + process.env._X_AMZN_TRACE_ID = + 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1'; + + // Act + const value = getXRayTraceIdFromEnv(); + + // Assess + expect(value).toEqual('1-5759e988-bd862e3fe1be46a994272793'); + }); + }); + + describe('Function: isRequestXRaySampled', () => { + it('returns true if the Sampled flag is set in the _X_AMZN_TRACE_ID environment variable', () => { + // Prepare + process.env._X_AMZN_TRACE_ID = + 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1'; + + // Act + const value = isRequestXRaySampled(); + + // Assess + expect(value).toEqual(true); + }); + + it('returns false if the Sampled flag is not set in the _X_AMZN_TRACE_ID environment variable', () => { + // Prepare + process.env._X_AMZN_TRACE_ID = + 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047'; + + // Act + const value = isRequestXRaySampled(); + + // Assess + expect(value).toEqual(false); + }); + + it('returns false when no _X_AMZN_TRACE_ID environment variable is present', () => { + // Prepare + process.env._X_AMZN_TRACE_ID = undefined; + + // Act + const value = isRequestXRaySampled(); + + // Assess + expect(value).toEqual(false); + }); + }); +}); diff --git a/packages/commons/typedoc.json b/packages/commons/typedoc.json index d34f7f99ef..1ba85b7f7d 100644 --- a/packages/commons/typedoc.json +++ b/packages/commons/typedoc.json @@ -7,6 +7,7 @@ "./src/types/index.ts", "./src/middleware/cleanupMiddlewares.ts", "./src/typeUtils.ts", + "./src/envUtils.ts", "./src/fromBase64.ts", "./src/LRUCache.ts" ],