@shivaedev/webhooks 0.1.0 → 0.1.1
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/dist/internal/receive.d.ts.map +1 -1
- package/dist/internal/receive.js +6 -3
- package/dist/internal/receive.js.map +1 -1
- package/dist/route.d.ts.map +1 -1
- package/dist/route.js +3 -2
- package/dist/route.js.map +1 -1
- package/package.json +7 -7
- package/src/internal/receive.ts +6 -3
- package/src/route.ts +8 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receive.d.ts","sourceRoot":"","sources":["../../src/internal/receive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"receive.d.ts","sourceRoot":"","sources":["../../src/internal/receive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE1E,eAAO,MAAM,OAAO,GAAgC,CAAC,4fA+BnD,CAAC"}
|
package/dist/internal/receive.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Effect, Option } from "effect";
|
|
2
2
|
import { HttpServerResponse } from "effect/http";
|
|
3
|
+
import * as HttpStatus from "effect/http/HttpStatus";
|
|
3
4
|
import { SqlClient } from "effect/sql";
|
|
4
5
|
import { enqueueWebhookJobs } from "#registration.ts";
|
|
5
6
|
export const receive = Effect.fnUntraced(function* (name, source, key, body, headers, jobs) {
|
|
6
7
|
yield* source.strategy.verify(body, headers, key);
|
|
7
8
|
const { id, event } = source.strategy.delivery(headers);
|
|
8
9
|
if (!(id && event)) {
|
|
9
|
-
return HttpServerResponse.text("Invalid delivery", { status:
|
|
10
|
+
return HttpServerResponse.text("Invalid delivery", { status: HttpStatus.fromLiteral("BadRequest") });
|
|
10
11
|
}
|
|
11
12
|
const definition = Object.hasOwn(source.events, event) ? source.events[event] : undefined;
|
|
12
13
|
const sql = yield* SqlClient.SqlClient;
|
|
@@ -15,12 +16,14 @@ export const receive = Effect.fnUntraced(function* (name, source, key, body, hea
|
|
|
15
16
|
values (${name}, ${id}, ${event}, 'ignored', '[]'::jsonb)
|
|
16
17
|
on conflict (source, delivery_id) do nothing returning delivery_id`;
|
|
17
18
|
if (inserted.length === 0) {
|
|
18
|
-
return HttpServerResponse.text("already queued", { status:
|
|
19
|
+
return HttpServerResponse.text("already queued", { status: HttpStatus.fromLiteral("OK") });
|
|
19
20
|
}
|
|
20
21
|
const requests = definition === undefined ? [] : yield* definition.decode(body);
|
|
21
22
|
const ids = (yield* enqueueWebhookJobs(requests, jobs)).flatMap(Option.toArray);
|
|
22
23
|
yield* sql `update webhook_receipts set job_ids = ${JSON.stringify(ids)}::jsonb, outcome = ${requests.length === 0 ? "ignored" : "queued"} where source = ${name} and delivery_id = ${id}`;
|
|
23
|
-
return HttpServerResponse.text(requests.length === 0 ? "ignored" : "queued", {
|
|
24
|
+
return HttpServerResponse.text(requests.length === 0 ? "ignored" : "queued", {
|
|
25
|
+
status: requests.length === 0 ? HttpStatus.fromLiteral("OK") : HttpStatus.fromLiteral("Accepted"),
|
|
26
|
+
});
|
|
24
27
|
}));
|
|
25
28
|
});
|
|
26
29
|
//# sourceMappingURL=receive.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receive.js","sourceRoot":"","sources":["../../src/internal/receive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAiB,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAsB,MAAM,kBAAkB,CAAC;AAE1E,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EACjD,IAAY,EACZ,MAAwB,EACxB,GAA8B,EAC9B,IAAgB,EAChB,OAAyC,EACzC,IAAmB;IAEnB,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,kBAAkB,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"receive.js","sourceRoot":"","sources":["../../src/internal/receive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAiB,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAsB,MAAM,kBAAkB,CAAC;AAE1E,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EACjD,IAAY,EACZ,MAAwB,EACxB,GAA8B,EAC9B,IAAgB,EAChB,OAAyC,EACzC,IAAmB;IAEnB,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,kBAAkB,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,OAAO,KAAK,CAAC,CAAC,GAAG,CAAC,eAAe,CAChC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAA;cAChB,IAAI,KAAK,EAAE,KAAK,KAAK;uEACoC,CAAC;QACrE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,kBAAkB,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,MAAM,QAAQ,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChF,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAChF,KAAK,CAAC,CAAC,GAAG,CAAA,yCAAyC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,sBAAsB,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,mBAAmB,IAAI,sBAAsB,EAAE,EAAE,CAAC;QAC1L,OAAO,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE;YAC5E,MAAM,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC;SACjG,CAAC,CAAC;IACJ,CAAC,CAAC,CACF,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAU,KAAK,EAAiB,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAU,KAAK,EAAiB,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,WAAW,mBAAmB,CAAC,KAAK,EAAE,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,IAAI,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,oKA+B5E"}
|
package/dist/route.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Effect, Layer } from "effect";
|
|
2
2
|
import { HttpRouter, HttpServerResponse } from "effect/http";
|
|
3
|
+
import * as HttpStatus from "effect/http/HttpStatus";
|
|
3
4
|
import { readBoundedBody } from "@shivaedev/http/server/boundedBody.ts";
|
|
4
5
|
import { receive } from "#internal/receive.ts";
|
|
5
6
|
export function webhookRoute(options) {
|
|
@@ -16,11 +17,11 @@ export function webhookRoute(options) {
|
|
|
16
17
|
const source = Object.hasOwn(options.sources, name) ? options.sources[name] : undefined;
|
|
17
18
|
const key = keys.get(name);
|
|
18
19
|
if (source === undefined || key === undefined) {
|
|
19
|
-
return HttpServerResponse.empty({ status:
|
|
20
|
+
return HttpServerResponse.empty({ status: HttpStatus.fromLiteral("NotFound") });
|
|
20
21
|
}
|
|
21
22
|
const body = new Uint8Array(yield* readBoundedBody(request));
|
|
22
23
|
return yield* receive(name, source, key, body, request.headers, jobs).pipe(Effect.provideContext(context));
|
|
23
|
-
}).pipe(Effect.catchTag("RequestBodyTooLarge", () => Effect.succeed(HttpServerResponse.empty({ status:
|
|
24
|
+
}).pipe(Effect.catchTag("RequestBodyTooLarge", () => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("PayloadTooLarge") }))), Effect.catchTag("WebhookUnauthorized", () => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("Unauthorized") }))), Effect.catchTag("SchemaError", () => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("BadRequest") }))), Effect.catch(() => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("ServiceUnavailable") })))));
|
|
24
25
|
}).pipe(Effect.orDie));
|
|
25
26
|
}
|
|
26
27
|
//# sourceMappingURL=route.js.map
|
package/dist/route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,KAAK,EAAiB,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,KAAK,EAAiB,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAS/C,MAAM,UAAU,YAAY,CAAW,OAAsC;IAC5E,OAAO,KAAK,CAAC,MAAM,CAClB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAmC,CAAC;QACzE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqC,CAAC;QAC1D,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAClG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACxF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,MAAM,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC/C,OAAO,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACjF,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7D,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5G,CAAC,CAAC,CAAC,IAAI,CACN,MAAM,CAAC,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAC3C,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAC/F,EACD,MAAM,CAAC,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,EAC1I,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAChI,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,CACtH,CACD,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CACrB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/webhooks",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Verified webhook receipts and transactional job delivery over Effect HTTP",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect"
|
|
@@ -47,15 +47,15 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@shivaedev/github": "0.7.0",
|
|
49
49
|
"@shivaedev/http": "0.1.0",
|
|
50
|
-
"@shivaedev/jobs": "0.
|
|
51
|
-
"@shivaedev/sql": "0.
|
|
50
|
+
"@shivaedev/jobs": "0.22.0",
|
|
51
|
+
"@shivaedev/sql": "0.24.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@effect/platform-node": "4.0.5",
|
|
55
|
-
"@shivaedev/quality": "0.
|
|
56
|
-
"@shivaedev/server": "0.
|
|
57
|
-
"@shivaedev/test-sql": "0.10.
|
|
58
|
-
"@shivaedev/test-story": "0.
|
|
55
|
+
"@shivaedev/quality": "0.43.0",
|
|
56
|
+
"@shivaedev/server": "0.3.0",
|
|
57
|
+
"@shivaedev/test-sql": "0.10.2",
|
|
58
|
+
"@shivaedev/test-story": "0.22.0",
|
|
59
59
|
"@types/node": "24.19.2",
|
|
60
60
|
"effect": "4.0.5",
|
|
61
61
|
"pg-boss": "12.38.0",
|
package/src/internal/receive.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Effect, Option, type Redacted } from "effect";
|
|
2
2
|
import { HttpServerResponse } from "effect/http";
|
|
3
|
+
import * as HttpStatus from "effect/http/HttpStatus";
|
|
3
4
|
import { SqlClient } from "effect/sql";
|
|
4
5
|
import type { PgBossService } from "@shivaedev/jobs/server/service.ts";
|
|
5
6
|
import { enqueueWebhookJobs, type WebhookSource } from "#registration.ts";
|
|
@@ -15,7 +16,7 @@ export const receive = Effect.fnUntraced(function* <R>(
|
|
|
15
16
|
yield* source.strategy.verify(body, headers, key);
|
|
16
17
|
const { id, event } = source.strategy.delivery(headers);
|
|
17
18
|
if (!(id && event)) {
|
|
18
|
-
return HttpServerResponse.text("Invalid delivery", { status:
|
|
19
|
+
return HttpServerResponse.text("Invalid delivery", { status: HttpStatus.fromLiteral("BadRequest") });
|
|
19
20
|
}
|
|
20
21
|
const definition = Object.hasOwn(source.events, event) ? source.events[event] : undefined;
|
|
21
22
|
const sql = yield* SqlClient.SqlClient;
|
|
@@ -25,12 +26,14 @@ export const receive = Effect.fnUntraced(function* <R>(
|
|
|
25
26
|
values (${name}, ${id}, ${event}, 'ignored', '[]'::jsonb)
|
|
26
27
|
on conflict (source, delivery_id) do nothing returning delivery_id`;
|
|
27
28
|
if (inserted.length === 0) {
|
|
28
|
-
return HttpServerResponse.text("already queued", { status:
|
|
29
|
+
return HttpServerResponse.text("already queued", { status: HttpStatus.fromLiteral("OK") });
|
|
29
30
|
}
|
|
30
31
|
const requests = definition === undefined ? [] : yield* definition.decode(body);
|
|
31
32
|
const ids = (yield* enqueueWebhookJobs(requests, jobs)).flatMap(Option.toArray);
|
|
32
33
|
yield* sql`update webhook_receipts set job_ids = ${JSON.stringify(ids)}::jsonb, outcome = ${requests.length === 0 ? "ignored" : "queued"} where source = ${name} and delivery_id = ${id}`;
|
|
33
|
-
return HttpServerResponse.text(requests.length === 0 ? "ignored" : "queued", {
|
|
34
|
+
return HttpServerResponse.text(requests.length === 0 ? "ignored" : "queued", {
|
|
35
|
+
status: requests.length === 0 ? HttpStatus.fromLiteral("OK") : HttpStatus.fromLiteral("Accepted"),
|
|
36
|
+
});
|
|
34
37
|
}),
|
|
35
38
|
);
|
|
36
39
|
});
|
package/src/route.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Context, Effect, Layer, type Redacted } from "effect";
|
|
2
2
|
import { HttpRouter, HttpServerResponse } from "effect/http";
|
|
3
|
+
import * as HttpStatus from "effect/http/HttpStatus";
|
|
3
4
|
import type { SqlClient } from "effect/sql";
|
|
4
5
|
import { readBoundedBody } from "@shivaedev/http/server/boundedBody.ts";
|
|
5
6
|
import type { PgBossService } from "@shivaedev/jobs/server/service.ts";
|
|
@@ -28,15 +29,17 @@ export function webhookRoute<TJobs, R>(options: WebhookRouteOptions<TJobs, R>) {
|
|
|
28
29
|
const source = Object.hasOwn(options.sources, name) ? options.sources[name] : undefined;
|
|
29
30
|
const key = keys.get(name);
|
|
30
31
|
if (source === undefined || key === undefined) {
|
|
31
|
-
return HttpServerResponse.empty({ status:
|
|
32
|
+
return HttpServerResponse.empty({ status: HttpStatus.fromLiteral("NotFound") });
|
|
32
33
|
}
|
|
33
34
|
const body = new Uint8Array(yield* readBoundedBody(request));
|
|
34
35
|
return yield* receive(name, source, key, body, request.headers, jobs).pipe(Effect.provideContext(context));
|
|
35
36
|
}).pipe(
|
|
36
|
-
Effect.catchTag("RequestBodyTooLarge", () =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Effect.
|
|
37
|
+
Effect.catchTag("RequestBodyTooLarge", () =>
|
|
38
|
+
Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("PayloadTooLarge") })),
|
|
39
|
+
),
|
|
40
|
+
Effect.catchTag("WebhookUnauthorized", () => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("Unauthorized") }))),
|
|
41
|
+
Effect.catchTag("SchemaError", () => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("BadRequest") }))),
|
|
42
|
+
Effect.catch(() => Effect.succeed(HttpServerResponse.empty({ status: HttpStatus.fromLiteral("ServiceUnavailable") }))),
|
|
40
43
|
),
|
|
41
44
|
);
|
|
42
45
|
}).pipe(Effect.orDie),
|