@nestarc/webhook 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -25
- package/dist/adapters/fetch-http-client.d.ts.map +1 -1
- package/dist/adapters/fetch-http-client.js +1 -1
- package/dist/adapters/fetch-http-client.js.map +1 -1
- package/dist/adapters/plaintext-secret-vault.d.ts.map +1 -1
- package/dist/adapters/plaintext-secret-vault.js +12 -2
- package/dist/adapters/plaintext-secret-vault.js.map +1 -1
- package/dist/adapters/prisma-delivery.repository.d.ts +12 -6
- package/dist/adapters/prisma-delivery.repository.d.ts.map +1 -1
- package/dist/adapters/prisma-delivery.repository.js +234 -46
- package/dist/adapters/prisma-delivery.repository.js.map +1 -1
- package/dist/adapters/prisma-endpoint.repository.d.ts +4 -3
- package/dist/adapters/prisma-endpoint.repository.d.ts.map +1 -1
- package/dist/adapters/prisma-endpoint.repository.js +41 -6
- package/dist/adapters/prisma-endpoint.repository.js.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/interfaces/webhook-delivery.interface.d.ts +17 -0
- package/dist/interfaces/webhook-delivery.interface.d.ts.map +1 -1
- package/dist/interfaces/webhook-endpoint.interface.d.ts +11 -1
- package/dist/interfaces/webhook-endpoint.interface.d.ts.map +1 -1
- package/dist/interfaces/webhook-options.interface.d.ts +8 -6
- package/dist/interfaces/webhook-options.interface.d.ts.map +1 -1
- package/dist/ports/webhook-delivery.repository.d.ts +30 -10
- package/dist/ports/webhook-delivery.repository.d.ts.map +1 -1
- package/dist/ports/webhook-endpoint.repository.d.ts +24 -4
- package/dist/ports/webhook-endpoint.repository.d.ts.map +1 -1
- package/dist/ports/webhook-event.repository.d.ts +3 -1
- package/dist/ports/webhook-event.repository.d.ts.map +1 -1
- package/dist/ports/webhook-http-client.d.ts +4 -0
- package/dist/ports/webhook-http-client.d.ts.map +1 -1
- package/dist/ports/webhook-secret-vault.d.ts +1 -0
- package/dist/ports/webhook-secret-vault.d.ts.map +1 -1
- package/dist/webhook.admin.service.d.ts +6 -4
- package/dist/webhook.admin.service.d.ts.map +1 -1
- package/dist/webhook.admin.service.js +8 -2
- package/dist/webhook.admin.service.js.map +1 -1
- package/dist/webhook.circuit-breaker.d.ts +6 -4
- package/dist/webhook.circuit-breaker.d.ts.map +1 -1
- package/dist/webhook.circuit-breaker.js +10 -8
- package/dist/webhook.circuit-breaker.js.map +1 -1
- package/dist/webhook.constants.d.ts +9 -2
- package/dist/webhook.constants.d.ts.map +1 -1
- package/dist/webhook.constants.js +11 -4
- package/dist/webhook.constants.js.map +1 -1
- package/dist/webhook.delivery-admin.service.d.ts +2 -1
- package/dist/webhook.delivery-admin.service.d.ts.map +1 -1
- package/dist/webhook.delivery-admin.service.js +3 -0
- package/dist/webhook.delivery-admin.service.js.map +1 -1
- package/dist/webhook.delivery-worker.d.ts +4 -0
- package/dist/webhook.delivery-worker.d.ts.map +1 -1
- package/dist/webhook.delivery-worker.js +49 -22
- package/dist/webhook.delivery-worker.js.map +1 -1
- package/dist/webhook.dispatcher.d.ts +1 -0
- package/dist/webhook.dispatcher.d.ts.map +1 -1
- package/dist/webhook.dispatcher.js +13 -6
- package/dist/webhook.dispatcher.js.map +1 -1
- package/dist/webhook.endpoint-admin.service.d.ts +4 -1
- package/dist/webhook.endpoint-admin.service.d.ts.map +1 -1
- package/dist/webhook.endpoint-admin.service.js +36 -9
- package/dist/webhook.endpoint-admin.service.js.map +1 -1
- package/dist/webhook.module.d.ts.map +1 -1
- package/dist/webhook.module.js +22 -13
- package/dist/webhook.module.js.map +1 -1
- package/dist/webhook.signer.d.ts +2 -0
- package/dist/webhook.signer.d.ts.map +1 -1
- package/dist/webhook.signer.js +28 -14
- package/dist/webhook.signer.js.map +1 -1
- package/package.json +4 -4
- package/src/sql/create-webhook-tables.sql +27 -1
- package/src/sql/migrations/v0.9.0.sql +32 -0
|
@@ -11,6 +11,26 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.PrismaDeliveryRepository = void 0;
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
|
+
const webhook_constants_1 = require("../webhook.constants");
|
|
15
|
+
const STALE_SENDING_RECOVERY_ERROR = 'Recovered stale SENDING delivery after worker lease expired';
|
|
16
|
+
function truncateAttemptResponseBody(body) {
|
|
17
|
+
if (body == null) {
|
|
18
|
+
return {
|
|
19
|
+
responseBody: null,
|
|
20
|
+
responseBodyTruncated: false,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (body.length <= webhook_constants_1.ATTEMPT_RESPONSE_BODY_MAX_LENGTH) {
|
|
24
|
+
return {
|
|
25
|
+
responseBody: body,
|
|
26
|
+
responseBodyTruncated: false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
responseBody: body.slice(0, webhook_constants_1.ATTEMPT_RESPONSE_BODY_MAX_LENGTH),
|
|
31
|
+
responseBodyTruncated: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
14
34
|
let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
15
35
|
prisma;
|
|
16
36
|
vault;
|
|
@@ -19,8 +39,35 @@ let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
|
19
39
|
this.vault = vault;
|
|
20
40
|
}
|
|
21
41
|
async createDeliveriesInTransaction(tx, eventId, endpointIds, maxAttempts) {
|
|
22
|
-
await tx.$executeRawUnsafe(`INSERT INTO webhook_deliveries (
|
|
23
|
-
|
|
42
|
+
await tx.$executeRawUnsafe(`INSERT INTO webhook_deliveries (
|
|
43
|
+
event_id,
|
|
44
|
+
endpoint_id,
|
|
45
|
+
status,
|
|
46
|
+
attempts,
|
|
47
|
+
max_attempts,
|
|
48
|
+
next_attempt_at,
|
|
49
|
+
endpoint_url_snapshot,
|
|
50
|
+
signing_secret_snapshot,
|
|
51
|
+
secondary_signing_secret_snapshot
|
|
52
|
+
)
|
|
53
|
+
SELECT
|
|
54
|
+
$1::uuid,
|
|
55
|
+
e.id,
|
|
56
|
+
'PENDING',
|
|
57
|
+
0,
|
|
58
|
+
$3,
|
|
59
|
+
NOW(),
|
|
60
|
+
e.url,
|
|
61
|
+
e.secret,
|
|
62
|
+
CASE
|
|
63
|
+
WHEN e.previous_secret IS NOT NULL
|
|
64
|
+
AND e.previous_secret_expires_at IS NOT NULL
|
|
65
|
+
AND e.previous_secret_expires_at > NOW()
|
|
66
|
+
THEN e.previous_secret
|
|
67
|
+
ELSE NULL
|
|
68
|
+
END
|
|
69
|
+
FROM webhook_endpoints e
|
|
70
|
+
WHERE e.id = ANY($2::uuid[])`, eventId, endpointIds, maxAttempts);
|
|
24
71
|
}
|
|
25
72
|
async runInTransaction(fn) {
|
|
26
73
|
return this.prisma.$transaction(fn);
|
|
@@ -40,70 +87,142 @@ let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
|
40
87
|
)
|
|
41
88
|
RETURNING
|
|
42
89
|
webhook_deliveries.id,
|
|
43
|
-
webhook_deliveries.event_id,
|
|
44
|
-
webhook_deliveries.endpoint_id,
|
|
90
|
+
webhook_deliveries.event_id AS "eventId",
|
|
91
|
+
webhook_deliveries.endpoint_id AS "endpointId",
|
|
45
92
|
webhook_deliveries.attempts,
|
|
46
|
-
webhook_deliveries.max_attempts`;
|
|
93
|
+
webhook_deliveries.max_attempts AS "maxAttempts"`;
|
|
47
94
|
}
|
|
48
95
|
async enrichDeliveries(deliveryIds) {
|
|
49
96
|
const rows = await this.prisma.$queryRaw `
|
|
50
97
|
SELECT
|
|
51
|
-
d.id,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
98
|
+
d.id,
|
|
99
|
+
d.event_id AS "eventId",
|
|
100
|
+
d.endpoint_id AS "endpointId",
|
|
101
|
+
d.attempts,
|
|
102
|
+
d.max_attempts AS "maxAttempts",
|
|
103
|
+
e.tenant_id::text AS "tenantId",
|
|
104
|
+
COALESCE(d.endpoint_url_snapshot, e.url) AS url,
|
|
105
|
+
COALESCE(d.signing_secret_snapshot, e.secret) AS secret,
|
|
106
|
+
CASE
|
|
107
|
+
WHEN d.secondary_signing_secret_snapshot IS NULL
|
|
108
|
+
THEN ARRAY[]::text[]
|
|
109
|
+
ELSE ARRAY[d.secondary_signing_secret_snapshot]
|
|
110
|
+
END AS "additionalSecrets",
|
|
111
|
+
ev.event_type AS "eventType",
|
|
112
|
+
ev.payload
|
|
55
113
|
FROM webhook_deliveries d
|
|
56
114
|
JOIN webhook_endpoints e ON e.id = d.endpoint_id
|
|
57
115
|
JOIN webhook_events ev ON ev.id = d.event_id
|
|
58
116
|
WHERE d.id = ANY(${deliveryIds}::uuid[])`;
|
|
59
117
|
if (this.vault) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
118
|
+
await Promise.all(rows.map(async (row) => {
|
|
119
|
+
const [secret, additionalSecrets] = await Promise.all([
|
|
120
|
+
this.vault.decrypt(row.secret),
|
|
121
|
+
Promise.all(row.additionalSecrets.map((secret) => this.vault.decrypt(secret))),
|
|
122
|
+
]);
|
|
123
|
+
row.secret = secret;
|
|
124
|
+
row.additionalSecrets = additionalSecrets;
|
|
125
|
+
}));
|
|
63
126
|
}
|
|
64
127
|
return rows;
|
|
65
128
|
}
|
|
66
129
|
async markSent(deliveryId, attempts, result) {
|
|
67
|
-
await this.prisma.$
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
130
|
+
await this.prisma.$transaction(async (tx) => {
|
|
131
|
+
await tx.$executeRaw `
|
|
132
|
+
UPDATE webhook_deliveries
|
|
133
|
+
SET status = 'SENT', attempts = ${attempts},
|
|
134
|
+
last_attempt_at = NOW(), completed_at = NOW(),
|
|
135
|
+
response_status = ${result.statusCode ?? null},
|
|
136
|
+
response_body = ${result.body ?? null},
|
|
137
|
+
latency_ms = ${result.latencyMs}
|
|
138
|
+
WHERE id = ${deliveryId}::uuid`;
|
|
139
|
+
await this.appendAttemptLog(tx, deliveryId, attempts, 'SENT', result);
|
|
140
|
+
});
|
|
75
141
|
}
|
|
76
142
|
async markFailed(deliveryId, attempts, result) {
|
|
77
|
-
await this.prisma.$
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
143
|
+
await this.prisma.$transaction(async (tx) => {
|
|
144
|
+
await tx.$executeRaw `
|
|
145
|
+
UPDATE webhook_deliveries
|
|
146
|
+
SET status = 'FAILED', attempts = ${attempts},
|
|
147
|
+
last_attempt_at = NOW(), completed_at = NOW(),
|
|
148
|
+
response_status = ${result.statusCode ?? null},
|
|
149
|
+
response_body = ${result.body ?? null},
|
|
150
|
+
latency_ms = ${result.latencyMs},
|
|
151
|
+
last_error = ${result.error ?? null}
|
|
152
|
+
WHERE id = ${deliveryId}::uuid`;
|
|
153
|
+
await this.appendAttemptLog(tx, deliveryId, attempts, 'FAILED', result);
|
|
154
|
+
});
|
|
86
155
|
}
|
|
87
156
|
async markRetry(deliveryId, attempts, nextAt, result) {
|
|
88
|
-
await this.prisma.$
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
157
|
+
await this.prisma.$transaction(async (tx) => {
|
|
158
|
+
await tx.$executeRaw `
|
|
159
|
+
UPDATE webhook_deliveries
|
|
160
|
+
SET status = 'PENDING', attempts = ${attempts},
|
|
161
|
+
last_attempt_at = NOW(), next_attempt_at = ${nextAt},
|
|
162
|
+
response_status = ${result.statusCode ?? null},
|
|
163
|
+
response_body = ${result.body ?? null},
|
|
164
|
+
latency_ms = ${result.latencyMs},
|
|
165
|
+
last_error = ${result.error ?? null}
|
|
166
|
+
WHERE id = ${deliveryId}::uuid`;
|
|
167
|
+
await this.appendAttemptLog(tx, deliveryId, attempts, 'PENDING', result);
|
|
168
|
+
});
|
|
97
169
|
}
|
|
98
170
|
async recoverStaleSending(stalenessMinutes) {
|
|
99
171
|
const interval = `${stalenessMinutes} minutes`;
|
|
100
172
|
const recovered = await this.prisma.$queryRaw `
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
173
|
+
WITH recovered AS (
|
|
174
|
+
UPDATE webhook_deliveries
|
|
175
|
+
SET attempts = attempts + 1,
|
|
176
|
+
status = CASE
|
|
177
|
+
WHEN attempts + 1 >= max_attempts THEN 'FAILED'
|
|
178
|
+
ELSE 'PENDING'
|
|
179
|
+
END,
|
|
180
|
+
claimed_at = NULL,
|
|
181
|
+
last_attempt_at = NOW(),
|
|
182
|
+
next_attempt_at = CASE
|
|
183
|
+
WHEN attempts + 1 >= max_attempts THEN NULL
|
|
184
|
+
ELSE NOW()
|
|
185
|
+
END,
|
|
186
|
+
completed_at = CASE
|
|
187
|
+
WHEN attempts + 1 >= max_attempts THEN NOW()
|
|
188
|
+
ELSE completed_at
|
|
189
|
+
END,
|
|
190
|
+
response_status = NULL,
|
|
191
|
+
response_body = NULL,
|
|
192
|
+
latency_ms = NULL,
|
|
193
|
+
last_error = ${STALE_SENDING_RECOVERY_ERROR}
|
|
194
|
+
WHERE status = 'SENDING'
|
|
195
|
+
AND claimed_at IS NOT NULL
|
|
196
|
+
AND claimed_at + ${interval}::interval < NOW()
|
|
197
|
+
RETURNING id, attempts, status
|
|
198
|
+
),
|
|
199
|
+
attempt_log AS (
|
|
200
|
+
INSERT INTO webhook_delivery_attempts (
|
|
201
|
+
delivery_id,
|
|
202
|
+
attempt_number,
|
|
203
|
+
status,
|
|
204
|
+
response_status,
|
|
205
|
+
response_body,
|
|
206
|
+
response_body_truncated,
|
|
207
|
+
latency_ms,
|
|
208
|
+
last_error
|
|
209
|
+
)
|
|
210
|
+
SELECT
|
|
211
|
+
id,
|
|
212
|
+
attempts,
|
|
213
|
+
status,
|
|
214
|
+
NULL,
|
|
215
|
+
NULL,
|
|
216
|
+
FALSE,
|
|
217
|
+
NULL,
|
|
218
|
+
${STALE_SENDING_RECOVERY_ERROR}
|
|
219
|
+
FROM recovered
|
|
220
|
+
ON CONFLICT (delivery_id, attempt_number) DO NOTHING
|
|
221
|
+
RETURNING delivery_id
|
|
222
|
+
)
|
|
223
|
+
SELECT recovered.id
|
|
224
|
+
FROM recovered
|
|
225
|
+
LEFT JOIN attempt_log ON attempt_log.delivery_id = recovered.id`;
|
|
107
226
|
return recovered.length;
|
|
108
227
|
}
|
|
109
228
|
async getDeliveryLogs(endpointId, filters) {
|
|
@@ -132,6 +251,8 @@ let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
|
132
251
|
SELECT d.id, d.status, d.attempts,
|
|
133
252
|
d.event_id AS "eventId",
|
|
134
253
|
d.endpoint_id AS "endpointId",
|
|
254
|
+
COALESCE(d.endpoint_url_snapshot, ep.url) AS "destinationUrl",
|
|
255
|
+
ep.tenant_id::text AS "tenantId",
|
|
135
256
|
d.max_attempts AS "maxAttempts",
|
|
136
257
|
d.next_attempt_at AS "nextAttemptAt",
|
|
137
258
|
d.last_attempt_at AS "lastAttemptAt",
|
|
@@ -142,6 +263,7 @@ let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
|
142
263
|
d.last_error AS "lastError"
|
|
143
264
|
FROM webhook_deliveries d
|
|
144
265
|
JOIN webhook_events ev ON ev.id = d.event_id
|
|
266
|
+
JOIN webhook_endpoints ep ON ep.id = d.endpoint_id
|
|
145
267
|
WHERE ${conditions.join(' AND ')}
|
|
146
268
|
ORDER BY d.last_attempt_at DESC NULLS LAST
|
|
147
269
|
LIMIT $${paramIndex++}
|
|
@@ -150,6 +272,23 @@ let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
|
150
272
|
const results = await this.prisma.$queryRawUnsafe(query, ...values);
|
|
151
273
|
return results;
|
|
152
274
|
}
|
|
275
|
+
async getDeliveryAttempts(deliveryId) {
|
|
276
|
+
return this.prisma.$queryRaw `
|
|
277
|
+
SELECT
|
|
278
|
+
id,
|
|
279
|
+
delivery_id AS "deliveryId",
|
|
280
|
+
attempt_number AS "attemptNumber",
|
|
281
|
+
status,
|
|
282
|
+
response_status AS "responseStatus",
|
|
283
|
+
response_body AS "responseBody",
|
|
284
|
+
response_body_truncated AS "responseBodyTruncated",
|
|
285
|
+
latency_ms AS "latencyMs",
|
|
286
|
+
last_error AS "lastError",
|
|
287
|
+
created_at AS "createdAt"
|
|
288
|
+
FROM webhook_delivery_attempts
|
|
289
|
+
WHERE delivery_id = ${deliveryId}::uuid
|
|
290
|
+
ORDER BY attempt_number ASC`;
|
|
291
|
+
}
|
|
153
292
|
async retryDelivery(deliveryId) {
|
|
154
293
|
const result = await this.prisma.$executeRaw `
|
|
155
294
|
UPDATE webhook_deliveries
|
|
@@ -159,8 +298,57 @@ let PrismaDeliveryRepository = class PrismaDeliveryRepository {
|
|
|
159
298
|
}
|
|
160
299
|
async createTestDelivery(eventId, endpointId) {
|
|
161
300
|
await this.prisma.$executeRaw `
|
|
162
|
-
INSERT INTO webhook_deliveries (
|
|
163
|
-
|
|
301
|
+
INSERT INTO webhook_deliveries (
|
|
302
|
+
event_id,
|
|
303
|
+
endpoint_id,
|
|
304
|
+
status,
|
|
305
|
+
max_attempts,
|
|
306
|
+
next_attempt_at,
|
|
307
|
+
endpoint_url_snapshot,
|
|
308
|
+
signing_secret_snapshot,
|
|
309
|
+
secondary_signing_secret_snapshot
|
|
310
|
+
)
|
|
311
|
+
SELECT
|
|
312
|
+
${eventId}::uuid,
|
|
313
|
+
e.id,
|
|
314
|
+
'PENDING',
|
|
315
|
+
1,
|
|
316
|
+
NOW(),
|
|
317
|
+
e.url,
|
|
318
|
+
e.secret,
|
|
319
|
+
CASE
|
|
320
|
+
WHEN e.previous_secret IS NOT NULL
|
|
321
|
+
AND e.previous_secret_expires_at IS NOT NULL
|
|
322
|
+
AND e.previous_secret_expires_at > NOW()
|
|
323
|
+
THEN e.previous_secret
|
|
324
|
+
ELSE NULL
|
|
325
|
+
END
|
|
326
|
+
FROM webhook_endpoints e
|
|
327
|
+
WHERE e.id = ${endpointId}::uuid`;
|
|
328
|
+
}
|
|
329
|
+
async appendAttemptLog(client, deliveryId, attempts, status, result) {
|
|
330
|
+
const { responseBody, responseBodyTruncated } = truncateAttemptResponseBody(result.body ?? null);
|
|
331
|
+
await client.$executeRaw `
|
|
332
|
+
INSERT INTO webhook_delivery_attempts (
|
|
333
|
+
delivery_id,
|
|
334
|
+
attempt_number,
|
|
335
|
+
status,
|
|
336
|
+
response_status,
|
|
337
|
+
response_body,
|
|
338
|
+
response_body_truncated,
|
|
339
|
+
latency_ms,
|
|
340
|
+
last_error
|
|
341
|
+
)
|
|
342
|
+
VALUES (
|
|
343
|
+
${deliveryId}::uuid,
|
|
344
|
+
${attempts},
|
|
345
|
+
${status},
|
|
346
|
+
${result.statusCode ?? null},
|
|
347
|
+
${responseBody},
|
|
348
|
+
${responseBodyTruncated},
|
|
349
|
+
${result.latencyMs},
|
|
350
|
+
${result.error ?? null}
|
|
351
|
+
)`;
|
|
164
352
|
}
|
|
165
353
|
};
|
|
166
354
|
exports.PrismaDeliveryRepository = PrismaDeliveryRepository;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-delivery.repository.js","sourceRoot":"","sources":["../../src/adapters/prisma-delivery.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;
|
|
1
|
+
{"version":3,"file":"prisma-delivery.repository.js","sourceRoot":"","sources":["../../src/adapters/prisma-delivery.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WebhookEndpointRepository } from '../ports/webhook-endpoint.repository';
|
|
1
|
+
import { ResolvedCreateEndpointInput, ResolvedRotateEndpointSecretInput, WebhookEndpointRepository } from '../ports/webhook-endpoint.repository';
|
|
2
2
|
import { EndpointRecord, EndpointRecordWithSecret, UpdateEndpointDto } from '../interfaces/webhook-endpoint.interface';
|
|
3
3
|
import { WebhookSecretVault } from '../ports/webhook-secret-vault';
|
|
4
4
|
export declare class PrismaEndpointRepository implements WebhookEndpointRepository {
|
|
@@ -7,14 +7,15 @@ export declare class PrismaEndpointRepository implements WebhookEndpointReposito
|
|
|
7
7
|
constructor(prisma: any, vault?: WebhookSecretVault | undefined);
|
|
8
8
|
findMatchingEndpoints(eventType: string, tenantId: string | undefined): Promise<EndpointRecord[]>;
|
|
9
9
|
findMatchingEndpointsInTransaction(tx: any, eventType: string, tenantId: string | undefined): Promise<EndpointRecord[]>;
|
|
10
|
-
createEndpoint(
|
|
10
|
+
createEndpoint(input: ResolvedCreateEndpointInput): Promise<EndpointRecordWithSecret>;
|
|
11
11
|
getEndpoint(id: string): Promise<EndpointRecord | null>;
|
|
12
12
|
listEndpoints(tenantId?: string): Promise<EndpointRecord[]>;
|
|
13
13
|
updateEndpoint(id: string, dto: UpdateEndpointDto): Promise<EndpointRecord | null>;
|
|
14
|
+
rotateSecret(id: string, input: ResolvedRotateEndpointSecretInput): Promise<EndpointRecord | null>;
|
|
14
15
|
deleteEndpoint(id: string): Promise<boolean>;
|
|
15
16
|
resetFailures(endpointId: string): Promise<void>;
|
|
16
17
|
incrementFailures(endpointId: string): Promise<number>;
|
|
17
|
-
disableEndpoint(endpointId: string, reason: string): Promise<
|
|
18
|
+
disableEndpoint(endpointId: string, reason: string): Promise<boolean>;
|
|
18
19
|
recoverEligibleEndpoints(cooldownMinutes: number): Promise<number>;
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=prisma-endpoint.repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-endpoint.repository.d.ts","sourceRoot":"","sources":["../../src/adapters/prisma-endpoint.repository.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"prisma-endpoint.repository.d.ts","sourceRoot":"","sources":["../../src/adapters/prisma-endpoint.repository.ts"],"names":[],"mappings":"AACA,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,yBAAyB,EAC1B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAyBnE,qBACa,wBAAyB,YAAW,yBAAyB;IAEtE,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBADN,MAAM,EAAE,GAAG,EACX,KAAK,CAAC,EAAE,kBAAkB,YAAA;IAGvC,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,OAAO,CAAC,cAAc,EAAE,CAAC;IAoBtB,kCAAkC,CACtC,EAAE,EAAE,GAAG,EACP,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,OAAO,CAAC,cAAc,EAAE,CAAC;IAoBtB,cAAc,CAClB,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,wBAAwB,CAAC;IAkB9B,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAQvD,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAe3D,cAAc,CAClB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAqC3B,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAoB3B,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM5C,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBhD,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAStD,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrE,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAazE"}
|
|
@@ -11,6 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.PrismaEndpointRepository = void 0;
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
|
+
const webhook_constants_1 = require("../webhook.constants");
|
|
14
15
|
/** Public columns — excludes secret */
|
|
15
16
|
const ENDPOINT_COLUMNS = `
|
|
16
17
|
id, url, events, active, description, metadata,
|
|
@@ -18,6 +19,7 @@ const ENDPOINT_COLUMNS = `
|
|
|
18
19
|
consecutive_failures AS "consecutiveFailures",
|
|
19
20
|
disabled_at AS "disabledAt",
|
|
20
21
|
disabled_reason AS "disabledReason",
|
|
22
|
+
previous_secret_expires_at AS "previousSecretExpiresAt",
|
|
21
23
|
created_at AS "createdAt",
|
|
22
24
|
updated_at AS "updatedAt"`;
|
|
23
25
|
/** Internal columns — includes secret (for creation response only) */
|
|
@@ -27,6 +29,7 @@ const ENDPOINT_COLUMNS_WITH_SECRET = `
|
|
|
27
29
|
consecutive_failures AS "consecutiveFailures",
|
|
28
30
|
disabled_at AS "disabledAt",
|
|
29
31
|
disabled_reason AS "disabledReason",
|
|
32
|
+
previous_secret_expires_at AS "previousSecretExpiresAt",
|
|
30
33
|
created_at AS "createdAt",
|
|
31
34
|
updated_at AS "updatedAt"`;
|
|
32
35
|
let PrismaEndpointRepository = class PrismaEndpointRepository {
|
|
@@ -60,11 +63,13 @@ let PrismaEndpointRepository = class PrismaEndpointRepository {
|
|
|
60
63
|
AND ($1 = ANY(events) OR '*' = ANY(events))`, eventType);
|
|
61
64
|
return rows;
|
|
62
65
|
}
|
|
63
|
-
async createEndpoint(
|
|
64
|
-
const encryptedSecret = this.vault
|
|
66
|
+
async createEndpoint(input) {
|
|
67
|
+
const encryptedSecret = this.vault
|
|
68
|
+
? await this.vault.encrypt(input.secret)
|
|
69
|
+
: input.secret;
|
|
65
70
|
const [endpoint] = await this.prisma.$queryRawUnsafe(`INSERT INTO webhook_endpoints (url, secret, events, description, metadata, tenant_id)
|
|
66
71
|
VALUES ($1, $2, $3::varchar[], $4, $5::jsonb, $6::uuid)
|
|
67
|
-
RETURNING ${ENDPOINT_COLUMNS_WITH_SECRET}`, url, encryptedSecret, events, description, metadata ? JSON.stringify(metadata) : null, tenantId);
|
|
72
|
+
RETURNING ${ENDPOINT_COLUMNS_WITH_SECRET}`, input.url, encryptedSecret, input.events, input.description, input.metadata ? JSON.stringify(input.metadata) : null, input.tenantId);
|
|
68
73
|
return endpoint;
|
|
69
74
|
}
|
|
70
75
|
async getEndpoint(id) {
|
|
@@ -113,6 +118,19 @@ let PrismaEndpointRepository = class PrismaEndpointRepository {
|
|
|
113
118
|
const results = await this.prisma.$queryRawUnsafe(query, ...values);
|
|
114
119
|
return results[0] ?? null;
|
|
115
120
|
}
|
|
121
|
+
async rotateSecret(id, input) {
|
|
122
|
+
const encryptedSecret = this.vault
|
|
123
|
+
? await this.vault.encrypt(input.secret)
|
|
124
|
+
: input.secret;
|
|
125
|
+
const results = await this.prisma.$queryRawUnsafe(`UPDATE webhook_endpoints
|
|
126
|
+
SET previous_secret = secret,
|
|
127
|
+
secret = $1,
|
|
128
|
+
previous_secret_expires_at = $2,
|
|
129
|
+
updated_at = NOW()
|
|
130
|
+
WHERE id = $3::uuid
|
|
131
|
+
RETURNING ${ENDPOINT_COLUMNS}`, encryptedSecret, input.previousSecretExpiresAt, id);
|
|
132
|
+
return results[0] ?? null;
|
|
133
|
+
}
|
|
116
134
|
async deleteEndpoint(id) {
|
|
117
135
|
const result = await this.prisma.$executeRaw `
|
|
118
136
|
DELETE FROM webhook_endpoints WHERE id = ${id}::uuid`;
|
|
@@ -121,8 +139,23 @@ let PrismaEndpointRepository = class PrismaEndpointRepository {
|
|
|
121
139
|
async resetFailures(endpointId) {
|
|
122
140
|
await this.prisma.$executeRaw `
|
|
123
141
|
UPDATE webhook_endpoints
|
|
124
|
-
SET consecutive_failures = 0,
|
|
125
|
-
|
|
142
|
+
SET consecutive_failures = 0,
|
|
143
|
+
active = CASE
|
|
144
|
+
WHEN disabled_reason = ${webhook_constants_1.ENDPOINT_DISABLED_REASON_CONSECUTIVE_FAILURES_EXCEEDED}
|
|
145
|
+
THEN true
|
|
146
|
+
ELSE active
|
|
147
|
+
END,
|
|
148
|
+
disabled_at = CASE
|
|
149
|
+
WHEN disabled_reason = ${webhook_constants_1.ENDPOINT_DISABLED_REASON_CONSECUTIVE_FAILURES_EXCEEDED}
|
|
150
|
+
THEN NULL
|
|
151
|
+
ELSE disabled_at
|
|
152
|
+
END,
|
|
153
|
+
disabled_reason = CASE
|
|
154
|
+
WHEN disabled_reason = ${webhook_constants_1.ENDPOINT_DISABLED_REASON_CONSECUTIVE_FAILURES_EXCEEDED}
|
|
155
|
+
THEN NULL
|
|
156
|
+
ELSE disabled_reason
|
|
157
|
+
END,
|
|
158
|
+
updated_at = NOW()
|
|
126
159
|
WHERE id = ${endpointId}::uuid`;
|
|
127
160
|
}
|
|
128
161
|
async incrementFailures(endpointId) {
|
|
@@ -134,10 +167,11 @@ let PrismaEndpointRepository = class PrismaEndpointRepository {
|
|
|
134
167
|
return updated.consecutive_failures;
|
|
135
168
|
}
|
|
136
169
|
async disableEndpoint(endpointId, reason) {
|
|
137
|
-
await this.prisma.$executeRaw `
|
|
170
|
+
const updated = await this.prisma.$executeRaw `
|
|
138
171
|
UPDATE webhook_endpoints
|
|
139
172
|
SET active = false, disabled_at = NOW(), disabled_reason = ${reason}, updated_at = NOW()
|
|
140
173
|
WHERE id = ${endpointId}::uuid AND active = true`;
|
|
174
|
+
return updated > 0;
|
|
141
175
|
}
|
|
142
176
|
async recoverEligibleEndpoints(cooldownMinutes) {
|
|
143
177
|
const cooldownInterval = `${cooldownMinutes} minutes`;
|
|
@@ -147,6 +181,7 @@ let PrismaEndpointRepository = class PrismaEndpointRepository {
|
|
|
147
181
|
disabled_at = NULL, disabled_reason = NULL, updated_at = NOW()
|
|
148
182
|
WHERE active = false
|
|
149
183
|
AND disabled_at IS NOT NULL
|
|
184
|
+
AND disabled_reason = ${webhook_constants_1.ENDPOINT_DISABLED_REASON_CONSECUTIVE_FAILURES_EXCEEDED}
|
|
150
185
|
AND disabled_at + ${cooldownInterval}::interval <= NOW()
|
|
151
186
|
RETURNING id`;
|
|
152
187
|
return recovered.length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-endpoint.repository.js","sourceRoot":"","sources":["../../src/adapters/prisma-endpoint.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;
|
|
1
|
+
{"version":3,"file":"prisma-endpoint.repository.js","sourceRoot":"","sources":["../../src/adapters/prisma-endpoint.repository.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
export { WebhookModule } from './webhook.module';
|
|
2
2
|
export { WebhookService } from './webhook.service';
|
|
3
|
+
/** @internal Wired automatically by WebhookModule. Exported for advanced testing/custom integration only. */
|
|
3
4
|
export { WebhookDeliveryWorker } from './webhook.delivery-worker';
|
|
5
|
+
/** @internal Wired automatically by WebhookModule. Exported for advanced testing/custom integration only. */
|
|
4
6
|
export { WebhookDispatcher } from './webhook.dispatcher';
|
|
7
|
+
/** @internal Wired automatically by WebhookModule. Exported for advanced testing/custom integration only. */
|
|
5
8
|
export { WebhookRetryPolicy } from './webhook.retry-policy';
|
|
6
9
|
export { WebhookSigner, type SignatureHeaders } from './webhook.signer';
|
|
10
|
+
/** @internal Wired automatically by WebhookModule. Exported for advanced testing/custom integration only. */
|
|
7
11
|
export { WebhookCircuitBreaker } from './webhook.circuit-breaker';
|
|
8
12
|
export { WebhookEvent } from './webhook.event';
|
|
9
13
|
export { WebhookEndpointAdminService } from './webhook.endpoint-admin.service';
|
|
10
14
|
export { WebhookDeliveryAdminService } from './webhook.delivery-admin.service';
|
|
11
|
-
/** @deprecated Use WebhookEndpointAdminService and WebhookDeliveryAdminService */
|
|
15
|
+
/** @deprecated since v0.2.0. Will be removed in v1.0.0. Use {@link WebhookEndpointAdminService} and {@link WebhookDeliveryAdminService}. */
|
|
12
16
|
export { WebhookAdminService } from './webhook.admin.service';
|
|
13
17
|
export type { WebhookEventRepository } from './ports/webhook-event.repository';
|
|
14
|
-
export type { WebhookEndpointRepository } from './ports/webhook-endpoint.repository';
|
|
15
|
-
export type { WebhookDeliveryRepository, PendingDelivery, } from './ports/webhook-delivery.repository';
|
|
18
|
+
export type { WebhookEndpointRepository, ResolvedCreateEndpointInput, ResolvedRotateEndpointSecretInput, } from './ports/webhook-endpoint.repository';
|
|
19
|
+
export type { WebhookDeliveryRepository, ClaimedDelivery, PendingDelivery, WebhookTransaction, } from './ports/webhook-delivery.repository';
|
|
16
20
|
export type { WebhookHttpClient } from './ports/webhook-http-client';
|
|
17
21
|
export type { WebhookSecretVault } from './ports/webhook-secret-vault';
|
|
18
22
|
export { PrismaEventRepository } from './adapters/prisma-event.repository';
|
|
@@ -21,8 +25,9 @@ export { PrismaDeliveryRepository } from './adapters/prisma-delivery.repository'
|
|
|
21
25
|
export { FetchHttpClient } from './adapters/fetch-http-client';
|
|
22
26
|
export { PlaintextSecretVault } from './adapters/plaintext-secret-vault';
|
|
23
27
|
export type { WebhookModuleOptions, WebhookModuleAsyncOptions, WebhookOptionsFactory, DeliveryOptions, CircuitBreakerOptions, PollingOptions, DeliveryFailedContext, DeliveryFailureKind, EndpointDisabledContext, } from './interfaces/webhook-options.interface';
|
|
24
|
-
export type { EndpointRecord, EndpointRecordWithSecret, CreateEndpointDto, UpdateEndpointDto, } from './interfaces/webhook-endpoint.interface';
|
|
25
|
-
export type { DeliveryStatus, DeliveryRecord, EventRecord, DeliveryResult, DeliveryLogFilters, } from './interfaces/webhook-delivery.interface';
|
|
26
|
-
export { WEBHOOK_MODULE_OPTIONS, WEBHOOK_EVENT_REPOSITORY, WEBHOOK_ENDPOINT_REPOSITORY, WEBHOOK_DELIVERY_REPOSITORY, WEBHOOK_HTTP_CLIENT, DEFAULT_BACKOFF_SCHEDULE, DEFAULT_DELIVERY_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_POLLING_INTERVAL, DEFAULT_POLLING_BATCH_SIZE, DEFAULT_CIRCUIT_BREAKER_THRESHOLD, DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MINUTES, DEFAULT_STALE_SENDING_MINUTES, } from './webhook.constants';
|
|
28
|
+
export type { EndpointRecord, EndpointRecordWithSecret, CreateEndpointDto, UpdateEndpointDto, RotateEndpointSecretDto, } from './interfaces/webhook-endpoint.interface';
|
|
29
|
+
export type { DeliveryStatus, DeliveryAttemptStatus, DeliveryRecord, DeliveryAttemptRecord, EventRecord, DeliveryResult, DeliveryLogFilters, } from './interfaces/webhook-delivery.interface';
|
|
30
|
+
export { WEBHOOK_MODULE_OPTIONS, WEBHOOK_EVENT_REPOSITORY, WEBHOOK_ENDPOINT_REPOSITORY, WEBHOOK_DELIVERY_REPOSITORY, WEBHOOK_HTTP_CLIENT, WEBHOOK_SECRET_VAULT, DEFAULT_BACKOFF_SCHEDULE, DEFAULT_DELIVERY_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_POLLING_INTERVAL, DEFAULT_POLLING_BATCH_SIZE, DEFAULT_CIRCUIT_BREAKER_THRESHOLD, DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MINUTES, ENDPOINT_DISABLED_REASON_CONSECUTIVE_FAILURES_EXCEEDED, DEFAULT_STALE_SENDING_MINUTES, } from './webhook.constants';
|
|
31
|
+
export type { EndpointDisabledReason } from './webhook.constants';
|
|
27
32
|
export { validateWebhookUrl, resolveAndValidateHost, WebhookUrlValidationError, type WebhookUrlValidationReason, } from './webhook.url-validator';
|
|
28
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,6GAA6G;AAC7G,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,6GAA6G;AAC7G,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,6GAA6G;AAC7G,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,6GAA6G;AAC7G,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,4IAA4I;AAC5I,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,YAAY,EACV,yBAAyB,EACzB,2BAA2B,EAC3B,iCAAiC,GAClC,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,kBAAkB,GACnB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAGhD,YAAY,EACV,cAAc,EACd,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,yCAAyC,CAAC;AAEjD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,cAAc,EACd,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,iCAAiC,EACjC,wCAAwC,EACxC,sDAAsD,EACtD,6BAA6B,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAGlE,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,KAAK,0BAA0B,GAChC,MAAM,yBAAyB,CAAC"}
|