Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .coverage
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Clone the repository
```shell
git clone https://github.com/NHSDigital/nhs-notify-digital-letters.git
cd nhs-notify-digital-letters
code protject.code-workspace
code project.code-workspace
```

Reopen with container
Expand Down
174 changes: 106 additions & 68 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"lambdas/ttl-handle-expiry-lambda",
"lambdas/ttl-poll-lambda",
"utils/utils",
"utils/sender-management",
"src/cloudevents",
"tests/playwright"
]
Expand Down
4 changes: 2 additions & 2 deletions scripts/config/sonar-scanner.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ sonar.host.url=https://sonarcloud.io
sonar.qualitygate.wait=true
sonar.sourceEncoding=UTF-8
sonar.sources=.
sonar.tests=tests/, src/asyncapigenerator/tests, src/cloudeventjekylldocs/tests, src/eventcatalogasyncapiimporter/tests, src/cloudevents/tools/builder/__tests__, src/cloudevents/tools/cache/__tests__, src/cloudevents/tools/generator/__tests__, lambdas/mesh-poll/src/__tests__, lambdas/ttl-create-lambda/src/__tests__, lambdas/ttl-poll-lambda/src/__tests__, utils/utils/src/__tests__
sonar.test.inclusions=tests/**, src/**/tests/**, src/**/__tests__/**, lambdas/**/src/__tests__/**, utils/utils/src/__tests__/**
sonar.tests=tests/, src/asyncapigenerator/tests, src/cloudeventjekylldocs/tests, src/eventcatalogasyncapiimporter/tests, src/cloudevents/tools/builder/__tests__, src/cloudevents/tools/cache/__tests__, src/cloudevents/tools/generator/__tests__, lambdas/mesh-poll/src/__tests__, lambdas/ttl-create-lambda/src/__tests__, lambdas/ttl-poll-lambda/src/__tests__, utils/utils/src/__tests__, utils/sender-management/src/__tests__
sonar.test.inclusions=tests/**, src/**/tests/**, src/**/__tests__/**, lambdas/**/src/__tests__/**, utils/utils/src/__tests__/**, utils/sender-management/src/__tests__/**
sonar.terraform.provider.aws.version=5.54.1
sonar.cpd.exclusions=**.test.*
sonar.coverage.exclusions=tests/**, src/**/tests/**, src/**/__tests__/**, **/*.dev.*, lambdas/**/src/__tests__/**, **/jest.config.ts, **/jest.config.cjs, scripts/**/*.*, docs/**/*.*, utils/utils/src/__tests__/**, src/asyncapigenerator/example_usage.py, src/asyncapigenerator/test_generator.py, src/eventcatalogasyncapiimporter/examples.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ sample_service_markdown
sanitization
schemaDir
sed
senderId
service_sorted
setCachedSchema
Someobject
Expand All @@ -92,5 +93,6 @@ toolchain
Trufflehog
updateReadme
Uploader
[Uu][Aa][Tt]
uuid
[Vv]alidator
146 changes: 146 additions & 0 deletions utils/sender-management/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# sender-management

TypeScript Library / CLI utility for managing comms manager sender configuration. These are currently stored in SSM Parameter Store.

## Usage

### CLI Usage

From the repo root run:

```bash
npm --prefix utils/sender-management run-script cli -- <command> [options]
```

### Library Usage

Install the package as `@sender-management`

Instantiate an instance of the library as follows. The library should take an implementation of an `IParameterStore` to define how the library will interact with SSM (e.g. caching vs non-caching).

```ts
import { SenderManagement } from '@sender-management';

const sm = SenderManagement({ parameterStore: new ParameterStore() });
```

### Global Options

#### CLI Options

- `--environment` - The name of the environment to run the command on e.g. 'pr123', 'main', 'uat', 'prod'. Required.
- `--format` - print data in json or tabular format. Default is `table`.

#### Library Options

```ts
const sm = SenderManagement({
parameterStore: new ParameterStore(),
configOverrides: { environment: 'pr123' },
});
```

## Commands

### Sender Configuration Commands

- [Put Sender](#put-sender)
- [List Senders](#list-senders)
- [Get Sender](#get-sender)
- [Delete Sender](#delete-sender)

#### Put Sender

Insert a new sender or update an existing one. Omit the `--sender-id` option to insert a new sender. Include it to update an existing sender. Note: the INT and PROD senderIds should be the same ID.

##### Put Sender Options

- `--sender-id` - the ID of the sender to update. (defaults to uuid. Should typically be excluded unless overwriting an existing sender). It cannot contain spaces.
- `--sender-name` - the display name of the sender. Will throw an error if this name is already taken. Unique across all the senders. (required)
- `--mesh-mailbox-sender-id` - the mesh mailbox id for this sender. Unique across all the senders. (required)
- `--mesh-mailbox-reports-id` - the mesh mailbox id used for reporting for this sender. It can be the same as mesh-mailbox-sender-id. (required)
- `--fallback-wait-time-seconds` - the fallback wait time to print letters. (required) (number)
- `--routing-config-id` - the routing configuration id.

##### Put Sender Examples

```bash
npm --prefix utils/sender-management run-script cli -- put-sender \
--sender-name 'Derby & Burton Trust' \
--mesh-mailbox-sender-id 'DerbyMailboxId' \
--mesh-mailbox-reports-id 'DerbyMailboxReportsId' \
--fallback-wait-time-seconds 100 \
--routing-config-id 'abc123' \
--environment 'pr123'
```

```bash
npm --prefix utils/sender-management run-script cli -- put-sender \
--sender-id 'integration_test_sender' \
--sender-name 'integration test sender' \
--mesh-mailbox-sender-id '123456' \
--mesh-mailbox-reports-id '123456' \
--fallback-wait-time-seconds 100 \
--routing-config-id 'abc123' \
--environment 'pr123'
```

```ts
const sender = await sm.putSender({
senderName: 'vaccs',
meshMailboxSenderId: 'meshMailbox1234',
meshMailboxReportsId: 'meshMailboxReport1234',
fallbackWaitTimeSeconds: 300,
routingConfigId: '1234',
});
```

#### List Senders

Return a list of all existing senders

##### List Senders Examples

```bash
npm --prefix utils/sender-management run-script cli -- list-senders --environment pr123
```

```ts
const senders = await sm.listSenders();
```

#### Get Sender

Return an individual sender by senderId

##### Get Sender Examples

```bash
npm --prefix utils/sender-management run-script cli -- get-sender \
--sender-id 'integration_test_sender' \
--environment 'pr123'
```

```ts
const sender = await sm.getSender({
senderId: 'integration_test_sender',
});
```

#### Delete Sender

Delete an individual sender by senderId.

##### Delete Sender Examples

```bash
npm --prefix utils/sender-management run-script cli -- delete-sender \
--sender-id 'integration_test_sender' \
--environment pr123
```

```ts
const sender = await sm.deleteSender({
senderId: 'integration_test_sender',
});
```
14 changes: 14 additions & 0 deletions utils/sender-management/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { baseJestConfig } from '../../jest.config.base';

const config = baseJestConfig;

config.coverageThreshold = {
global: {
branches: 84,
functions: 91,
lines: 90,
statements: -10,
},
};

export default config;
30 changes: 30 additions & 0 deletions utils/sender-management/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"dependencies": {
"@aws-sdk/client-ssm": "^3.914.0",
"@types/yargs": "^17.0.33",
"tsx": "^4.20.6",
"utils": "^0.0.1",
"yargs": "^17.7.2",
"zod": "^4.1.12"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"aws-sdk-client-mock": "^4.1.0",
"aws-sdk-client-mock-jest": "^4.1.0",
"jest": "^29.7.0",
"jest-mock-extended": "^3.0.7",
"typescript": "^5.9.3"
},
"main": "src/index.ts",
"name": "sender-management",
"private": true,
"scripts": {
"cli": "tsx ./src/entrypoint/cli/index.ts",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test:unit": "jest",
"typecheck": "tsc --noEmit"
},
"sideEffects": false,
"version": "0.0.1"
}
31 changes: 31 additions & 0 deletions utils/sender-management/src/__tests__/app/delete-sender.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { mockDeep } from 'jest-mock-extended';
import { AppDependencies, createApp } from '../../app';
import { DeleteSenderCommandParameters } from '../../app/delete-sender';

function setup() {
const mocks = mockDeep<AppDependencies>({
infra: {
senderRepository: {
deleteSender: jest.fn(),
},
},
});

return mocks;
}

describe('deleteSender', () => {
it('deletes the sender from the sender repository by id', async () => {
const mocks = setup();

const app = createApp(mocks);

const input: DeleteSenderCommandParameters = { senderId: 'input_id' };

await app.deleteSender(input);

expect(mocks.infra.senderRepository.deleteSender).toHaveBeenCalledWith(
input.senderId,
);
});
});
43 changes: 43 additions & 0 deletions utils/sender-management/src/__tests__/app/get-sender.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { mockDeep } from 'jest-mock-extended';
import { Sender } from 'utils';
import { AppDependencies, createApp } from '../../app';
import { GetSenderCommandParameters } from '../../app/get-sender';

function setup() {
const sender: Sender = {
senderId: 'test_sender_id',
senderName: 'test_sender_name',
meshMailboxSenderId: 'test_sender_mesh_mailbox_sender_id',
meshMailboxReportsId: 'test_sender_mesh_mailbox_reports_id',
fallbackWaitTimeSeconds: 300,
routingConfigId: '1234',
};

const mocks = mockDeep<AppDependencies>({
infra: {
senderRepository: {
getSender: jest.fn().mockResolvedValueOnce(sender),
},
},
});

return { mocks, data: { sender } };
}

describe('getSender', () => {
it('retrieves the sender from the sender repository by id and returns it', async () => {
const { data, mocks } = setup();

const app = createApp(mocks);

const input: GetSenderCommandParameters = { senderId: 'input_id' };

const result = await app.getSender(input);

expect(mocks.infra.senderRepository.getSender).toHaveBeenCalledWith(
input.senderId,
);

expect(result).toBe(data.sender);
});
});
39 changes: 39 additions & 0 deletions utils/sender-management/src/__tests__/app/list-senders.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { mockDeep } from 'jest-mock-extended';
import { Sender } from 'utils';
import { AppDependencies, createApp } from '../../app';

function setup() {
const senders: Sender[] = [
{
senderId: 'test_sender_id',
senderName: 'test_sender_name',
meshMailboxSenderId: 'test_sender_mesh_mailbox_sender_id',
meshMailboxReportsId: 'test_sender_mesh_mailbox_reports_id',
fallbackWaitTimeSeconds: 300,
routingConfigId: '1234',
},
];

const mocks = mockDeep<AppDependencies>({
infra: {
senderRepository: {
listSenders: jest.fn().mockResolvedValueOnce(senders),
},
},
});

return { mocks, data: { senders } };
}

describe('listSenders', () => {
it('retrieves senders from the sender repository and returns them', async () => {
const { data, mocks } = setup();

const app = createApp(mocks);

const result = await app.listSenders();

expect(mocks.infra.senderRepository.listSenders).toHaveBeenCalled();
expect(result).toBe(data.senders);
});
});
Loading