@zap-studio/webhooks 0.1.3 → 0.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @zap-studio/webhooks
2
2
 
3
+ ## 0.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - e26293e: Updated dependencies.
8
+ - @zap-studio/validation@0.3.2
9
+
3
10
  ## 0.1.3
4
11
 
5
12
  ### Patch Changes
package/bin/intent.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // Auto-generated by @tanstack/intent setup
3
+ // Exposes the intent end-user CLI for consumers of this library.
4
+ await import("@tanstack/intent/intent-library");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zap-studio/webhooks",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -33,11 +33,14 @@
33
33
  "dist",
34
34
  "CHANGELOG.md",
35
35
  "LICENSE",
36
- "README.md"
36
+ "README.md",
37
+ "skills",
38
+ "bin",
39
+ "!skills/_artifacts"
37
40
  ],
38
41
  "dependencies": {
39
42
  "@standard-schema/spec": "^1.1.0",
40
- "@zap-studio/validation": "0.3.1"
43
+ "@zap-studio/validation": "0.3.2"
41
44
  },
42
45
  "devDependencies": {
43
46
  "@types/node": "^25.0.2",
@@ -46,9 +49,9 @@
46
49
  "typescript": "^5.9.3",
47
50
  "vitest": "^4.0.18",
48
51
  "zod": "^4.2.0",
49
- "@zap-studio/tsdown-config": "0.0.0",
52
+ "@zap-studio/typescript-config": "0.0.0",
50
53
  "@zap-studio/vitest-config": "0.0.0",
51
- "@zap-studio/typescript-config": "0.0.0"
54
+ "@zap-studio/tsdown-config": "0.0.0"
52
55
  },
53
56
  "exports": {
54
57
  ".": "./dist/index.mjs",
@@ -61,6 +64,9 @@
61
64
  "main": "./dist/index.mjs",
62
65
  "module": "./dist/index.mjs",
63
66
  "types": "./dist/index.d.mts",
67
+ "bin": {
68
+ "intent": "./bin/intent.js"
69
+ },
64
70
  "scripts": {
65
71
  "build": "tsdown --config tsdown.config.ts",
66
72
  "typecheck": "tsc --noEmit",
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: zap-webhooks-routing-and-verification
3
+ description: >
4
+ Build webhook ingestion with @zap-studio/webhooks using createWebhookRouter,
5
+ register path keys, prefix normalization, schema validation, lifecycle hooks,
6
+ createHmacVerifier, and BaseAdapter request/response mapping.
7
+ type: core
8
+ library: '@zap-studio/webhooks'
9
+ library_version: '0.1.3'
10
+ sources:
11
+ - 'zap-studio/monorepo:packages/webhooks/README.md'
12
+ - 'zap-studio/monorepo:packages/webhooks/src/index.ts'
13
+ - 'zap-studio/monorepo:packages/webhooks/src/verify.ts'
14
+ - 'zap-studio/monorepo:packages/webhooks/src/adapters/base.ts'
15
+ ---
16
+
17
+ # @zap-studio/webhooks — Routing and Verification
18
+
19
+ ## Setup
20
+
21
+ ```ts
22
+ import { createWebhookRouter } from '@zap-studio/webhooks';
23
+ import { createHmacVerifier } from '@zap-studio/webhooks/verify';
24
+ import { z } from 'zod';
25
+
26
+ const router = createWebhookRouter({
27
+ prefix: '/webhooks/',
28
+ verify: createHmacVerifier({
29
+ headerName: 'x-hub-signature-256',
30
+ secret: process.env.WEBHOOK_SECRET!,
31
+ }),
32
+ });
33
+
34
+ router.register('github/push', {
35
+ schema: z.object({ ref: z.string() }),
36
+ handler: async ({ payload, ack }) => {
37
+ console.log(payload.ref);
38
+ return ack({ status: 200, body: 'ok' });
39
+ },
40
+ });
41
+ ```
42
+
43
+ ## Core Patterns
44
+
45
+ ### Add global hooks for observability and error shaping
46
+
47
+ ```ts
48
+ const router = createWebhookRouter({
49
+ before: (req) => {
50
+ console.log('incoming', req.path);
51
+ },
52
+ after: (_req, res) => {
53
+ console.log('status', res.status);
54
+ },
55
+ onError: (error) => ({
56
+ status: 500,
57
+ body: { error: error.message },
58
+ }),
59
+ });
60
+ ```
61
+
62
+ ### Register route-specific hooks
63
+
64
+ ```ts
65
+ router.register('payments/succeeded', {
66
+ schema: PaymentSchema,
67
+ before: (req) => {
68
+ req.headers.set('x-processed', '1');
69
+ },
70
+ after: (_req, res) => {
71
+ console.log('finished', res.status);
72
+ },
73
+ handler: async ({ payload, ack }) => ack({ body: { id: payload.id } }),
74
+ });
75
+ ```
76
+
77
+ ### Implement an adapter with `BaseAdapter`
78
+
79
+ ```ts
80
+ import { BaseAdapter } from '@zap-studio/webhooks/adapters/base';
81
+
82
+ class MyAdapter extends BaseAdapter {
83
+ async toNormalizedRequest(req: Request) {
84
+ return {
85
+ method: req.method,
86
+ path: req.url,
87
+ headers: req.headers,
88
+ rawBody: Buffer.from(await req.text()),
89
+ };
90
+ }
91
+
92
+ async toFrameworkResponse(res: Response, normalized) {
93
+ return new Response(JSON.stringify(normalized.body), {
94
+ status: normalized.status,
95
+ headers: normalized.headers,
96
+ }) as unknown as Response;
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Common Mistakes
102
+
103
+ ### HIGH Registering paths with leading slash
104
+
105
+ Wrong:
106
+
107
+ ```ts
108
+ router.register('/github/push', {
109
+ schema: PushSchema,
110
+ handler,
111
+ });
112
+ ```
113
+
114
+ Correct:
115
+
116
+ ```ts
117
+ router.register('github/push', {
118
+ schema: PushSchema,
119
+ handler,
120
+ });
121
+ ```
122
+
123
+ Incoming paths normalize to slashless keys; leading slash route keys do not match and return 404.
124
+
125
+ Source: zap-studio/monorepo:packages/webhooks/src/index.ts
126
+
127
+ ### CRITICAL Verifying a transformed payload instead of raw body
128
+
129
+ Wrong:
130
+
131
+ ```ts
132
+ const parsed = JSON.parse(req.rawBody.toString());
133
+ await verifyProvider(JSON.stringify(parsed));
134
+ ```
135
+
136
+ Correct:
137
+
138
+ ```ts
139
+ await verify(req); // uses req.rawBody bytes
140
+ const parsed = JSON.parse(req.rawBody.toString());
141
+ ```
142
+
143
+ Signature checks must run on exact raw bytes; any parse/serialize transformation can invalidate signatures.
144
+
145
+ Source: zap-studio/monorepo:packages/webhooks/src/verify.ts
146
+
147
+ ### HIGH Using Node HMAC verifier in non-Node runtime
148
+
149
+ Wrong:
150
+
151
+ ```ts
152
+ const verify = createHmacVerifier({
153
+ headerName: 'x-signature',
154
+ secret: env.WEBHOOK_SECRET,
155
+ });
156
+ // used in edge runtime
157
+ ```
158
+
159
+ Correct:
160
+
161
+ ```ts
162
+ const verify = async (req) => {
163
+ // implement provider verification with Web Crypto in edge runtimes
164
+ };
165
+ ```
166
+
167
+ `createHmacVerifier` imports `node:crypto` and is intended for Node-compatible runtimes.
168
+
169
+ Source: zap-studio/monorepo:packages/webhooks/src/verify.ts
170
+
171
+ See also: zap-validation-standard-schema/SKILL.md — payload validation result handling.