Skip to content

Commit a5609d7

Browse files
Feature/ccm 13135 client management (#126)
* CCM-13135: DL Sender management cli tool * CCM-13135: Address review comments
1 parent e9df91e commit a5609d7

Some content is hidden

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

45 files changed

+1925
-71
lines changed

.coverage

0 Bytes
Binary file not shown.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Clone the repository
3333
```shell
3434
git clone https://github.com/NHSDigital/nhs-notify-digital-letters.git
3535
cd nhs-notify-digital-letters
36-
code protject.code-workspace
36+
code project.code-workspace
3737
```
3838

3939
Reopen with container

package-lock.json

Lines changed: 106 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"lambdas/ttl-handle-expiry-lambda",
5858
"lambdas/ttl-poll-lambda",
5959
"utils/utils",
60+
"utils/sender-management",
6061
"src/cloudevents",
6162
"tests/playwright"
6263
]

scripts/config/sonar-scanner.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ sonar.host.url=https://sonarcloud.io
44
sonar.qualitygate.wait=true
55
sonar.sourceEncoding=UTF-8
66
sonar.sources=.
7-
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__
8-
sonar.test.inclusions=tests/**, src/**/tests/**, src/**/__tests__/**, lambdas/**/src/__tests__/**, utils/utils/src/__tests__/**
7+
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__
8+
sonar.test.inclusions=tests/**, src/**/tests/**, src/**/__tests__/**, lambdas/**/src/__tests__/**, utils/utils/src/__tests__/**, utils/sender-management/src/__tests__/**
99
sonar.terraform.provider.aws.version=5.54.1
1010
sonar.cpd.exclusions=**.test.*
1111
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

scripts/config/vale/styles/config/vocabularies/words/accept.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ sample_service_markdown
8080
sanitization
8181
schemaDir
8282
sed
83+
senderId
8384
service_sorted
8485
setCachedSchema
8586
Someobject
@@ -92,5 +93,6 @@ toolchain
9293
Trufflehog
9394
updateReadme
9495
Uploader
96+
[Uu][Aa][Tt]
9597
uuid
9698
[Vv]alidator

utils/sender-management/README.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# sender-management
2+
3+
TypeScript Library / CLI utility for managing comms manager sender configuration. These are currently stored in SSM Parameter Store.
4+
5+
## Usage
6+
7+
### CLI Usage
8+
9+
From the repo root run:
10+
11+
```bash
12+
npm --prefix utils/sender-management run-script cli -- <command> [options]
13+
```
14+
15+
### Library Usage
16+
17+
Install the package as `@sender-management`
18+
19+
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).
20+
21+
```ts
22+
import { SenderManagement } from '@sender-management';
23+
24+
const sm = SenderManagement({ parameterStore: new ParameterStore() });
25+
```
26+
27+
### Global Options
28+
29+
#### CLI Options
30+
31+
- `--environment` - The name of the environment to run the command on e.g. 'pr123', 'main', 'uat', 'prod'. Required.
32+
- `--format` - print data in json or tabular format. Default is `table`.
33+
34+
#### Library Options
35+
36+
```ts
37+
const sm = SenderManagement({
38+
parameterStore: new ParameterStore(),
39+
configOverrides: { environment: 'pr123' },
40+
});
41+
```
42+
43+
## Commands
44+
45+
### Sender Configuration Commands
46+
47+
- [Put Sender](#put-sender)
48+
- [List Senders](#list-senders)
49+
- [Get Sender](#get-sender)
50+
- [Delete Sender](#delete-sender)
51+
52+
#### Put Sender
53+
54+
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.
55+
56+
##### Put Sender Options
57+
58+
- `--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.
59+
- `--sender-name` - the display name of the sender. Will throw an error if this name is already taken. Unique across all the senders. (required)
60+
- `--mesh-mailbox-sender-id` - the mesh mailbox id for this sender. Unique across all the senders. (required)
61+
- `--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)
62+
- `--fallback-wait-time-seconds` - the fallback wait time to print letters. (required) (number)
63+
- `--routing-config-id` - the routing configuration id.
64+
65+
##### Put Sender Examples
66+
67+
```bash
68+
npm --prefix utils/sender-management run-script cli -- put-sender \
69+
--sender-name 'Derby & Burton Trust' \
70+
--mesh-mailbox-sender-id 'DerbyMailboxId' \
71+
--mesh-mailbox-reports-id 'DerbyMailboxReportsId' \
72+
--fallback-wait-time-seconds 100 \
73+
--routing-config-id 'abc123' \
74+
--environment 'pr123'
75+
```
76+
77+
```bash
78+
npm --prefix utils/sender-management run-script cli -- put-sender \
79+
--sender-id 'integration_test_sender' \
80+
--sender-name 'integration test sender' \
81+
--mesh-mailbox-sender-id '123456' \
82+
--mesh-mailbox-reports-id '123456' \
83+
--fallback-wait-time-seconds 100 \
84+
--routing-config-id 'abc123' \
85+
--environment 'pr123'
86+
```
87+
88+
```ts
89+
const sender = await sm.putSender({
90+
senderName: 'vaccs',
91+
meshMailboxSenderId: 'meshMailbox1234',
92+
meshMailboxReportsId: 'meshMailboxReport1234',
93+
fallbackWaitTimeSeconds: 300,
94+
routingConfigId: '1234',
95+
});
96+
```
97+
98+
#### List Senders
99+
100+
Return a list of all existing senders
101+
102+
##### List Senders Examples
103+
104+
```bash
105+
npm --prefix utils/sender-management run-script cli -- list-senders --environment pr123
106+
```
107+
108+
```ts
109+
const senders = await sm.listSenders();
110+
```
111+
112+
#### Get Sender
113+
114+
Return an individual sender by senderId
115+
116+
##### Get Sender Examples
117+
118+
```bash
119+
npm --prefix utils/sender-management run-script cli -- get-sender \
120+
--sender-id 'integration_test_sender' \
121+
--environment 'pr123'
122+
```
123+
124+
```ts
125+
const sender = await sm.getSender({
126+
senderId: 'integration_test_sender',
127+
});
128+
```
129+
130+
#### Delete Sender
131+
132+
Delete an individual sender by senderId.
133+
134+
##### Delete Sender Examples
135+
136+
```bash
137+
npm --prefix utils/sender-management run-script cli -- delete-sender \
138+
--sender-id 'integration_test_sender' \
139+
--environment pr123
140+
```
141+
142+
```ts
143+
const sender = await sm.deleteSender({
144+
senderId: 'integration_test_sender',
145+
});
146+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { baseJestConfig } from '../../jest.config.base';
2+
3+
const config = baseJestConfig;
4+
5+
config.coverageThreshold = {
6+
global: {
7+
branches: 84,
8+
functions: 91,
9+
lines: 90,
10+
statements: -10,
11+
},
12+
};
13+
14+
export default config;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"dependencies": {
3+
"@aws-sdk/client-ssm": "^3.914.0",
4+
"@types/yargs": "^17.0.33",
5+
"tsx": "^4.20.6",
6+
"utils": "^0.0.1",
7+
"yargs": "^17.7.2",
8+
"zod": "^4.1.12"
9+
},
10+
"devDependencies": {
11+
"@types/jest": "^29.5.14",
12+
"aws-sdk-client-mock": "^4.1.0",
13+
"aws-sdk-client-mock-jest": "^4.1.0",
14+
"jest": "^29.7.0",
15+
"jest-mock-extended": "^3.0.7",
16+
"typescript": "^5.9.3"
17+
},
18+
"main": "src/index.ts",
19+
"name": "sender-management",
20+
"private": true,
21+
"scripts": {
22+
"cli": "tsx ./src/entrypoint/cli/index.ts",
23+
"lint": "eslint .",
24+
"lint:fix": "eslint . --fix",
25+
"test:unit": "jest",
26+
"typecheck": "tsc --noEmit"
27+
},
28+
"sideEffects": false,
29+
"version": "0.0.1"
30+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { mockDeep } from 'jest-mock-extended';
2+
import { AppDependencies, createApp } from '../../app';
3+
import { DeleteSenderCommandParameters } from '../../app/delete-sender';
4+
5+
function setup() {
6+
const mocks = mockDeep<AppDependencies>({
7+
infra: {
8+
senderRepository: {
9+
deleteSender: jest.fn(),
10+
},
11+
},
12+
});
13+
14+
return mocks;
15+
}
16+
17+
describe('deleteSender', () => {
18+
it('deletes the sender from the sender repository by id', async () => {
19+
const mocks = setup();
20+
21+
const app = createApp(mocks);
22+
23+
const input: DeleteSenderCommandParameters = { senderId: 'input_id' };
24+
25+
await app.deleteSender(input);
26+
27+
expect(mocks.infra.senderRepository.deleteSender).toHaveBeenCalledWith(
28+
input.senderId,
29+
);
30+
});
31+
});

0 commit comments

Comments
 (0)