diff --git a/infrastructure/terraform/components/api/README.md b/infrastructure/terraform/components/api/README.md index ce859ec31..6cecaf322 100644 --- a/infrastructure/terraform/components/api/README.md +++ b/infrastructure/terraform/components/api/README.md @@ -78,6 +78,7 @@ No requirements. | [sqs\_letter\_updates](#module\_sqs\_letter\_updates) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-sqs.zip | n/a | | [sqs\_supplier\_allocator](#module\_sqs\_supplier\_allocator) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-sqs.zip | n/a | | [supplier\_allocator](#module\_supplier\_allocator) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a | +| [supplier\_mock](#module\_supplier\_mock) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a | | [supplier\_ssl](#module\_supplier\_ssl) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.26/terraform-ssl.zip | n/a | | [update\_letter\_queue](#module\_update\_letter\_queue) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a | | [upsert\_letter](#module\_upsert\_letter) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a | diff --git a/infrastructure/terraform/components/api/module_lambda_supplier_mock.tf b/infrastructure/terraform/components/api/module_lambda_supplier_mock.tf new file mode 100644 index 000000000..aa83fa015 --- /dev/null +++ b/infrastructure/terraform/components/api/module_lambda_supplier_mock.tf @@ -0,0 +1,71 @@ +module "supplier_mock" { + source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip" + + function_name = "supplier_mock" + description = "Mock the behaviour of a supplier" + + aws_account_id = var.aws_account_id + component = var.component + environment = var.environment + project = var.project + region = var.region + group = var.group + + log_retention_in_days = var.log_retention_in_days + kms_key_arn = module.kms.key_arn + + iam_policy_document = { + body = data.aws_iam_policy_document.supplier_mock_lambda.json + } + + function_s3_bucket = local.acct.s3_buckets["lambda_function_artefacts"]["id"] + function_code_base_path = local.aws_lambda_functions_dir_path + function_code_dir = "supplier-mock/dist" + function_include_common = true + handler_function_name = "supplierMockHandler" + runtime = "nodejs22.x" + memory = 512 + timeout = 29 + log_level = var.log_level + + force_lambda_code_deploy = var.force_lambda_code_deploy + enable_lambda_insights = false + + log_destination_arn = local.destination_arn + log_subscription_role_arn = local.acct.log_subscription_role_arn + + lambda_env_vars = merge(local.common_lambda_env_vars, { + ENVIRONMENT = var.environment + GET_LETTERS_FUNCTION_NAME = module.get_letters.function_name + }) +} + +data "aws_iam_policy_document" "supplier_mock_lambda" { + statement { + sid = "KMSPermissions" + effect = "Allow" + + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey", + ] + + resources = [ + module.kms.key_arn, ## Requires shared kms module + ] + } + + statement { + sid = "AllowInvokeLambda" + effect = "Allow" + + actions = [ + "lambda:InvokeFunction", + ] + + resources = [ + module.get_letters.function_arn, + module.patch_letter.function_arn + ] + } +} diff --git a/lambdas/supplier-mock/.gitignore b/lambdas/supplier-mock/.gitignore new file mode 100644 index 000000000..fc5a7859a --- /dev/null +++ b/lambdas/supplier-mock/.gitignore @@ -0,0 +1,5 @@ +coverage +node_modules +dist +.reports +.aws-sam diff --git a/lambdas/supplier-mock/buildAndRun.sh b/lambdas/supplier-mock/buildAndRun.sh new file mode 100755 index 000000000..36ffab780 --- /dev/null +++ b/lambdas/supplier-mock/buildAndRun.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +npm run lambda-build +sam build +sam local invoke SupplierMockFunction --event event.json diff --git a/lambdas/supplier-mock/event.json b/lambdas/supplier-mock/event.json new file mode 100644 index 000000000..1260ec487 --- /dev/null +++ b/lambdas/supplier-mock/event.json @@ -0,0 +1,3 @@ +{ + "name": "Vlasios" +} diff --git a/lambdas/supplier-mock/jest.config.ts b/lambdas/supplier-mock/jest.config.ts new file mode 100644 index 000000000..174e7f7f9 --- /dev/null +++ b/lambdas/supplier-mock/jest.config.ts @@ -0,0 +1,69 @@ +export const baseJestConfig = { + preset: "ts-jest", + extensionsToTreatAsEsm: [".ts"], + transform: { + "^.+\\.ts$": [ + "ts-jest", + { + useESM: true, + }, + ], + }, + transformIgnorePatterns: [ + "node_modules/(?!(@nhsdigital/nhs-notify-event-schemas-supplier-config)/)", + ], + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // The directory where Jest should output its coverage files + coverageDirectory: "./.reports/unit/coverage", + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "babel", + + coverageThreshold: { + global: { + branches: 100, + functions: 100, + lines: 100, + statements: -10, + }, + }, + + coveragePathIgnorePatterns: ["/__tests__/"], + testPathIgnorePatterns: [".build"], + testMatch: ["**/?(*.)+(spec|test).[jt]s?(x)"], + + // Use this configuration option to add custom reporters to Jest + reporters: [ + "default", + [ + "jest-html-reporter", + { + pageTitle: "Test Report", + outputPath: "./.reports/unit/test-report.html", + includeFailureMsg: true, + }, + ], + ], + + // The test environment that will be used for testing + testEnvironment: "jsdom", +}; + +const utilsJestConfig = { + ...baseJestConfig, + + testEnvironment: "node", + + coveragePathIgnorePatterns: [ + ...(baseJestConfig.coveragePathIgnorePatterns ?? []), + "zod-validators.ts", + ], +}; + +export default utilsJestConfig; diff --git a/lambdas/supplier-mock/package.json b/lambdas/supplier-mock/package.json new file mode 100644 index 000000000..23fdd1b89 --- /dev/null +++ b/lambdas/supplier-mock/package.json @@ -0,0 +1,21 @@ +{ + "dependencies": { + "@aws-sdk/client-api-gateway": "^3.1030.0", + "@aws-sdk/client-lambda": "^3.1030.0", + "@internal/helpers": "^0.1.0", + "aws-embedded-metrics": "^4.2.1", + "aws-lambda": "^1.0.7", + "pino": "^10.3.1", + "zod": "^4.3.6" + }, + "name": "nhs-notify-supplier-api-supplier-mock", + "private": true, + "scripts": { + "lambda-build": "rm -rf dist && npx esbuild --bundle --minify --sourcemap --target=es2020 --platform=node --loader:.node=file --entry-names=[name] --outdir=dist src/index.ts", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "test:unit": "jest", + "typecheck": "tsc --noEmit" + }, + "version": "0.0.1" +} diff --git a/lambdas/supplier-mock/src/__tests__/supplier-mock.test.ts b/lambdas/supplier-mock/src/__tests__/supplier-mock.test.ts new file mode 100644 index 000000000..3d8bb8057 --- /dev/null +++ b/lambdas/supplier-mock/src/__tests__/supplier-mock.test.ts @@ -0,0 +1,5 @@ +describe("Supplier Mock Lambda", () => { + test("should return a successful response", async () => { + expect(true).toBe(true); + }); +}); diff --git a/lambdas/supplier-mock/src/deps.ts b/lambdas/supplier-mock/src/deps.ts new file mode 100644 index 000000000..a17810141 --- /dev/null +++ b/lambdas/supplier-mock/src/deps.ts @@ -0,0 +1,21 @@ +import { Logger } from "pino"; +import { createLogger } from "@internal/helpers/src"; +import { LambdaClient } from "@aws-sdk/client-lambda"; +import { EnvVars, envVars } from "./env"; + +export type Deps = { + logger: Logger; + env: EnvVars; + lambdaClient: LambdaClient; +}; + +export function createDependenciesContainer(): Deps { + const log = createLogger({ logLevel: envVars.PINO_LOG_LEVEL }); + const lambdaClient = new LambdaClient(); + + return { + logger: log, + env: envVars, + lambdaClient, + }; +} diff --git a/lambdas/supplier-mock/src/env.ts b/lambdas/supplier-mock/src/env.ts new file mode 100644 index 000000000..a18409ccf --- /dev/null +++ b/lambdas/supplier-mock/src/env.ts @@ -0,0 +1,12 @@ +import { z } from "zod"; + +const EnvVarsSchema = z.object({ + PINO_LOG_LEVEL: z.coerce.string().optional(), + ENVIRONMENT: z.string().optional(), + AWS_REGION: z.string().optional(), + GET_LETTERS_FUNCTION_NAME: z.string().optional(), +}); + +export type EnvVars = z.infer; + +export const envVars: EnvVars = EnvVarsSchema.parse(process.env); diff --git a/lambdas/supplier-mock/src/index.ts b/lambdas/supplier-mock/src/index.ts new file mode 100644 index 000000000..869ccfd49 --- /dev/null +++ b/lambdas/supplier-mock/src/index.ts @@ -0,0 +1,7 @@ +import { createDependenciesContainer } from "./deps"; +import createHandler from "./supplier-mock"; + +const containerPromise = createDependenciesContainer(); + +// eslint-disable-next-line import-x/prefer-default-export +export const supplierMockHandler = createHandler(containerPromise); diff --git a/lambdas/supplier-mock/src/supplier-mock.ts b/lambdas/supplier-mock/src/supplier-mock.ts new file mode 100644 index 000000000..69758fd63 --- /dev/null +++ b/lambdas/supplier-mock/src/supplier-mock.ts @@ -0,0 +1,84 @@ +/* eslint-disable sonarjs/no-commented-code */ +import { InvokeCommand } from "@aws-sdk/client-lambda"; +import { Deps } from "./deps"; +import { RequestHeaders } from "../../../tests/constants/request-headers"; + +export default function createHandler(deps: Deps) { + return async () => { + deps.logger.info("Hello from the supplier mock lambda!"); + // const envName = deps.env.ENVIRONMENT; + const envName = "pr535"; + deps.logger.info("VLASIS - second log"); + deps.logger.info(`Environment: ${envName}`); + deps.logger.info({ + msg: `Environment: ${envName}`, + }); + // const input: ListFunctionsRequest = { + // MaxItems: 1000, + // }; + // const command = new ListFunctionsCommand(input); + // deps.logger.info("VLASIS - Invoking ListFunctionsCommand"); + // const response = await deps.lambdaClient.send(command); + // const functions: FunctionConfiguration[] = response.Functions ?? []; + // console.log( + // "list of functions in my environment:", + // functions + // .map((fn) => fn.FunctionName) + // .filter((fnName) => fnName?.includes(envName)) + // .join("\n"), + // ); + + // const getLettersLambdaResponse = await deps.lambdaClient.send( + // new InvokeCommand({ + // FunctionName: `nhs-${envName}-supapi-getletters`, + // InvocationType: "RequestResponse", + // Payload: Buffer.from(JSON.stringify({ test: "VLASIS data" })), + // }), + // ); + + deps.logger.info("Invoking get_letters lambda directly"); + + if (!deps.env.GET_LETTERS_FUNCTION_NAME) { + throw new Error("GET_LETTERS_FUNCTION_NAME is not configured"); + } + + const headers: RequestHeaders = { + "NHSD-Supplier-ID": "TestSupplier1", + "NHSD-Correlation-ID": "12345", + "X-Request-ID": "requestId1", + }; + + const invokeResponse = await deps.lambdaClient.send( + new InvokeCommand({ + FunctionName: deps.env.GET_LETTERS_FUNCTION_NAME, + InvocationType: "RequestResponse", + Payload: Buffer.from( + JSON.stringify({ + headers: { + "nhsd-supplier-id": headers["NHSD-Supplier-ID"], + "nhsd-correlation-id": headers["NHSD-Correlation-ID"], + "x-request-id": headers["X-Request-ID"], + }, + queryStringParameters: null, + requestContext: {}, + }), + ), + }), + ); + + const responsePayload = invokeResponse.Payload + ? JSON.parse(Buffer.from(invokeResponse.Payload).toString("utf8")) + : undefined; + + deps.logger.info( + { + statusCode: responsePayload?.statusCode, + functionError: invokeResponse.FunctionError, + }, + "Received response from get_letters lambda", + ); + deps.logger.info({ + body: responsePayload?.body, + }); + }; +} diff --git a/lambdas/supplier-mock/template.yaml b/lambdas/supplier-mock/template.yaml new file mode 100644 index 000000000..b356efa0d --- /dev/null +++ b/lambdas/supplier-mock/template.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 + +Resources: + SupplierMockFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: supplier_mock + Runtime: nodejs22.x + Handler: index.handler + CodeUri: dist + MemorySize: 512 + Timeout: 29 diff --git a/lambdas/supplier-mock/tsconfig.json b/lambdas/supplier-mock/tsconfig.json new file mode 100644 index 000000000..1a5fe4479 --- /dev/null +++ b/lambdas/supplier-mock/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "ignoreDeprecations": "5.0" + }, + "extends": "../../tsconfig.base.json", + "include": ["src/**/*", "jest.config.ts"] +} diff --git a/package-lock.json b/package-lock.json index c8fcc257a..3c056b1ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -316,6 +316,472 @@ "pino": "bin.js" } }, + "lambdas/supplier-mock": { + "name": "nhs-notify-supplier-api-supplier-mock", + "version": "0.0.1", + "dependencies": { + "@aws-sdk/client-api-gateway": "^3.1030.0", + "@aws-sdk/client-lambda": "^3.1030.0", + "@internal/helpers": "^0.1.0", + "aws-embedded-metrics": "^4.2.1", + "aws-lambda": "^1.0.7", + "pino": "^10.3.1", + "zod": "^4.3.6" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/client-api-gateway": { + "version": "3.1049.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-api-gateway/-/client-api-gateway-3.1049.0.tgz", + "integrity": "sha512-JcQzTxd6QVGBxdo9pRq1GksajlpABf702VKqF1KfcbErOIFNVsvRBH5ZiQ9SgWY9Ut0b1hrSmJu9hfm1W3f/ow==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/credential-provider-node": "^3.972.43", + "@aws-sdk/middleware-sdk-api-gateway": "^3.972.12", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/client-lambda": { + "version": "3.1049.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1049.0.tgz", + "integrity": "sha512-aMN6q+BLouSD6LDbSxXoqH3X55yacDFOH9+7RbUABFbo5NFMZCLtswbNE8UI6unk9fIUMA6V9YEm64SHmfIhaA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/credential-provider-node": "^3.972.43", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/core": { + "version": "3.974.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.12.tgz", + "integrity": "sha512-qrqgioqYFjwR6LatVNS1L2Vk++EwRIxqSQXPKNv5Ofux2D8UNgqMQ1znnMyEImXquVPTtbf71fc128pvmU6y9A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@aws-sdk/xml-builder": "^3.972.24", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.2", + "@smithy/signature-v4": "^5.4.2", + "@smithy/types": "^4.14.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.38", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.38.tgz", + "integrity": "sha512-m3WjZEgPtioMhPmwqUt+DhlTJ2i9ufR6DhfkyXojb9puEvfR+ur2U5shavu5/Cc9WHHsDCvALi6UFHgcqjhQ5w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.40", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.40.tgz", + "integrity": "sha512-D78L/m2Dr6cJnnSvWoAudPhQmCwmJ7j6APXsPYmFpPaKfQTfCSu0rdm8j14Np+VmXF9z8Aj8HE3xFpsrwtfgeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.42.tgz", + "integrity": "sha512-Mu5ESvFXeinafVM8jTIvRqcvK2Ehj4kz3auT39yUcHwu1Vfxo6xRlmUafdKLW4tusjAJukQwK09sCSMgOm7OKg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/credential-provider-env": "^3.972.38", + "@aws-sdk/credential-provider-http": "^3.972.40", + "@aws-sdk/credential-provider-login": "^3.972.42", + "@aws-sdk/credential-provider-process": "^3.972.38", + "@aws-sdk/credential-provider-sso": "^3.972.42", + "@aws-sdk/credential-provider-web-identity": "^3.972.42", + "@aws-sdk/nested-clients": "^3.997.10", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/credential-provider-imds": "^4.3.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.42.tgz", + "integrity": "sha512-O6WkZga3kf0yqyJYd1dbeJqVhEgJx/x1UaLgtbR+XuL/YP+K5y6QTxQKL7ka9z3jnQASESKGAPnRyt4D5hQrxA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/nested-clients": "^3.997.10", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.43", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.43.tgz", + "integrity": "sha512-D/DJmbrWRP5BXEO3FH+ar4el+2n6OlGofiud7dQun2jES+AQEJjczenp1jBb4MBN7CpGpS8nsWGQLtuzc9tQbA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.38", + "@aws-sdk/credential-provider-http": "^3.972.40", + "@aws-sdk/credential-provider-ini": "^3.972.42", + "@aws-sdk/credential-provider-process": "^3.972.38", + "@aws-sdk/credential-provider-sso": "^3.972.42", + "@aws-sdk/credential-provider-web-identity": "^3.972.42", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/credential-provider-imds": "^4.3.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.38", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.38.tgz", + "integrity": "sha512-EnbYVajGgbkb24s0K1eo4VNAPV5mHIET7LSvirTaFCwkfrfaOJxtSE+wY/tJdKDS21cEYkZs2ruCaAm+W4iblg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.42.tgz", + "integrity": "sha512-RVV/9NbFwI8ZHEH5dn39lGyFmSbSVj1+orZdr6QsOe1mW9DCglmlen0cFaNZmCcqkqc7erNRHNBduxbeZuHAnw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/nested-clients": "^3.997.10", + "@aws-sdk/token-providers": "3.1049.0", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.42.tgz", + "integrity": "sha512-/67fXX0ddllD4u2Nujc5PvT4byHgpMUfz6+RxIKi/0nFIckeorm7JvXgzBuDyVKw0s58EbofmETDWUf9vTEuHQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/nested-clients": "^3.997.10", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/middleware-sdk-api-gateway": { + "version": "3.972.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-api-gateway/-/middleware-sdk-api-gateway-3.972.12.tgz", + "integrity": "sha512-Fb9oEuB3875hI/187dj4MclC/nlBzc/iTEOYecUjFoipRGxqBE38XPqiE0g8oshs9rJXCZJousW0e/aElDFuDA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/nested-clients": { + "version": "3.997.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.10.tgz", + "integrity": "sha512-FtQ/Bt327peZJuyo4WZSOLVUTw9ujRxntepiC7L65FxA2P82Xlq0g14T22BuqBUeMjDoxa9nvwiMHjLIfP3eUg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/signature-v4-multi-region": "^3.996.27", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.27", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.27.tgz", + "integrity": "sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/signature-v4": "^5.4.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/token-providers": { + "version": "3.1049.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1049.0.tgz", + "integrity": "sha512-r7+d0lQMTHKypkmaF5jRTBYLYHCUHzt3gaVoN9SidLhQeWhCmHk3AKrboDTpPF5b7Pt7vKu3+oeMjznM2Eu1ow==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.12", + "@aws-sdk/nested-clients": "^3.997.10", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/types": { + "version": "3.973.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.8.tgz", + "integrity": "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@aws-sdk/xml-builder": { + "version": "3.972.24", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.24.tgz", + "integrity": "sha512-V8z5YcDPfsvzrBlj0xR1vhRtocblhYbqdreCJB/voGd4Sr5zjNAeWxexbnqVtskTJe0vFb5KMqbSL++ePl+zRw==", + "license": "Apache-2.0", + "dependencies": { + "@nodable/entities": "2.1.0", + "@smithy/types": "^4.14.1", + "fast-xml-parser": "5.7.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@smithy/core": { + "version": "3.24.3", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.3.tgz", + "integrity": "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@smithy/credential-provider-imds": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.3.tgz", + "integrity": "sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@smithy/fetch-http-handler": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.3.tgz", + "integrity": "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@smithy/node-http-handler": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.3.tgz", + "integrity": "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@smithy/signature-v4": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.3.tgz", + "integrity": "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "lambdas/supplier-mock/node_modules/@smithy/types": { + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.2.tgz", + "integrity": "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "lambdas/supplier-mock/node_modules/fast-xml-builder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "lambdas/supplier-mock/node_modules/fast-xml-parser": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz", + "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.7", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "lambdas/supplier-mock/node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "lambdas/supplier-mock/node_modules/strnum": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz", + "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "lambdas/update-letter-queue": { "name": "nhs-notify-supplier-api-update-letter-queue", "version": "0.0.1", @@ -5197,15 +5663,6 @@ "resolved": "internal/events", "link": true }, - "node_modules/@nhsdigital/nhs-notify-event-schemas-supplier-config": { - "version": "1.0.1", - "resolved": "https://npm.pkg.github.com/download/@nhsdigital/nhs-notify-event-schemas-supplier-config/1.0.1/ff1ce566201ae291825acd5e771537229d6aa9ca", - "integrity": "sha512-gIZgfzgvkCfZE+HCosrVJ3tBce2FJRGfwPmtYtZDBG+ox/KvbpJFWXzJ5Jkh/42YzcVn2GxT1fy1L1F6pxiYWA==", - "dependencies": { - "@asyncapi/bundler": "^0.6.4", - "zod": "^4.1.12" - } - }, "node_modules/@nhsdigital/notify-digital-letters-consumer-contracts": { "version": "1.0.1", "resolved": "https://npm.pkg.github.com/download/@nhsdigital/notify-digital-letters-consumer-contracts/1.0.1/a721d9c8b1e01a61de4ecc2b62d3c692e5213bb8", @@ -5216,6 +5673,18 @@ "resolved": "pact-contracts", "link": true }, + "node_modules/@nodable/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -17620,6 +18089,10 @@ "resolved": "lambdas/mi-updates-transformer", "link": true }, + "node_modules/nhs-notify-supplier-api-supplier-mock": { + "resolved": "lambdas/supplier-mock", + "link": true + }, "node_modules/nhs-notify-supplier-api-suppliers-data-utility": { "resolved": "scripts/utilities/supplier-data", "link": true @@ -22749,6 +23222,21 @@ "node": ">=18" } }, + "node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/xml2js": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", diff --git a/tests/component-tests/apiGateway-tests/get-letters.spec.ts b/tests/component-tests/apiGateway-tests/get-letters.spec.ts index d01a97d43..4f5fb25b0 100644 --- a/tests/component-tests/apiGateway-tests/get-letters.spec.ts +++ b/tests/component-tests/apiGateway-tests/get-letters.spec.ts @@ -16,6 +16,8 @@ test.beforeAll(async () => { test.describe("API Gateway Tests To Get List Of Pending Letters", () => { test("GET /letters should return 200 and list items", async ({ request }) => { const header = createValidRequestHeaders(); + console.log("VLASIOS - Base URL for API Gateway:", baseUrl); + console.log("VLASIOS - Request headers:", header); const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}`, { headers: header, params: {