Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit e2830d1

Browse files
authored
feat: generate types for webhook from OpenAPI spec (#58)
- Add OpenAPI spec document for webhook - Add tooling to generate webhook types - Remove manually defined types for webhook - Change all blockNumber variables from bigint -> number as it's only a u32 - Lint/formatting
1 parent f026322 commit e2830d1

22 files changed

+991
-312
lines changed

apps/api/src/api.service.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,18 @@ export class ApiService {
7171
currentWebhookRegistrationDtos = JSON.parse(currentRegistedWebooks);
7272
}
7373

74-
webhookRegistration.announcementTypes.map((a) => a.toLowerCase()).forEach((announcementType) => {
75-
const existingRegistration = currentWebhookRegistrationDtos.find((currentWebhookRegistration) => currentWebhookRegistration.announcementType === announcementType);
76-
if (!existingRegistration) {
77-
currentWebhookRegistrationDtos.push({ announcementType: announcementType.toLowerCase(), urls: [webhookRegistration.url] });
78-
} else {
79-
const urls = new Set(existingRegistration.urls);
80-
urls.add(webhookRegistration.url);
81-
existingRegistration.urls = [...urls];
82-
}
83-
});
74+
webhookRegistration.announcementTypes
75+
.map((a) => a.toLowerCase())
76+
.forEach((announcementType) => {
77+
const existingRegistration = currentWebhookRegistrationDtos.find((currentWebhookRegistration) => currentWebhookRegistration.announcementType === announcementType);
78+
if (!existingRegistration) {
79+
currentWebhookRegistrationDtos.push({ announcementType: announcementType.toLowerCase(), urls: [webhookRegistration.url] });
80+
} else {
81+
const urls = new Set(existingRegistration.urls);
82+
urls.add(webhookRegistration.url);
83+
existingRegistration.urls = [...urls];
84+
}
85+
});
8486

8587
await this.redis.set(REGISTERED_WEBHOOK_KEY, JSON.stringify(currentWebhookRegistrationDtos));
8688
}

content-announcement.openapi.json

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
{
2+
"openapi": "3.1.0",
3+
"info": {
4+
"title": "Content Announcement API",
5+
"version": "1.0.0"
6+
},
7+
"paths": {
8+
"/content-announcements": {
9+
"post": {
10+
"summary": "Create a new content announcement",
11+
"operationId": "createAnnouncementResponse",
12+
"requestBody": {
13+
"required": true,
14+
"content": {
15+
"application/json": {
16+
"schema": {
17+
"$ref": "#/components/schemas/AnnouncementResponse"
18+
}
19+
}
20+
}
21+
},
22+
"responses": {
23+
"201": {
24+
"description": "Content announcement created successfully"
25+
},
26+
"400": {
27+
"description": "Bad request"
28+
}
29+
}
30+
}
31+
}
32+
},
33+
"components": {
34+
"schemas": {
35+
"AnnouncementType": {
36+
"enum": [
37+
0,
38+
2,
39+
3,
40+
4,
41+
5,
42+
6,
43+
113
44+
],
45+
"x-enum-varnames": [
46+
"Tombstone",
47+
"Broadcast",
48+
"Reply",
49+
"Reaction",
50+
"Profile",
51+
"Update",
52+
"PublicFollows"
53+
]
54+
},
55+
"AnnouncementResponse": {
56+
"type": "object",
57+
"properties": {
58+
"requestId": {
59+
"type": "string",
60+
"nullable": true,
61+
"description": "An optional identifier for the request, may be used for tracking or correlation"
62+
},
63+
"schemaId": {
64+
"type": "string",
65+
"description": "Identifier for the schema being used or referenced"
66+
},
67+
"blockNumber": {
68+
"type": "integer",
69+
"description": "The block number on the blockchain where this announcement was recorded"
70+
},
71+
"announcement": {
72+
"oneOf": [
73+
{
74+
"$ref": "#/components/schemas/TombstoneAnnouncement"
75+
},
76+
{
77+
"$ref": "#/components/schemas/BroadcastAnnouncement"
78+
},
79+
{
80+
"$ref": "#/components/schemas/ReplyAnnouncement"
81+
},
82+
{
83+
"$ref": "#/components/schemas/ReactionAnnouncement"
84+
},
85+
{
86+
"$ref": "#/components/schemas/ProfileAnnouncement"
87+
},
88+
{
89+
"$ref": "#/components/schemas/UpdateAnnouncement"
90+
}
91+
]
92+
}
93+
},
94+
"required": [
95+
"schemaId",
96+
"blockNumber",
97+
"announcement"
98+
]
99+
},
100+
"TypedAnnouncement": {
101+
"type": "object",
102+
"properties": {
103+
"announcementType": {
104+
"type": "AnnouncementType"
105+
},
106+
"fromId": {
107+
"type": "string"
108+
}
109+
},
110+
"required": [
111+
"announcementType",
112+
"fromId"
113+
],
114+
"discriminator": {
115+
"propertyName": "announcementType",
116+
"mapping": {
117+
"0": "#/components/schemas/TombstoneAnnouncement",
118+
"2": "#/components/schemas/BroadcastAnnouncement",
119+
"3": "#/components/schemas/ReplyAnnouncement",
120+
"4": "#/components/schemas/ReactionAnnouncement",
121+
"5": "#/components/schemas/ProfileAnnouncement",
122+
"6": "#/components/schemas/UpdateAnnouncement"
123+
}
124+
}
125+
},
126+
"TombstoneAnnouncement": {
127+
"allOf": [
128+
{
129+
"$ref": "#/components/schemas/TypedAnnouncement"
130+
},
131+
{
132+
"type": "object",
133+
"properties": {
134+
"targetAnnouncementType": {
135+
"type": "integer"
136+
},
137+
"targetContentHash": {
138+
"type": "string"
139+
}
140+
},
141+
"required": [
142+
"targetAnnouncementType",
143+
"targetContentHash"
144+
]
145+
}
146+
]
147+
},
148+
"BroadcastAnnouncement": {
149+
"allOf": [
150+
{
151+
"$ref": "#/components/schemas/TypedAnnouncement"
152+
},
153+
{
154+
"type": "object",
155+
"properties": {
156+
"contentHash": {
157+
"type": "string"
158+
},
159+
"url": {
160+
"type": "string"
161+
}
162+
},
163+
"required": [
164+
"contentHash",
165+
"url"
166+
]
167+
}
168+
]
169+
},
170+
"ReplyAnnouncement": {
171+
"allOf": [
172+
{
173+
"$ref": "#/components/schemas/TypedAnnouncement"
174+
},
175+
{
176+
"type": "object",
177+
"properties": {
178+
"contentHash": {
179+
"type": "string"
180+
},
181+
"inReplyTo": {
182+
"type": "string"
183+
},
184+
"url": {
185+
"type": "string"
186+
}
187+
},
188+
"required": [
189+
"contentHash",
190+
"inReplyTo",
191+
"url"
192+
]
193+
}
194+
]
195+
},
196+
"ReactionAnnouncement": {
197+
"allOf": [
198+
{
199+
"$ref": "#/components/schemas/TypedAnnouncement"
200+
},
201+
{
202+
"type": "object",
203+
"properties": {
204+
"emoji": {
205+
"type": "string"
206+
},
207+
"inReplyTo": {
208+
"type": "string"
209+
},
210+
"apply": {
211+
"type": "integer"
212+
}
213+
},
214+
"required": [
215+
"emoji",
216+
"inReplyTo",
217+
"apply"
218+
]
219+
}
220+
]
221+
},
222+
"ProfileAnnouncement": {
223+
"allOf": [
224+
{
225+
"$ref": "#/components/schemas/TypedAnnouncement"
226+
},
227+
{
228+
"type": "object",
229+
"properties": {
230+
"contentHash": {
231+
"type": "string"
232+
},
233+
"url": {
234+
"type": "string"
235+
}
236+
},
237+
"required": [
238+
"contentHash",
239+
"url"
240+
]
241+
}
242+
]
243+
},
244+
"UpdateAnnouncement": {
245+
"allOf": [
246+
{
247+
"$ref": "#/components/schemas/TypedAnnouncement"
248+
},
249+
{
250+
"type": "object",
251+
"properties": {
252+
"contentHash": {
253+
"type": "string"
254+
},
255+
"targetAnnouncementType": {
256+
"type": "integer"
257+
},
258+
"targetContentHash": {
259+
"type": "string"
260+
},
261+
"url": {
262+
"type": "string"
263+
}
264+
},
265+
"required": [
266+
"contentHash",
267+
"targetAnnouncementType",
268+
"targetContentHash",
269+
"url"
270+
]
271+
}
272+
]
273+
}
274+
}
275+
}
276+
}

libs/common/src/config/swagger_config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { INestApplication } from '@nestjs/common';
22
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
3+
import * as fs from 'fs';
34
import metadata from '../../../../apps/api/src/metadata';
45

56
export const initSwagger = async (app: INestApplication, apiPath: string) => {
@@ -17,5 +18,9 @@ export const initSwagger = async (app: INestApplication, apiPath: string) => {
1718
const document = SwaggerModule.createDocument(app, options, {
1819
extraModels: [],
1920
});
21+
fs.writeFileSync(
22+
'./swagger.json',
23+
JSON.stringify(document, (_, v) => v, 2),
24+
);
2025
SwaggerModule.setup(apiPath, app, document);
2126
};

libs/common/src/crawler/crawler.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ import { Injectable } from '@nestjs/common';
33
import { InjectQueue, Processor } from '@nestjs/bullmq';
44
import Redis from 'ioredis';
55
import { InjectRedis } from '@songkeys/nestjs-redis';
6-
import { Vec, u16, u32 } from '@polkadot/types';
6+
import { Vec } from '@polkadot/types';
77
import { BlockPaginationResponseMessage, MessageResponse, SchemaId } from '@frequency-chain/api-augment/interfaces';
88
import { Job, Queue } from 'bullmq';
9-
import { firstValueFrom } from 'rxjs';
109
import { BlockNumber } from '@polkadot/types/interfaces';
1110
import { FrameSystemEventRecord } from '@polkadot/types/lookup';
1211
import { BlockchainService } from '../blockchain/blockchain.service';
@@ -16,7 +15,7 @@ import { createIPFSQueueJob } from '../interfaces/ipfs.job.interface';
1615
import { BaseConsumer } from '../utils/base-consumer';
1716
import { ContentSearchRequestDto } from '../dtos/request-job.dto';
1817
import { REGISTERED_WEBHOOK_KEY } from '../constants';
19-
import { MessageResponseWithSchemaId } from '../interfaces/announcement_response';
18+
import { MessageResponseWithSchemaId } from '../interfaces/message_response_with_schema_id';
2019

2120
@Injectable()
2221
@Processor(QueueConstants.REQUEST_QUEUE_NAME, {
@@ -138,7 +137,7 @@ export class CrawlerService extends BaseConsumer {
138137
}
139138

140139
const ipfsQueueJob = createIPFSQueueJob(
141-
message.block_number.toString(),
140+
message.block_number.toNumber(),
142141
message.msa_id.isNone ? message.provider_msa_id.toString() : message.msa_id.unwrap().toString(),
143142
message.provider_msa_id.toString(),
144143
schemaId,

0 commit comments

Comments
 (0)