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