hooklatch 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +438 -2
- package/dist/adapters/cloudflare.d.ts +11 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -0
- package/dist/adapters/cloudflare.js +27 -0
- package/dist/adapters/cloudflare.js.map +1 -0
- package/dist/adapters/express.d.ts +9 -0
- package/dist/adapters/express.d.ts.map +1 -0
- package/dist/adapters/express.js +63 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/hono.d.ts +12 -0
- package/dist/adapters/hono.d.ts.map +1 -0
- package/dist/adapters/hono.js +28 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/adapters/nextjs.d.ts +6 -0
- package/dist/adapters/nextjs.d.ts.map +1 -0
- package/dist/adapters/nextjs.js +56 -0
- package/dist/adapters/nextjs.js.map +1 -0
- package/dist/adapters/shared.d.ts +8 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/adapters/shared.js +53 -0
- package/dist/adapters/shared.js.map +1 -0
- package/dist/cjs/adapters/cloudflare.cjs +29 -0
- package/dist/cjs/adapters/cloudflare.d.cts +10 -0
- package/dist/cjs/adapters/express.cjs +65 -0
- package/dist/cjs/adapters/express.d.cts +8 -0
- package/dist/cjs/adapters/hono.cjs +30 -0
- package/dist/cjs/adapters/hono.d.cts +11 -0
- package/dist/cjs/adapters/nextjs.cjs +58 -0
- package/dist/cjs/adapters/nextjs.d.cts +5 -0
- package/dist/cjs/adapters/shared.cjs +58 -0
- package/dist/cjs/adapters/shared.d.cts +7 -0
- package/dist/cjs/core.cjs +30 -0
- package/dist/cjs/core.d.cts +5 -0
- package/dist/cjs/diagnostics/catalog.cjs +341 -0
- package/dist/cjs/diagnostics/catalog.d.cts +19 -0
- package/dist/cjs/diagnostics/index.cjs +90 -0
- package/dist/cjs/diagnostics/index.d.cts +5 -0
- package/dist/cjs/diagnostics/types.cjs +2 -0
- package/dist/cjs/diagnostics/types.d.cts +20 -0
- package/dist/cjs/errors.cjs +13 -0
- package/dist/cjs/errors.d.cts +6 -0
- package/dist/cjs/index.cjs +9 -0
- package/dist/cjs/index.d.cts +3 -0
- package/dist/cjs/internal/body.cjs +50 -0
- package/dist/cjs/internal/body.d.cts +2 -0
- package/dist/cjs/internal/bytes.cjs +43 -0
- package/dist/cjs/internal/bytes.d.cts +4 -0
- package/dist/cjs/internal/crypto.cjs +52 -0
- package/dist/cjs/internal/crypto.d.cts +3 -0
- package/dist/cjs/internal/headers.cjs +72 -0
- package/dist/cjs/internal/headers.d.cts +2 -0
- package/dist/cjs/internal/options.cjs +130 -0
- package/dist/cjs/internal/options.d.cts +7 -0
- package/dist/cjs/internal/prepare.cjs +11 -0
- package/dist/cjs/internal/prepare.d.cts +4 -0
- package/dist/cjs/internal/provider-options.cjs +72 -0
- package/dist/cjs/internal/provider-options.d.cts +6 -0
- package/dist/cjs/internal/provider.cjs +2 -0
- package/dist/cjs/internal/provider.d.cts +39 -0
- package/dist/cjs/internal/verification.cjs +71 -0
- package/dist/cjs/internal/verification.d.cts +12 -0
- package/dist/cjs/providers/clerk.cjs +15 -0
- package/dist/cjs/providers/clerk.d.cts +9 -0
- package/dist/cjs/providers/dodo-payments.cjs +26 -0
- package/dist/cjs/providers/dodo-payments.d.cts +20 -0
- package/dist/cjs/providers/doppler.cjs +71 -0
- package/dist/cjs/providers/doppler.d.cts +37 -0
- package/dist/cjs/providers/fal.cjs +80 -0
- package/dist/cjs/providers/fal.d.cts +13 -0
- package/dist/cjs/providers/github.cjs +52 -0
- package/dist/cjs/providers/github.d.cts +7 -0
- package/dist/cjs/providers/gitlab.cjs +26 -0
- package/dist/cjs/providers/gitlab.d.cts +20 -0
- package/dist/cjs/providers/grafana.cjs +180 -0
- package/dist/cjs/providers/grafana.d.cts +35 -0
- package/dist/cjs/providers/index.cjs +110 -0
- package/dist/cjs/providers/index.d.cts +26 -0
- package/dist/cjs/providers/lemon-squeezy.cjs +36 -0
- package/dist/cjs/providers/lemon-squeezy.d.cts +15 -0
- package/dist/cjs/providers/linear.cjs +58 -0
- package/dist/cjs/providers/linear.d.cts +36 -0
- package/dist/cjs/providers/paddle.cjs +105 -0
- package/dist/cjs/providers/paddle.d.cts +14 -0
- package/dist/cjs/providers/polar.cjs +80 -0
- package/dist/cjs/providers/polar.d.cts +25 -0
- package/dist/cjs/providers/razorpay.cjs +43 -0
- package/dist/cjs/providers/razorpay.d.cts +19 -0
- package/dist/cjs/providers/replicate.cjs +25 -0
- package/dist/cjs/providers/replicate.d.cts +19 -0
- package/dist/cjs/providers/sanity.cjs +161 -0
- package/dist/cjs/providers/sanity.d.cts +38 -0
- package/dist/cjs/providers/sentry.cjs +47 -0
- package/dist/cjs/providers/sentry.d.cts +25 -0
- package/dist/cjs/providers/shared.cjs +49 -0
- package/dist/cjs/providers/shared.d.cts +14 -0
- package/dist/cjs/providers/shopify.cjs +40 -0
- package/dist/cjs/providers/shopify.d.cts +8 -0
- package/dist/cjs/providers/standard-webhooks-protocol.cjs +97 -0
- package/dist/cjs/providers/standard-webhooks-protocol.d.cts +14 -0
- package/dist/cjs/providers/standard-webhooks.cjs +15 -0
- package/dist/cjs/providers/standard-webhooks.d.cts +9 -0
- package/dist/cjs/providers/stripe.cjs +81 -0
- package/dist/cjs/providers/stripe.d.cts +7 -0
- package/dist/cjs/providers/svix.cjs +63 -0
- package/dist/cjs/providers/svix.d.cts +9 -0
- package/dist/cjs/providers/vercel.cjs +39 -0
- package/dist/cjs/providers/vercel.d.cts +15 -0
- package/dist/cjs/providers/workos.cjs +120 -0
- package/dist/cjs/providers/workos.d.cts +32 -0
- package/dist/cjs/types.cjs +2 -0
- package/dist/cjs/types.d.cts +68 -0
- package/dist/cli/args.d.ts +86 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +358 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/filesystem.d.ts +15 -0
- package/dist/cli/filesystem.d.ts.map +1 -0
- package/dist/cli/filesystem.js +170 -0
- package/dist/cli/filesystem.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +64 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/templates.d.ts +13 -0
- package/dist/cli/templates.d.ts.map +1 -0
- package/dist/cli/templates.js +297 -0
- package/dist/cli/templates.js.map +1 -0
- package/dist/core.d.ts +6 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +26 -0
- package/dist/core.js.map +1 -0
- package/dist/diagnostics/catalog.d.ts +20 -0
- package/dist/diagnostics/catalog.d.ts.map +1 -0
- package/dist/diagnostics/catalog.js +335 -0
- package/dist/diagnostics/catalog.js.map +1 -0
- package/dist/diagnostics/index.d.ts +6 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +88 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/diagnostics/types.d.ts +21 -0
- package/dist/diagnostics/types.d.ts.map +1 -0
- package/dist/diagnostics/types.js +2 -0
- package/dist/diagnostics/types.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +10 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/body.d.ts +3 -0
- package/dist/internal/body.d.ts.map +1 -0
- package/dist/internal/body.js +48 -0
- package/dist/internal/body.js.map +1 -0
- package/dist/internal/bytes.d.ts +5 -0
- package/dist/internal/bytes.d.ts.map +1 -0
- package/dist/internal/bytes.js +38 -0
- package/dist/internal/bytes.js.map +1 -0
- package/dist/internal/crypto.d.ts +4 -0
- package/dist/internal/crypto.d.ts.map +1 -0
- package/dist/internal/crypto.js +49 -0
- package/dist/internal/crypto.js.map +1 -0
- package/dist/internal/headers.d.ts +3 -0
- package/dist/internal/headers.d.ts.map +1 -0
- package/dist/internal/headers.js +70 -0
- package/dist/internal/headers.js.map +1 -0
- package/dist/internal/options.d.ts +8 -0
- package/dist/internal/options.d.ts.map +1 -0
- package/dist/internal/options.js +128 -0
- package/dist/internal/options.js.map +1 -0
- package/dist/internal/prepare.d.ts +5 -0
- package/dist/internal/prepare.d.ts.map +1 -0
- package/dist/internal/prepare.js +9 -0
- package/dist/internal/prepare.js.map +1 -0
- package/dist/internal/provider-options.d.ts +7 -0
- package/dist/internal/provider-options.d.ts.map +1 -0
- package/dist/internal/provider-options.js +69 -0
- package/dist/internal/provider-options.js.map +1 -0
- package/dist/internal/provider.d.ts +40 -0
- package/dist/internal/provider.d.ts.map +1 -0
- package/dist/internal/provider.js +2 -0
- package/dist/internal/provider.js.map +1 -0
- package/dist/internal/verification.d.ts +13 -0
- package/dist/internal/verification.d.ts.map +1 -0
- package/dist/internal/verification.js +66 -0
- package/dist/internal/verification.js.map +1 -0
- package/dist/node/adapters/cloudflare.d.ts +1 -0
- package/dist/node/adapters/cloudflare.js +3 -0
- package/dist/node/adapters/express.d.ts +1 -0
- package/dist/node/adapters/express.js +3 -0
- package/dist/node/adapters/hono.d.ts +1 -0
- package/dist/node/adapters/hono.js +3 -0
- package/dist/node/adapters/nextjs.d.ts +1 -0
- package/dist/node/adapters/nextjs.js +3 -0
- package/dist/node/diagnostics/index.d.ts +1 -0
- package/dist/node/diagnostics/index.js +3 -0
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +6 -0
- package/dist/providers/clerk.d.ts +10 -0
- package/dist/providers/clerk.d.ts.map +1 -0
- package/dist/providers/clerk.js +13 -0
- package/dist/providers/clerk.js.map +1 -0
- package/dist/providers/dodo-payments.d.ts +21 -0
- package/dist/providers/dodo-payments.d.ts.map +1 -0
- package/dist/providers/dodo-payments.js +24 -0
- package/dist/providers/dodo-payments.js.map +1 -0
- package/dist/providers/doppler.d.ts +38 -0
- package/dist/providers/doppler.d.ts.map +1 -0
- package/dist/providers/doppler.js +69 -0
- package/dist/providers/doppler.js.map +1 -0
- package/dist/providers/fal.d.ts +14 -0
- package/dist/providers/fal.d.ts.map +1 -0
- package/dist/providers/fal.js +78 -0
- package/dist/providers/fal.js.map +1 -0
- package/dist/providers/github.d.ts +8 -0
- package/dist/providers/github.d.ts.map +1 -0
- package/dist/providers/github.js +50 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/gitlab.d.ts +21 -0
- package/dist/providers/gitlab.d.ts.map +1 -0
- package/dist/providers/gitlab.js +24 -0
- package/dist/providers/gitlab.js.map +1 -0
- package/dist/providers/grafana.d.ts +36 -0
- package/dist/providers/grafana.d.ts.map +1 -0
- package/dist/providers/grafana.js +178 -0
- package/dist/providers/grafana.js.map +1 -0
- package/dist/providers/index.d.ts +27 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +89 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/lemon-squeezy.d.ts +16 -0
- package/dist/providers/lemon-squeezy.d.ts.map +1 -0
- package/dist/providers/lemon-squeezy.js +34 -0
- package/dist/providers/lemon-squeezy.js.map +1 -0
- package/dist/providers/linear.d.ts +37 -0
- package/dist/providers/linear.d.ts.map +1 -0
- package/dist/providers/linear.js +56 -0
- package/dist/providers/linear.js.map +1 -0
- package/dist/providers/paddle.d.ts +15 -0
- package/dist/providers/paddle.d.ts.map +1 -0
- package/dist/providers/paddle.js +103 -0
- package/dist/providers/paddle.js.map +1 -0
- package/dist/providers/polar.d.ts +26 -0
- package/dist/providers/polar.d.ts.map +1 -0
- package/dist/providers/polar.js +78 -0
- package/dist/providers/polar.js.map +1 -0
- package/dist/providers/razorpay.d.ts +20 -0
- package/dist/providers/razorpay.d.ts.map +1 -0
- package/dist/providers/razorpay.js +41 -0
- package/dist/providers/razorpay.js.map +1 -0
- package/dist/providers/replicate.d.ts +20 -0
- package/dist/providers/replicate.d.ts.map +1 -0
- package/dist/providers/replicate.js +23 -0
- package/dist/providers/replicate.js.map +1 -0
- package/dist/providers/sanity.d.ts +39 -0
- package/dist/providers/sanity.d.ts.map +1 -0
- package/dist/providers/sanity.js +159 -0
- package/dist/providers/sanity.js.map +1 -0
- package/dist/providers/sentry.d.ts +26 -0
- package/dist/providers/sentry.d.ts.map +1 -0
- package/dist/providers/sentry.js +45 -0
- package/dist/providers/sentry.js.map +1 -0
- package/dist/providers/shared.d.ts +15 -0
- package/dist/providers/shared.d.ts.map +1 -0
- package/dist/providers/shared.js +40 -0
- package/dist/providers/shared.js.map +1 -0
- package/dist/providers/shopify.d.ts +9 -0
- package/dist/providers/shopify.d.ts.map +1 -0
- package/dist/providers/shopify.js +38 -0
- package/dist/providers/shopify.js.map +1 -0
- package/dist/providers/standard-webhooks-protocol.d.ts +15 -0
- package/dist/providers/standard-webhooks-protocol.d.ts.map +1 -0
- package/dist/providers/standard-webhooks-protocol.js +95 -0
- package/dist/providers/standard-webhooks-protocol.js.map +1 -0
- package/dist/providers/standard-webhooks.d.ts +10 -0
- package/dist/providers/standard-webhooks.d.ts.map +1 -0
- package/dist/providers/standard-webhooks.js +13 -0
- package/dist/providers/standard-webhooks.js.map +1 -0
- package/dist/providers/stripe.d.ts +8 -0
- package/dist/providers/stripe.d.ts.map +1 -0
- package/dist/providers/stripe.js +79 -0
- package/dist/providers/stripe.js.map +1 -0
- package/dist/providers/svix.d.ts +10 -0
- package/dist/providers/svix.d.ts.map +1 -0
- package/dist/providers/svix.js +61 -0
- package/dist/providers/svix.js.map +1 -0
- package/dist/providers/vercel.d.ts +16 -0
- package/dist/providers/vercel.d.ts.map +1 -0
- package/dist/providers/vercel.js +37 -0
- package/dist/providers/vercel.js.map +1 -0
- package/dist/providers/workos.d.ts +33 -0
- package/dist/providers/workos.d.ts.map +1 -0
- package/dist/providers/workos.js +118 -0
- package/dist/providers/workos.js.map +1 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +200 -4
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { NormalizedHeaders, ParseResult } from '../internal/provider.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* Doppler `X-Doppler-Signature: sha256=<hex HMAC-SHA256(raw request body)>`.
|
|
4
|
+
*
|
|
5
|
+
* Doppler documents exactly one `<scheme>=<64 hex>` value; there is no list and
|
|
6
|
+
* no unknown-field tolerance. The complete value is validated before the scheme
|
|
7
|
+
* decision, so a well-formed digest under another scheme token (`sha1=<64 hex>`)
|
|
8
|
+
* fails as `unsupported-scheme`, while any nonconforming syntax — wrong length,
|
|
9
|
+
* non-hex, bare hex, commas, extra equals, empty digest, or outer whitespace —
|
|
10
|
+
* fails as `malformed-signature`. `sha256=` is case-sensitive; `SHA256=<64 hex>`
|
|
11
|
+
* is a different scheme and therefore unsupported.
|
|
12
|
+
*
|
|
13
|
+
* The secret is the literal, untrimmed UTF-8 text of the webhook `Secret`. It is
|
|
14
|
+
* never Base64-decoded and no `whsec_`-style prefix is inferred, so an empty
|
|
15
|
+
* secret is an invalid configuration rather than an encoded empty key.
|
|
16
|
+
*
|
|
17
|
+
* The HMAC covers the exact raw body only; no timestamp or identifier is
|
|
18
|
+
* included in the MAC, so every identity field is null and
|
|
19
|
+
* `authenticatedFields` is empty: this descriptor never establishes freshness and
|
|
20
|
+
* offers no replay protection. Signing is optional on the Doppler side, so a
|
|
21
|
+
* delivery without a configured secret carries no signature and cannot be
|
|
22
|
+
* verified; there is no Basic/Bearer or unsigned fallback path here.
|
|
23
|
+
*
|
|
24
|
+
* The Doppler docs' Node example re-serializes with `JSON.stringify(req.body)`.
|
|
25
|
+
* This descriptor authenticates the received bytes instead, so a caller that has
|
|
26
|
+
* already parsed the body cannot reliably reconstruct the signed content and
|
|
27
|
+
* should pass the original bytes.
|
|
28
|
+
*
|
|
29
|
+
* Source: https://docs.doppler.com/docs/webhooks
|
|
30
|
+
*
|
|
31
|
+
* No Doppler-published signature tuple was located; test anchors are synthetic.
|
|
32
|
+
*/
|
|
33
|
+
export declare const dopplerDescriptor: {
|
|
34
|
+
provider: "doppler";
|
|
35
|
+
decodeSecret(secret: string): Uint8Array;
|
|
36
|
+
parse(headers: NormalizedHeaders, rawBody: Uint8Array): ParseResult;
|
|
37
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.falDescriptor = void 0;
|
|
4
|
+
const errors_js_1 = require("../errors.cjs");
|
|
5
|
+
const bytes_js_1 = require("../internal/bytes.cjs");
|
|
6
|
+
const shared_js_1 = require("./shared.cjs");
|
|
7
|
+
/** Static-key fal webhook formatting only; key authentication belongs to core.
|
|
8
|
+
* https://fal.ai/docs/documentation/model-apis/inference/webhooks
|
|
9
|
+
* Strict ID and hex grammars are Hooklatch receiver policy, not vendor parity.
|
|
10
|
+
*/
|
|
11
|
+
exports.falDescriptor = {
|
|
12
|
+
provider: 'fal',
|
|
13
|
+
crypto: { kind: 'ed25519', signatureBytes: 64 },
|
|
14
|
+
async parse(headers, rawBody) {
|
|
15
|
+
const signatureRaw = headers.get('x-fal-webhook-signature');
|
|
16
|
+
const requestId = headers.get('x-fal-webhook-request-id');
|
|
17
|
+
const userId = headers.get('x-fal-webhook-user-id');
|
|
18
|
+
const timestamp = headers.get('x-fal-webhook-timestamp');
|
|
19
|
+
if (signatureRaw === undefined || signatureRaw.trim() === '') {
|
|
20
|
+
return (0, shared_js_1.failure)('missing-signature', 'No fal signature header was provided.');
|
|
21
|
+
}
|
|
22
|
+
const signature = decodeSignature(signatureRaw);
|
|
23
|
+
if (signature === null)
|
|
24
|
+
return malformed();
|
|
25
|
+
// Presence of both IDs takes precedence over grammar of either ID.
|
|
26
|
+
if (requestId === undefined || requestId.trim() === '') {
|
|
27
|
+
return (0, shared_js_1.failure)('missing-identity', 'No fal request identity was provided.');
|
|
28
|
+
}
|
|
29
|
+
if (userId === undefined || userId.trim() === '') {
|
|
30
|
+
return (0, shared_js_1.failure)('missing-identity', 'No fal user identity was provided.');
|
|
31
|
+
}
|
|
32
|
+
if (!isIdentity(requestId) || !isIdentity(userId))
|
|
33
|
+
return malformed();
|
|
34
|
+
if (timestamp === undefined || timestamp.trim() === '') {
|
|
35
|
+
return (0, shared_js_1.failure)('missing-timestamp', 'No fal timestamp was provided.');
|
|
36
|
+
}
|
|
37
|
+
if (!(0, shared_js_1.isCanonicalTimestamp)(timestamp))
|
|
38
|
+
return malformed();
|
|
39
|
+
const body = new Uint8Array(rawBody);
|
|
40
|
+
const subtle = globalThis.crypto?.subtle;
|
|
41
|
+
if (!subtle)
|
|
42
|
+
throw new errors_js_1.HooklatchError('crypto-unavailable', 'Web Crypto is unavailable.');
|
|
43
|
+
let digest;
|
|
44
|
+
try {
|
|
45
|
+
digest = await subtle.digest('SHA-256', body);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (isUnsupported(error)) {
|
|
49
|
+
throw new errors_js_1.HooklatchError('crypto-unavailable', 'Web Crypto is unavailable.');
|
|
50
|
+
}
|
|
51
|
+
throw new errors_js_1.HooklatchError('internal', 'Cryptographic verification failed.');
|
|
52
|
+
}
|
|
53
|
+
const hex = Array.from(new Uint8Array(digest), byte => byte.toString(16).padStart(2, '0')).join('');
|
|
54
|
+
return {
|
|
55
|
+
ok: true, signatures: [signature],
|
|
56
|
+
signedContent: (0, bytes_js_1.utf8)(`${requestId}\n${userId}\n${timestamp}\n${hex}`),
|
|
57
|
+
recipient: userId,
|
|
58
|
+
identity: { deliveryId: null, eventId: null, timestamp: Number(timestamp), authenticatedFields: ['timestamp'] },
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
function malformed() {
|
|
63
|
+
return (0, shared_js_1.failure)('malformed-signature', 'The fal signature headers are malformed.');
|
|
64
|
+
}
|
|
65
|
+
/** DOM exceptions may originate outside this realm. */
|
|
66
|
+
function isUnsupported(error) {
|
|
67
|
+
return error !== null && typeof error === 'object' && 'name' in error && error.name === 'NotSupportedError';
|
|
68
|
+
}
|
|
69
|
+
function isIdentity(value) {
|
|
70
|
+
return /^[\x21-\x7e]{1,1024}$/.test(value) && !value.includes(',');
|
|
71
|
+
}
|
|
72
|
+
function decodeSignature(value) {
|
|
73
|
+
if (!/^[a-fA-F0-9]{128}$/.test(value))
|
|
74
|
+
return null;
|
|
75
|
+
const bytes = new Uint8Array(64);
|
|
76
|
+
for (let index = 0; index < bytes.length; index++) {
|
|
77
|
+
bytes[index] = Number.parseInt(value.slice(index * 2, index * 2 + 2), 16);
|
|
78
|
+
}
|
|
79
|
+
return bytes;
|
|
80
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FalParseResult, NormalizedHeaders } from '../internal/provider.cjs';
|
|
2
|
+
/** Static-key fal webhook formatting only; key authentication belongs to core.
|
|
3
|
+
* https://fal.ai/docs/documentation/model-apis/inference/webhooks
|
|
4
|
+
* Strict ID and hex grammars are Hooklatch receiver policy, not vendor parity.
|
|
5
|
+
*/
|
|
6
|
+
export declare const falDescriptor: {
|
|
7
|
+
provider: "fal";
|
|
8
|
+
crypto: {
|
|
9
|
+
kind: "ed25519";
|
|
10
|
+
signatureBytes: 64;
|
|
11
|
+
};
|
|
12
|
+
parse(headers: NormalizedHeaders, rawBody: Uint8Array): Promise<FalParseResult>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.githubDescriptor = void 0;
|
|
4
|
+
const shared_js_1 = require("./shared.cjs");
|
|
5
|
+
const SIGNATURE_HEADER = 'x-hub-signature-256';
|
|
6
|
+
const LEGACY_SIGNATURE_HEADER = 'x-hub-signature';
|
|
7
|
+
const SCHEME = 'sha256';
|
|
8
|
+
const DELIVERY_HEADER = 'x-github-delivery';
|
|
9
|
+
function optionalHeader(headers, name) {
|
|
10
|
+
const value = headers.get(name);
|
|
11
|
+
return value === undefined || value === '' ? null : value;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* GitHub `X-Hub-Signature-256: sha256=<hex>` over the raw body only. The legacy
|
|
15
|
+
* `X-Hub-Signature: sha1=<hex>` is recognized but never treated as SHA-256.
|
|
16
|
+
* `X-GitHub-Delivery` is unsigned metadata and never proves authenticity.
|
|
17
|
+
*/
|
|
18
|
+
exports.githubDescriptor = {
|
|
19
|
+
provider: 'github',
|
|
20
|
+
decodeSecret(secret) {
|
|
21
|
+
return (0, shared_js_1.decodeLiteralSecret)(secret, 'GitHub');
|
|
22
|
+
},
|
|
23
|
+
parse(headers, rawBody) {
|
|
24
|
+
const raw = headers.get(SIGNATURE_HEADER);
|
|
25
|
+
if (raw === undefined || raw.trim() === '') {
|
|
26
|
+
const legacy = headers.get(LEGACY_SIGNATURE_HEADER);
|
|
27
|
+
if (legacy !== undefined && legacy.trim() !== '') {
|
|
28
|
+
return (0, shared_js_1.failure)('unsupported-scheme', 'Only the legacy SHA-1 GitHub signature was provided.');
|
|
29
|
+
}
|
|
30
|
+
return (0, shared_js_1.failure)('missing-signature', 'No GitHub signature header was provided.');
|
|
31
|
+
}
|
|
32
|
+
const separator = raw.indexOf('=');
|
|
33
|
+
if (separator <= 0 || separator === raw.length - 1) {
|
|
34
|
+
return (0, shared_js_1.failure)('malformed-signature', 'The GitHub signature header is malformed.');
|
|
35
|
+
}
|
|
36
|
+
const scheme = raw.slice(0, separator);
|
|
37
|
+
if (scheme.toLowerCase() !== SCHEME) {
|
|
38
|
+
return (0, shared_js_1.failure)('unsupported-scheme', 'No supported GitHub signature scheme was provided.');
|
|
39
|
+
}
|
|
40
|
+
const signature = (0, shared_js_1.decodeHexSignature)(raw.slice(separator + 1));
|
|
41
|
+
if (signature === null) {
|
|
42
|
+
return (0, shared_js_1.failure)('malformed-signature', 'The GitHub signature header is malformed.');
|
|
43
|
+
}
|
|
44
|
+
const identity = {
|
|
45
|
+
deliveryId: optionalHeader(headers, DELIVERY_HEADER),
|
|
46
|
+
eventId: null,
|
|
47
|
+
timestamp: null,
|
|
48
|
+
authenticatedFields: [],
|
|
49
|
+
};
|
|
50
|
+
return { ok: true, signatures: [signature], signedContent: rawBody, identity };
|
|
51
|
+
},
|
|
52
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ProviderDescriptor } from '../internal/provider.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* GitHub `X-Hub-Signature-256: sha256=<hex>` over the raw body only. The legacy
|
|
4
|
+
* `X-Hub-Signature: sha1=<hex>` is recognized but never treated as SHA-256.
|
|
5
|
+
* `X-GitHub-Delivery` is unsigned metadata and never proves authenticity.
|
|
6
|
+
*/
|
|
7
|
+
export declare const githubDescriptor: ProviderDescriptor;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitlabDescriptor = void 0;
|
|
4
|
+
const standard_webhooks_protocol_js_1 = require("./standard-webhooks-protocol.cjs");
|
|
5
|
+
/**
|
|
6
|
+
* GitLab signing-token mode (introduced in 19.0 behind a default-enabled flag
|
|
7
|
+
* and generally available in 19.1) sends the canonical Standard Webhooks
|
|
8
|
+
* `webhook-id`, `webhook-timestamp` and `webhook-signature` headers. The
|
|
9
|
+
* secret is Base64-decoded (an optional `whsec_` prefix is stripped) and must
|
|
10
|
+
* decode to 24-64 bytes; the signature covers the exact
|
|
11
|
+
* `${webhook-id}.${webhook-timestamp}.` bytes followed by the raw body.
|
|
12
|
+
*
|
|
13
|
+
* The legacy `X-Gitlab-Token` header is a shared string comparison, not an
|
|
14
|
+
* authenticated body signature. It is deliberately ignored: a legacy-token-only
|
|
15
|
+
* request fails closed, and adding that header can neither repair a canonical
|
|
16
|
+
* defect nor change which bytes were authenticated.
|
|
17
|
+
*
|
|
18
|
+
* No GitLab-published signing-token vector is claimed; the direct tests use
|
|
19
|
+
* synthetic anchors. Source:
|
|
20
|
+
* https://docs.gitlab.com/user/project/integrations/webhooks/#signing-tokens
|
|
21
|
+
*/
|
|
22
|
+
exports.gitlabDescriptor = (0, standard_webhooks_protocol_js_1.createStandardWebhooksProtocol)('gitlab', 'GitLab', {
|
|
23
|
+
id: 'webhook-id',
|
|
24
|
+
timestamp: 'webhook-timestamp',
|
|
25
|
+
signature: 'webhook-signature',
|
|
26
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitLab signing-token mode (introduced in 19.0 behind a default-enabled flag
|
|
3
|
+
* and generally available in 19.1) sends the canonical Standard Webhooks
|
|
4
|
+
* `webhook-id`, `webhook-timestamp` and `webhook-signature` headers. The
|
|
5
|
+
* secret is Base64-decoded (an optional `whsec_` prefix is stripped) and must
|
|
6
|
+
* decode to 24-64 bytes; the signature covers the exact
|
|
7
|
+
* `${webhook-id}.${webhook-timestamp}.` bytes followed by the raw body.
|
|
8
|
+
*
|
|
9
|
+
* The legacy `X-Gitlab-Token` header is a shared string comparison, not an
|
|
10
|
+
* authenticated body signature. It is deliberately ignored: a legacy-token-only
|
|
11
|
+
* request fails closed, and adding that header can neither repair a canonical
|
|
12
|
+
* defect nor change which bytes were authenticated.
|
|
13
|
+
*
|
|
14
|
+
* No GitLab-published signing-token vector is claimed; the direct tests use
|
|
15
|
+
* synthetic anchors. Source:
|
|
16
|
+
* https://docs.gitlab.com/user/project/integrations/webhooks/#signing-tokens
|
|
17
|
+
*/
|
|
18
|
+
export declare const gitlabDescriptor: {
|
|
19
|
+
readonly provider: "gitlab";
|
|
20
|
+
} & Pick<import("../internal/provider.cjs").ProviderDescriptor, "decodeSecret" | "parse">;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGrafanaDescriptor = createGrafanaDescriptor;
|
|
4
|
+
const errors_js_1 = require("../errors.cjs");
|
|
5
|
+
const bytes_js_1 = require("../internal/bytes.cjs");
|
|
6
|
+
const shared_js_1 = require("./shared.cjs");
|
|
7
|
+
/** Grafana's own default signature header name. */
|
|
8
|
+
const DEFAULT_SIGNATURE_HEADER = 'x-grafana-alerting-signature';
|
|
9
|
+
/** RFC 9110 field-name token characters. */
|
|
10
|
+
const FIELD_NAME_TOKEN = /^[!#$%&'*+.^_`|~\dA-Za-z-]+$/;
|
|
11
|
+
/**
|
|
12
|
+
* Authentication and framing header names that a configured Grafana header
|
|
13
|
+
* must not replace. This is Hooklatch configuration policy, not a Grafana
|
|
14
|
+
* rule: Grafana itself does not restrict the configured header names.
|
|
15
|
+
*/
|
|
16
|
+
const RESERVED_HEADER_NAMES = new Set([
|
|
17
|
+
'host',
|
|
18
|
+
'content-length',
|
|
19
|
+
'transfer-encoding',
|
|
20
|
+
'connection',
|
|
21
|
+
'upgrade',
|
|
22
|
+
'trailer',
|
|
23
|
+
'te',
|
|
24
|
+
'proxy-authorization',
|
|
25
|
+
'proxy-authenticate',
|
|
26
|
+
'authorization',
|
|
27
|
+
'cookie',
|
|
28
|
+
'set-cookie',
|
|
29
|
+
]);
|
|
30
|
+
const ALLOWED_OPTION_KEYS = new Set([
|
|
31
|
+
'mode',
|
|
32
|
+
'signatureHeader',
|
|
33
|
+
'timestampHeader',
|
|
34
|
+
]);
|
|
35
|
+
const INVALID_OPTIONS_MESSAGE = 'Invalid Grafana provider options.';
|
|
36
|
+
function invalidOptions() {
|
|
37
|
+
throw new errors_js_1.HooklatchError('invalid-options', INVALID_OPTIONS_MESSAGE);
|
|
38
|
+
}
|
|
39
|
+
function isOptionsObject(options) {
|
|
40
|
+
return typeof options === 'object' && options !== null && !Array.isArray(options);
|
|
41
|
+
}
|
|
42
|
+
function isHeaderNameText(value) {
|
|
43
|
+
return typeof value === 'string';
|
|
44
|
+
}
|
|
45
|
+
function isConfiguredHeaderName(value) {
|
|
46
|
+
return FIELD_NAME_TOKEN.test(value) && !RESERVED_HEADER_NAMES.has(value.toLowerCase());
|
|
47
|
+
}
|
|
48
|
+
/** Only the three documented option keys are accepted; nothing is inherited. */
|
|
49
|
+
function hasUnexpectedOptionKey(options) {
|
|
50
|
+
for (const key of Object.keys(options)) {
|
|
51
|
+
if (!ALLOWED_OPTION_KEYS.has(key))
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
for (const key of Object.getOwnPropertySymbols(options)) {
|
|
55
|
+
if (Object.prototype.propertyIsEnumerable.call(options, key))
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function readSignatureHeader(options) {
|
|
61
|
+
if (!Object.hasOwn(options, 'signatureHeader'))
|
|
62
|
+
return DEFAULT_SIGNATURE_HEADER;
|
|
63
|
+
const value = options.signatureHeader;
|
|
64
|
+
if (!isHeaderNameText(value) || !isConfiguredHeaderName(value))
|
|
65
|
+
invalidOptions();
|
|
66
|
+
return value.toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
function readTimestampHeader(options, mode, signatureHeader) {
|
|
69
|
+
const configured = Object.hasOwn(options, 'timestampHeader');
|
|
70
|
+
if (mode === 'body') {
|
|
71
|
+
// Body-only mode has no timestamp header, not even an explicit undefined.
|
|
72
|
+
if (configured)
|
|
73
|
+
invalidOptions();
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (!configured)
|
|
77
|
+
invalidOptions();
|
|
78
|
+
const value = options.timestampHeader;
|
|
79
|
+
if (!isHeaderNameText(value) || !isConfiguredHeaderName(value))
|
|
80
|
+
invalidOptions();
|
|
81
|
+
const normalized = value.toLowerCase();
|
|
82
|
+
// A collision would make the two headers unreadable, so it is rejected.
|
|
83
|
+
if (normalized === signatureHeader)
|
|
84
|
+
invalidOptions();
|
|
85
|
+
return normalized;
|
|
86
|
+
}
|
|
87
|
+
function buildConfiguration(options) {
|
|
88
|
+
if (!isOptionsObject(options))
|
|
89
|
+
invalidOptions();
|
|
90
|
+
if (hasUnexpectedOptionKey(options))
|
|
91
|
+
invalidOptions();
|
|
92
|
+
if (!Object.hasOwn(options, 'mode'))
|
|
93
|
+
invalidOptions();
|
|
94
|
+
const mode = options.mode;
|
|
95
|
+
if (mode !== 'body' && mode !== 'timestamped')
|
|
96
|
+
invalidOptions();
|
|
97
|
+
const signatureHeader = readSignatureHeader(options);
|
|
98
|
+
const timestampHeader = readTimestampHeader(options, mode, signatureHeader);
|
|
99
|
+
return { signatureHeader, timestampHeader };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Validate and snapshot the configuration. Any getter or proxy trap observed
|
|
103
|
+
* while reading the options is contained here and reported as one generic
|
|
104
|
+
* invalid-options error that never echoes the underlying exception.
|
|
105
|
+
*/
|
|
106
|
+
function snapshotConfiguration(options) {
|
|
107
|
+
try {
|
|
108
|
+
return buildConfiguration(options);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
throw new errors_js_1.HooklatchError('invalid-options', INVALID_OPTIONS_MESSAGE);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse the configured Grafana headers into the bytes Grafana signs.
|
|
116
|
+
*
|
|
117
|
+
* The signature header is always read first: its structure decides the
|
|
118
|
+
* failure before any timestamp is inspected. Freshness and the HMAC check
|
|
119
|
+
* belong to core, so this only reports the signature and the signed bytes.
|
|
120
|
+
*/
|
|
121
|
+
function parseGrafana(configuration, headers, rawBody) {
|
|
122
|
+
const signatureRaw = headers.get(configuration.signatureHeader);
|
|
123
|
+
if (signatureRaw === undefined || signatureRaw.trim() === '') {
|
|
124
|
+
return (0, shared_js_1.failure)('missing-signature', 'No Grafana signature header was provided.');
|
|
125
|
+
}
|
|
126
|
+
const signature = (0, shared_js_1.decodeHexSignature)(signatureRaw);
|
|
127
|
+
if (signature === null) {
|
|
128
|
+
return (0, shared_js_1.failure)('malformed-signature', 'The Grafana signature header is malformed.');
|
|
129
|
+
}
|
|
130
|
+
const timestampHeader = configuration.timestampHeader;
|
|
131
|
+
if (timestampHeader === null) {
|
|
132
|
+
return {
|
|
133
|
+
ok: true,
|
|
134
|
+
signatures: [signature],
|
|
135
|
+
signedContent: rawBody,
|
|
136
|
+
identity: { deliveryId: null, eventId: null, timestamp: null, authenticatedFields: [] },
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const timestampRaw = headers.get(timestampHeader);
|
|
140
|
+
if (timestampRaw === undefined || timestampRaw.trim() === '') {
|
|
141
|
+
return (0, shared_js_1.failure)('missing-timestamp', 'No Grafana timestamp header was provided.');
|
|
142
|
+
}
|
|
143
|
+
if (!(0, shared_js_1.isCanonicalTimestamp)(timestampRaw)) {
|
|
144
|
+
return (0, shared_js_1.failure)('malformed-signature', 'The Grafana timestamp is malformed.');
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
ok: true,
|
|
148
|
+
signatures: [signature],
|
|
149
|
+
signedContent: (0, bytes_js_1.concatBytes)((0, bytes_js_1.utf8)(`${timestampRaw}:`), rawBody),
|
|
150
|
+
identity: {
|
|
151
|
+
deliveryId: null,
|
|
152
|
+
eventId: null,
|
|
153
|
+
timestamp: Number(timestampRaw),
|
|
154
|
+
authenticatedFields: ['timestamp'],
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Create a Grafana descriptor for the given receiver configuration.
|
|
160
|
+
*
|
|
161
|
+
* The configuration is trusted application input, never derived from a
|
|
162
|
+
* request. Header names select which header is read; they are lookup
|
|
163
|
+
* configuration and are not part of the signed bytes, so the same secret,
|
|
164
|
+
* body and timestamp produce the same MAC under any configured header name.
|
|
165
|
+
*
|
|
166
|
+
* The returned descriptor is not registered with the public provider
|
|
167
|
+
* registry; the coordinator owns that integration.
|
|
168
|
+
*/
|
|
169
|
+
function createGrafanaDescriptor(options) {
|
|
170
|
+
const configuration = snapshotConfiguration(options);
|
|
171
|
+
return {
|
|
172
|
+
provider: 'grafana',
|
|
173
|
+
decodeSecret(secret) {
|
|
174
|
+
return (0, shared_js_1.decodeLiteralSecret)(secret, 'Grafana');
|
|
175
|
+
},
|
|
176
|
+
parse(headers, rawBody) {
|
|
177
|
+
return parseGrafana(configuration, headers, rawBody);
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProviderDescriptor } from '../internal/provider.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* Receiver configuration for the Grafana alerting webhook HMAC.
|
|
4
|
+
*
|
|
5
|
+
* `mode` selects the signed layout. `body` signs the exact raw body.
|
|
6
|
+
* `timestamped` signs `${timestamp}:` followed by the exact raw body, where
|
|
7
|
+
* the timestamp is read from the configured timestamp header. The mode is
|
|
8
|
+
* always explicit: nothing is inferred from the request, and a missing
|
|
9
|
+
* timestamp never downgrades to the body-only layout.
|
|
10
|
+
*/
|
|
11
|
+
export type GrafanaDescriptorOptions = {
|
|
12
|
+
readonly mode: 'body';
|
|
13
|
+
readonly signatureHeader?: string;
|
|
14
|
+
readonly timestampHeader?: never;
|
|
15
|
+
} | {
|
|
16
|
+
readonly mode: 'timestamped';
|
|
17
|
+
readonly signatureHeader?: string;
|
|
18
|
+
readonly timestampHeader: string;
|
|
19
|
+
};
|
|
20
|
+
type GrafanaDescriptor = {
|
|
21
|
+
readonly provider: 'grafana';
|
|
22
|
+
} & Pick<ProviderDescriptor, 'decodeSecret' | 'parse'>;
|
|
23
|
+
/**
|
|
24
|
+
* Create a Grafana descriptor for the given receiver configuration.
|
|
25
|
+
*
|
|
26
|
+
* The configuration is trusted application input, never derived from a
|
|
27
|
+
* request. Header names select which header is read; they are lookup
|
|
28
|
+
* configuration and are not part of the signed bytes, so the same secret,
|
|
29
|
+
* body and timestamp produce the same MAC under any configured header name.
|
|
30
|
+
*
|
|
31
|
+
* The returned descriptor is not registered with the public provider
|
|
32
|
+
* registry; the coordinator owns that integration.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createGrafanaDescriptor(options: GrafanaDescriptorOptions): GrafanaDescriptor;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.falDescriptor = exports.vercelDescriptor = exports.linearDescriptor = exports.sanityDescriptor = exports.dopplerDescriptor = exports.sentryDescriptor = exports.workosDescriptor = exports.replicateDescriptor = exports.gitlabDescriptor = exports.dodoPaymentsDescriptor = exports.lemonSqueezyDescriptor = exports.paddleDescriptor = exports.razorpayDescriptor = exports.svixDescriptor = exports.stripeDescriptor = exports.standardWebhooksDescriptor = exports.shopifyDescriptor = exports.githubDescriptor = exports.clerkDescriptor = exports.SUPPORTED_PROVIDERS = void 0;
|
|
4
|
+
exports.getProviderDescriptor = getProviderDescriptor;
|
|
5
|
+
const errors_js_1 = require("../errors.cjs");
|
|
6
|
+
const grafana_js_1 = require("./grafana.cjs");
|
|
7
|
+
const polar_js_1 = require("./polar.cjs");
|
|
8
|
+
const clerk_js_1 = require("./clerk.cjs");
|
|
9
|
+
Object.defineProperty(exports, "clerkDescriptor", { enumerable: true, get: function () { return clerk_js_1.clerkDescriptor; } });
|
|
10
|
+
const github_js_1 = require("./github.cjs");
|
|
11
|
+
Object.defineProperty(exports, "githubDescriptor", { enumerable: true, get: function () { return github_js_1.githubDescriptor; } });
|
|
12
|
+
const shopify_js_1 = require("./shopify.cjs");
|
|
13
|
+
Object.defineProperty(exports, "shopifyDescriptor", { enumerable: true, get: function () { return shopify_js_1.shopifyDescriptor; } });
|
|
14
|
+
const standard_webhooks_js_1 = require("./standard-webhooks.cjs");
|
|
15
|
+
Object.defineProperty(exports, "standardWebhooksDescriptor", { enumerable: true, get: function () { return standard_webhooks_js_1.standardWebhooksDescriptor; } });
|
|
16
|
+
const stripe_js_1 = require("./stripe.cjs");
|
|
17
|
+
Object.defineProperty(exports, "stripeDescriptor", { enumerable: true, get: function () { return stripe_js_1.stripeDescriptor; } });
|
|
18
|
+
const svix_js_1 = require("./svix.cjs");
|
|
19
|
+
Object.defineProperty(exports, "svixDescriptor", { enumerable: true, get: function () { return svix_js_1.svixDescriptor; } });
|
|
20
|
+
const razorpay_js_1 = require("./razorpay.cjs");
|
|
21
|
+
Object.defineProperty(exports, "razorpayDescriptor", { enumerable: true, get: function () { return razorpay_js_1.razorpayDescriptor; } });
|
|
22
|
+
const paddle_js_1 = require("./paddle.cjs");
|
|
23
|
+
Object.defineProperty(exports, "paddleDescriptor", { enumerable: true, get: function () { return paddle_js_1.paddleDescriptor; } });
|
|
24
|
+
const lemon_squeezy_js_1 = require("./lemon-squeezy.cjs");
|
|
25
|
+
Object.defineProperty(exports, "lemonSqueezyDescriptor", { enumerable: true, get: function () { return lemon_squeezy_js_1.lemonSqueezyDescriptor; } });
|
|
26
|
+
const dodo_payments_js_1 = require("./dodo-payments.cjs");
|
|
27
|
+
Object.defineProperty(exports, "dodoPaymentsDescriptor", { enumerable: true, get: function () { return dodo_payments_js_1.dodoPaymentsDescriptor; } });
|
|
28
|
+
const gitlab_js_1 = require("./gitlab.cjs");
|
|
29
|
+
Object.defineProperty(exports, "gitlabDescriptor", { enumerable: true, get: function () { return gitlab_js_1.gitlabDescriptor; } });
|
|
30
|
+
const replicate_js_1 = require("./replicate.cjs");
|
|
31
|
+
Object.defineProperty(exports, "replicateDescriptor", { enumerable: true, get: function () { return replicate_js_1.replicateDescriptor; } });
|
|
32
|
+
const workos_js_1 = require("./workos.cjs");
|
|
33
|
+
Object.defineProperty(exports, "workosDescriptor", { enumerable: true, get: function () { return workos_js_1.workosDescriptor; } });
|
|
34
|
+
const sentry_js_1 = require("./sentry.cjs");
|
|
35
|
+
Object.defineProperty(exports, "sentryDescriptor", { enumerable: true, get: function () { return sentry_js_1.sentryDescriptor; } });
|
|
36
|
+
const doppler_js_1 = require("./doppler.cjs");
|
|
37
|
+
Object.defineProperty(exports, "dopplerDescriptor", { enumerable: true, get: function () { return doppler_js_1.dopplerDescriptor; } });
|
|
38
|
+
const sanity_js_1 = require("./sanity.cjs");
|
|
39
|
+
Object.defineProperty(exports, "sanityDescriptor", { enumerable: true, get: function () { return sanity_js_1.sanityDescriptor; } });
|
|
40
|
+
const linear_js_1 = require("./linear.cjs");
|
|
41
|
+
Object.defineProperty(exports, "linearDescriptor", { enumerable: true, get: function () { return linear_js_1.linearDescriptor; } });
|
|
42
|
+
const vercel_js_1 = require("./vercel.cjs");
|
|
43
|
+
Object.defineProperty(exports, "vercelDescriptor", { enumerable: true, get: function () { return vercel_js_1.vercelDescriptor; } });
|
|
44
|
+
const fal_js_1 = require("./fal.cjs");
|
|
45
|
+
Object.defineProperty(exports, "falDescriptor", { enumerable: true, get: function () { return fal_js_1.falDescriptor; } });
|
|
46
|
+
/** Registry order is part of the internal contract; append new providers only. */
|
|
47
|
+
exports.SUPPORTED_PROVIDERS = [
|
|
48
|
+
'stripe',
|
|
49
|
+
'github',
|
|
50
|
+
'shopify',
|
|
51
|
+
'standard-webhooks',
|
|
52
|
+
'clerk',
|
|
53
|
+
'svix',
|
|
54
|
+
'razorpay',
|
|
55
|
+
'paddle',
|
|
56
|
+
'lemon-squeezy',
|
|
57
|
+
'dodo-payments',
|
|
58
|
+
'gitlab',
|
|
59
|
+
'replicate',
|
|
60
|
+
'workos',
|
|
61
|
+
'sentry',
|
|
62
|
+
'doppler',
|
|
63
|
+
'sanity',
|
|
64
|
+
'grafana',
|
|
65
|
+
'polar',
|
|
66
|
+
'linear',
|
|
67
|
+
'vercel',
|
|
68
|
+
'fal',
|
|
69
|
+
];
|
|
70
|
+
const DESCRIPTORS = {
|
|
71
|
+
stripe: stripe_js_1.stripeDescriptor,
|
|
72
|
+
github: github_js_1.githubDescriptor,
|
|
73
|
+
shopify: shopify_js_1.shopifyDescriptor,
|
|
74
|
+
'standard-webhooks': standard_webhooks_js_1.standardWebhooksDescriptor,
|
|
75
|
+
clerk: clerk_js_1.clerkDescriptor,
|
|
76
|
+
svix: svix_js_1.svixDescriptor,
|
|
77
|
+
razorpay: razorpay_js_1.razorpayDescriptor,
|
|
78
|
+
paddle: paddle_js_1.paddleDescriptor,
|
|
79
|
+
'lemon-squeezy': lemon_squeezy_js_1.lemonSqueezyDescriptor,
|
|
80
|
+
'dodo-payments': dodo_payments_js_1.dodoPaymentsDescriptor,
|
|
81
|
+
gitlab: gitlab_js_1.gitlabDescriptor,
|
|
82
|
+
replicate: replicate_js_1.replicateDescriptor,
|
|
83
|
+
workos: workos_js_1.workosDescriptor,
|
|
84
|
+
sentry: sentry_js_1.sentryDescriptor,
|
|
85
|
+
doppler: doppler_js_1.dopplerDescriptor,
|
|
86
|
+
sanity: sanity_js_1.sanityDescriptor,
|
|
87
|
+
linear: linear_js_1.linearDescriptor,
|
|
88
|
+
vercel: vercel_js_1.vercelDescriptor,
|
|
89
|
+
fal: fal_js_1.falDescriptor,
|
|
90
|
+
};
|
|
91
|
+
/** Resolve the pure descriptor for a supported provider. */
|
|
92
|
+
function getProviderDescriptor(provider, providerOptions) {
|
|
93
|
+
if (provider === 'grafana') {
|
|
94
|
+
if (providerOptions === undefined || !('mode' in providerOptions)) {
|
|
95
|
+
throw new errors_js_1.HooklatchError('invalid-options', 'Invalid provider options.');
|
|
96
|
+
}
|
|
97
|
+
return (0, grafana_js_1.createGrafanaDescriptor)(providerOptions);
|
|
98
|
+
}
|
|
99
|
+
if (provider === 'polar') {
|
|
100
|
+
if (providerOptions !== undefined && 'mode' in providerOptions) {
|
|
101
|
+
throw new errors_js_1.HooklatchError('invalid-options', 'Invalid provider options.');
|
|
102
|
+
}
|
|
103
|
+
return (0, polar_js_1.createPolarDescriptor)(providerOptions);
|
|
104
|
+
}
|
|
105
|
+
const descriptor = Object.hasOwn(DESCRIPTORS, provider) ? DESCRIPTORS[provider] : undefined;
|
|
106
|
+
if (descriptor === undefined) {
|
|
107
|
+
throw new errors_js_1.HooklatchError('unknown-provider', 'Unsupported webhook provider.');
|
|
108
|
+
}
|
|
109
|
+
return descriptor;
|
|
110
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AnyProviderDescriptor } from '../internal/provider.cjs';
|
|
2
|
+
import type { Provider, GrafanaOptions, PolarOptions } from '../types.cjs';
|
|
3
|
+
import { clerkDescriptor } from './clerk.cjs';
|
|
4
|
+
import { githubDescriptor } from './github.cjs';
|
|
5
|
+
import { shopifyDescriptor } from './shopify.cjs';
|
|
6
|
+
import { standardWebhooksDescriptor } from './standard-webhooks.cjs';
|
|
7
|
+
import { stripeDescriptor } from './stripe.cjs';
|
|
8
|
+
import { svixDescriptor } from './svix.cjs';
|
|
9
|
+
import { razorpayDescriptor } from './razorpay.cjs';
|
|
10
|
+
import { paddleDescriptor } from './paddle.cjs';
|
|
11
|
+
import { lemonSqueezyDescriptor } from './lemon-squeezy.cjs';
|
|
12
|
+
import { dodoPaymentsDescriptor } from './dodo-payments.cjs';
|
|
13
|
+
import { gitlabDescriptor } from './gitlab.cjs';
|
|
14
|
+
import { replicateDescriptor } from './replicate.cjs';
|
|
15
|
+
import { workosDescriptor } from './workos.cjs';
|
|
16
|
+
import { sentryDescriptor } from './sentry.cjs';
|
|
17
|
+
import { dopplerDescriptor } from './doppler.cjs';
|
|
18
|
+
import { sanityDescriptor } from './sanity.cjs';
|
|
19
|
+
import { linearDescriptor } from './linear.cjs';
|
|
20
|
+
import { vercelDescriptor } from './vercel.cjs';
|
|
21
|
+
import { falDescriptor } from './fal.cjs';
|
|
22
|
+
/** Registry order is part of the internal contract; append new providers only. */
|
|
23
|
+
export declare const SUPPORTED_PROVIDERS: readonly ["stripe", "github", "shopify", "standard-webhooks", "clerk", "svix", "razorpay", "paddle", "lemon-squeezy", "dodo-payments", "gitlab", "replicate", "workos", "sentry", "doppler", "sanity", "grafana", "polar", "linear", "vercel", "fal"];
|
|
24
|
+
/** Resolve the pure descriptor for a supported provider. */
|
|
25
|
+
export declare function getProviderDescriptor(provider: Provider, providerOptions?: GrafanaOptions | PolarOptions): AnyProviderDescriptor;
|
|
26
|
+
export { clerkDescriptor, githubDescriptor, shopifyDescriptor, standardWebhooksDescriptor, stripeDescriptor, svixDescriptor, razorpayDescriptor, paddleDescriptor, lemonSqueezyDescriptor, dodoPaymentsDescriptor, gitlabDescriptor, replicateDescriptor, workosDescriptor, sentryDescriptor, dopplerDescriptor, sanityDescriptor, linearDescriptor, vercelDescriptor, falDescriptor, };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.lemonSqueezyDescriptor = void 0;
|
|
4
|
+
const shared_js_1 = require("./shared.cjs");
|
|
5
|
+
const SIGNATURE_HEADER = 'x-signature';
|
|
6
|
+
/**
|
|
7
|
+
* Lemon Squeezy `X-Signature`: a single 64-character hex HMAC-SHA256 digest of
|
|
8
|
+
* the exact raw body, keyed with the literal webhook signing secret. The docs
|
|
9
|
+
* suggest 6-40 character secrets, but that UI guidance is not enforced as a
|
|
10
|
+
* cryptographic limit. No timestamp or event identifier is documented for
|
|
11
|
+
* verification, so identity stays null and unsigned (`X-Event-Name` is
|
|
12
|
+
* metadata and is not interpreted).
|
|
13
|
+
* Source: https://docs.lemonsqueezy.com/help/webhooks/signing-requests
|
|
14
|
+
*/
|
|
15
|
+
exports.lemonSqueezyDescriptor = {
|
|
16
|
+
provider: 'lemon-squeezy',
|
|
17
|
+
decodeSecret(secret) {
|
|
18
|
+
return (0, shared_js_1.decodeLiteralSecret)(secret, 'Lemon Squeezy');
|
|
19
|
+
},
|
|
20
|
+
parse(headers, rawBody) {
|
|
21
|
+
const raw = headers.get(SIGNATURE_HEADER);
|
|
22
|
+
if (raw === undefined || raw.trim() === '') {
|
|
23
|
+
return (0, shared_js_1.failure)('missing-signature', 'No Lemon Squeezy signature header was provided.');
|
|
24
|
+
}
|
|
25
|
+
const signature = (0, shared_js_1.decodeHexSignature)(raw);
|
|
26
|
+
if (signature === null) {
|
|
27
|
+
return (0, shared_js_1.failure)('malformed-signature', 'The Lemon Squeezy signature header is malformed.');
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
ok: true,
|
|
31
|
+
signatures: [signature],
|
|
32
|
+
signedContent: rawBody,
|
|
33
|
+
identity: { deliveryId: null, eventId: null, timestamp: null, authenticatedFields: [] },
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { NormalizedHeaders, ParseResult } from '../internal/provider.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* Lemon Squeezy `X-Signature`: a single 64-character hex HMAC-SHA256 digest of
|
|
4
|
+
* the exact raw body, keyed with the literal webhook signing secret. The docs
|
|
5
|
+
* suggest 6-40 character secrets, but that UI guidance is not enforced as a
|
|
6
|
+
* cryptographic limit. No timestamp or event identifier is documented for
|
|
7
|
+
* verification, so identity stays null and unsigned (`X-Event-Name` is
|
|
8
|
+
* metadata and is not interpreted).
|
|
9
|
+
* Source: https://docs.lemonsqueezy.com/help/webhooks/signing-requests
|
|
10
|
+
*/
|
|
11
|
+
export declare const lemonSqueezyDescriptor: {
|
|
12
|
+
provider: "lemon-squeezy";
|
|
13
|
+
decodeSecret(secret: string): Uint8Array;
|
|
14
|
+
parse(headers: NormalizedHeaders, rawBody: Uint8Array): ParseResult;
|
|
15
|
+
};
|