Skip to content

Commit 3e2c18c

Browse files
authored
Merge pull request #1385 from guardian/pf/ingest-iconik-messages-1
Iconik Ingest 1: Use zod for ingestion lambda types
2 parents e9887c0 + 8ceba93 commit 3e2c18c

File tree

5 files changed

+50
-63
lines changed

5 files changed

+50
-63
lines changed

pluto-message-ingestion/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"@aws-sdk/client-secrets-manager": "3.901.0",
1919
"@aws-sdk/credential-providers": "3.901.0",
2020
"@guardian/libs": "26.0.0",
21-
"esbuild": "0.25.10"
21+
"esbuild": "0.25.10",
22+
"zod": "^4.1.12"
2223
},
2324
"devDependencies": {
2425
"@types/aws-lambda": "8.10.152",

pluto-message-ingestion/scripts/test-pluto-lambda-CODE.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// @ts-check
33

44
/**
5-
* @typedef {import("../src/types").UpsertMessage} UpsertMessage
6-
* @typedef {import("../src/types").DeleteMessage} DeleteMessage
5+
* @typedef {import("../src/types").PlutoUpsertMessage} UpsertMessage
6+
* @typedef {import("../src/types").PlutoDeleteMessage} DeleteMessage
77
*/
88

99
import { getProject, invokeLambda } from './aws.js';

pluto-message-ingestion/src/process-record.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { createHmacClient } from './hmac-request';
44
import { createLogger, Logger } from './logging';
55
import {
66
hasRecognisedMessageType,
7-
isDeleteMessage,
8-
isUpsertMessage
7+
isPlutoDeleteMessage,
8+
isPlutoUpsertMessage
99
} from './types';
1010

1111
export async function processRecord(
@@ -24,7 +24,7 @@ export async function processRecord(
2424
return 'failure'; // if the message is not valid there isn't any point in retrying
2525
}
2626

27-
if (isDeleteMessage(data)) {
27+
if (isPlutoDeleteMessage(data)) {
2828
const result = await hmacDelete({
2929
url: `${baseUrl}/api/pluto/commissions/${data.commissionId}`
3030
});
@@ -36,7 +36,7 @@ export async function processRecord(
3636
`Error deleting commission ${data.commissionId}: ${result.status} ${result.statusText}`
3737
);
3838
}
39-
} else if (isUpsertMessage(data)) {
39+
} else if (isPlutoUpsertMessage(data)) {
4040
const result = await hmacPut({
4141
url: `${baseUrl}/api/pluto/projects`,
4242
data
Lines changed: 37 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
const recognisedMessageTypes = ['project-created', 'project-updated'];
2-
type MessageType = (typeof recognisedMessageTypes)[number];
1+
import { z } from 'zod/v4';
32

4-
export type UpsertMessage = {
5-
type: MessageType;
6-
id: string;
7-
title: string;
8-
status: string;
9-
commissionId: string;
10-
commissionTitle: string;
11-
productionOffice: string;
12-
created: string;
13-
};
3+
const plutoMessageTypes = ['project-created', 'project-updated'];
4+
5+
const plutoMessageTypeSchema = z.enum(plutoMessageTypes);
6+
7+
export type MessageType = z.infer<typeof plutoMessageTypeSchema>;
148

159
export function isRecognisedMessageType(type: unknown): type is MessageType {
16-
return recognisedMessageTypes.includes(type as MessageType);
10+
return plutoMessageTypes.includes(type as MessageType);
1711
}
1812

1913
export function hasRecognisedMessageType(data: unknown): boolean {
@@ -24,50 +18,37 @@ export function hasRecognisedMessageType(data: unknown): boolean {
2418
return isRecognisedMessageType(type);
2519
}
2620

27-
export function isUpsertMessage(data: unknown): data is UpsertMessage {
28-
if (!data || typeof data !== 'object' || data === null) {
29-
return false;
30-
}
31-
const {
32-
type,
33-
id,
34-
title,
35-
status,
36-
commissionId,
37-
commissionTitle,
38-
productionOffice,
39-
created
40-
} = data as {
41-
[key: string]: unknown;
42-
};
43-
return (
44-
isRecognisedMessageType(type) &&
45-
typeof id === 'string' &&
46-
typeof title === 'string' &&
47-
typeof status === 'string' &&
48-
typeof commissionId === 'string' &&
49-
typeof commissionTitle === 'string' &&
50-
typeof productionOffice === 'string' &&
51-
typeof created === 'string'
52-
);
21+
const plutoUpsertMessageSchema = z.looseObject({
22+
type: plutoMessageTypeSchema,
23+
id: z.string(),
24+
title: z.string(),
25+
status: z.string(),
26+
commissionId: z.string(),
27+
commissionTitle: z.string(),
28+
productionOffice: z.string(),
29+
created: z.string()
30+
});
31+
32+
export type PlutoUpsertMessage = z.infer<typeof plutoUpsertMessageSchema>;
33+
34+
export function isPlutoUpsertMessage(
35+
data: unknown
36+
): data is PlutoUpsertMessage {
37+
const parsed = plutoUpsertMessageSchema.safeParse(data);
38+
return parsed.success;
5339
}
5440

55-
export type DeleteMessage = {
56-
type: MessageType;
57-
commissionId: string;
58-
commissionTitle: '(DELETE)';
59-
};
41+
const PlutoDeleteMessageSchema = z.looseObject({
42+
type: plutoMessageTypeSchema,
43+
commissionId: z.string(),
44+
commissionTitle: z.literal('(DELETE)')
45+
});
6046

61-
export function isDeleteMessage(data: unknown): data is DeleteMessage {
62-
if (!data || typeof data !== 'object' || data === null) {
63-
return false;
64-
}
65-
const { commissionId, commissionTitle, type } = data as {
66-
[key: string]: unknown;
67-
};
68-
return (
69-
isRecognisedMessageType(type) &&
70-
typeof commissionId === 'string' &&
71-
commissionTitle === '(DELETE)'
72-
);
47+
export type PlutoDeleteMessage = z.infer<typeof PlutoDeleteMessageSchema>;
48+
49+
export function isPlutoDeleteMessage(
50+
data: unknown
51+
): data is PlutoDeleteMessage {
52+
const parsed = PlutoDeleteMessageSchema.safeParse(data);
53+
return parsed.success;
7354
}

pluto-message-ingestion/yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,3 +2296,8 @@ yocto-queue@^0.1.0:
22962296
version "0.1.0"
22972297
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
22982298
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
2299+
2300+
zod@^4.1.12:
2301+
version "4.1.12"
2302+
resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0"
2303+
integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==

0 commit comments

Comments
 (0)