Skip to content

Commit 1b08d0c

Browse files
Refactor handling of letter not found
1 parent d5c8591 commit 1b08d0c

10 files changed

Lines changed: 31 additions & 23 deletions

File tree

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
- [ ] This PR is a result of pair or mob programming
2828
- [ ] If I have used the 'skip-trivy-package' label I have done so responsibly and in the knowledge that this is being fixed as part of a separate ticket/PR.
2929

30+
## DT3-Specific Checklist
31+
32+
<!-- Go over all the following points, and put an `x` in all the boxes that apply. -->
33+
34+
- [ ] If I have added a new resource (SQS, Lambda, Gateway, DDB table, etc), I have created the appropriate alarms
35+
3036
---
3137

3238
## Sensitive Information Declaration

internal/datastore/src/__test__/letter-queue-repository.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "./db";
88
import LetterQueueRepository from "../letter-queue-repository";
99
import { InsertPendingLetter } from "../types";
10-
import { LetterAlreadyExistsError } from "../errors";
10+
import { LetterAlreadyExistsError } from "../errors/letter-already-exists-error";
1111
import { createTestLogger } from "./logs";
1212

1313
function createLetter(letterId = "letter1"): InsertPendingLetter {

internal/datastore/src/__test__/letter-repository.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ describe("LetterRepository", () => {
140140
await expect(
141141
letterRepository.getLetterById("supplier1", "letter1"),
142142
).rejects.toThrow(
143-
"Letter with id letter1 not found for supplier supplier1",
143+
"Letter not found: supplierId=supplier1, letterId=letter1",
144144
);
145145
});
146146

internal/datastore/src/errors.ts renamed to internal/datastore/src/errors/letter-already-exists-error.ts

File renamed without changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Error thrown when a letter is not found in the database.
3+
*/
4+
export default class LetterNotFoundError extends Error {
5+
constructor(
6+
public readonly supplierId: string,
7+
public readonly letterId: string,
8+
) {
9+
super(`Letter not found: supplierId=${supplierId}, letterId=${letterId}`);
10+
this.name = "LetterNotFoundError";
11+
}
12+
}

internal/datastore/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export * from "./types";
2-
export * from "./errors";
2+
export * from "./errors/letter-already-exists-error";
33
export * from "./mi-repository";
44
export * from "./letter-repository";
55
export * from "./supplier-repository";

internal/datastore/src/letter-queue-repository.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
PendingLetter,
66
PendingLetterSchema,
77
} from "./types";
8-
import { LetterAlreadyExistsError } from "./errors";
8+
import { LetterAlreadyExistsError } from "./errors/letter-already-exists-error";
99

1010
type LetterQueueRepositoryConfig = {
1111
letterQueueTableName: string;

internal/datastore/src/letter-repository.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
LetterSchemaBase,
1919
UpdateLetter,
2020
} from "./types";
21+
import LetterNotFoundError from "./errors/letter-not-found-error";
2122

2223
export type PagingOptions = Partial<{
2324
exclusiveStartKey: Record<string, any>;
@@ -117,9 +118,7 @@ export class LetterRepository {
117118
);
118119

119120
if (!result.Item) {
120-
throw new Error(
121-
`Letter with id ${letterId} not found for supplier ${supplierId}`,
122-
);
121+
throw new LetterNotFoundError(supplierId, letterId);
123122
}
124123
return LetterSchema.parse(result.Item);
125124
}

lambdas/api-handler/src/services/__tests__/letter-operations.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import pino from "pino";
33
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
44
import { S3Client } from "@aws-sdk/client-s3";
55
import { SQSClient } from "@aws-sdk/client-sqs";
6+
import LetterNotFoundError from "@internal/datastore/src/errors/letter-not-found-error";
67
import {
78
enqueueLetterUpdateRequests,
89
getLetterById,
@@ -104,13 +105,11 @@ describe("getLetterById", () => {
104105
const mockRepo = {
105106
getLetterById: jest
106107
.fn()
107-
.mockRejectedValue(
108-
new Error("Letter with id l1 not found for supplier s1"),
109-
),
108+
.mockRejectedValue(new LetterNotFoundError("supplier1", "letter1")),
110109
};
111110

112111
await expect(
113-
getLetterById("supplierid", "letter1", mockRepo as any),
112+
getLetterById("supplier1", "letter1", mockRepo as any),
114113
).rejects.toThrow("No resource found with that ID");
115114
});
116115

@@ -171,9 +170,7 @@ describe("getLetterDataUrl function", () => {
171170
deps.letterRepo = {
172171
getLetterById: jest
173172
.fn()
174-
.mockRejectedValue(
175-
new Error("Letter with id l1 not found for supplier s1"),
176-
),
173+
.mockRejectedValue(new LetterNotFoundError("supplier1", "letter42")),
177174
} as unknown as LetterRepository;
178175

179176
await expect(

lambdas/api-handler/src/services/letter-operations.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,12 @@ import { LetterBase, LetterRepository } from "@internal/datastore";
22
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
33
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
44
import { SendMessageBatchCommand } from "@aws-sdk/client-sqs";
5+
import LetterNotFoundError from "@internal/datastore/src/errors/letter-not-found-error";
56
import NotFoundError from "../errors/not-found-error";
67
import { UpdateLetterCommand } from "../contracts/letters";
78
import { ApiErrorDetail } from "../contracts/errors";
89
import { Deps } from "../config/deps";
910

10-
function isNotFoundError(error: any) {
11-
return (
12-
error instanceof Error &&
13-
/^Letter with id \w+ not found for supplier \w+$/.test(error.message)
14-
);
15-
}
16-
1711
async function getDownloadUrl(
1812
s3Uri: string,
1913
s3Client: S3Client,
@@ -50,7 +44,7 @@ export const getLetterById = async (
5044
try {
5145
letter = await letterRepo.getLetterById(supplierId, letterId);
5246
} catch (error) {
53-
if (isNotFoundError(error)) {
47+
if (error instanceof LetterNotFoundError) {
5448
throw new NotFoundError(ApiErrorDetail.NotFoundLetterId);
5549
}
5650
throw error;
@@ -74,7 +68,7 @@ export const getLetterDataUrl = async (
7468
deps.env.DOWNLOAD_URL_TTL_SECONDS,
7569
);
7670
} catch (error) {
77-
if (isNotFoundError(error)) {
71+
if (error instanceof LetterNotFoundError) {
7872
throw new NotFoundError(ApiErrorDetail.NotFoundLetterId);
7973
}
8074
throw error;

0 commit comments

Comments
 (0)