@orgloop/connector-webhook 0.1.7 → 0.1.9
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/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orgloop/connector-webhook",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "OrgLoop generic webhook connector — inbound and outbound",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@orgloop/sdk": "0.1.
|
|
9
|
+
"@orgloop/sdk": "0.1.9"
|
|
10
10
|
},
|
|
11
11
|
"orgloop": {
|
|
12
12
|
"type": "connector",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/webhook.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,567 +0,0 @@
|
|
|
1
|
-
import { createHmac } from 'node:crypto';
|
|
2
|
-
import { EventEmitter } from 'node:events';
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { tmpdir } from 'node:os';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { WebhookSource } from '../source.js';
|
|
8
|
-
import { WebhookTarget } from '../target.js';
|
|
9
|
-
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
10
|
-
function createMockRequest(body, method = 'POST', headers = {}) {
|
|
11
|
-
const req = new EventEmitter();
|
|
12
|
-
req.method = method;
|
|
13
|
-
req.headers = headers;
|
|
14
|
-
setTimeout(() => {
|
|
15
|
-
req.emit('data', Buffer.from(body));
|
|
16
|
-
req.emit('end');
|
|
17
|
-
}, 0);
|
|
18
|
-
return req;
|
|
19
|
-
}
|
|
20
|
-
function createMockResponse() {
|
|
21
|
-
const res = {
|
|
22
|
-
statusCode: 200,
|
|
23
|
-
body: '',
|
|
24
|
-
writeHead(code, _headers) {
|
|
25
|
-
res.statusCode = code;
|
|
26
|
-
return res;
|
|
27
|
-
},
|
|
28
|
-
end(data) {
|
|
29
|
-
res.body = data ?? '';
|
|
30
|
-
return res;
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
return res;
|
|
34
|
-
}
|
|
35
|
-
function signPayload(body, secret) {
|
|
36
|
-
return `sha256=${createHmac('sha256', secret).update(body).digest('hex')}`;
|
|
37
|
-
}
|
|
38
|
-
// ─── WebhookSource ────────────────────────────────────────────────────────────
|
|
39
|
-
describe('WebhookSource', () => {
|
|
40
|
-
it('initializes and returns empty poll', async () => {
|
|
41
|
-
const source = new WebhookSource();
|
|
42
|
-
await source.init({
|
|
43
|
-
id: 'webhook',
|
|
44
|
-
connector: '@orgloop/connector-webhook',
|
|
45
|
-
config: { path: '/webhook' },
|
|
46
|
-
});
|
|
47
|
-
const result = await source.poll(null);
|
|
48
|
-
expect(result.events).toHaveLength(0);
|
|
49
|
-
});
|
|
50
|
-
it('receives webhook and normalizes to OrgLoop event', async () => {
|
|
51
|
-
const source = new WebhookSource();
|
|
52
|
-
await source.init({ id: 'webhook', connector: '@orgloop/connector-webhook', config: {} });
|
|
53
|
-
const handler = source.webhook();
|
|
54
|
-
const payload = { type: 'deployment', repo: 'my-app', status: 'success' };
|
|
55
|
-
const req = createMockRequest(JSON.stringify(payload));
|
|
56
|
-
const res = createMockResponse();
|
|
57
|
-
const events = await handler(req, res);
|
|
58
|
-
expect(res.statusCode).toBe(200);
|
|
59
|
-
expect(events).toHaveLength(1);
|
|
60
|
-
expect(events[0].type).toBe('resource.changed');
|
|
61
|
-
expect(events[0].source).toBe('webhook');
|
|
62
|
-
expect(events[0].provenance.platform).toBe('webhook');
|
|
63
|
-
expect(events[0].provenance.platform_event).toBe('deployment');
|
|
64
|
-
expect(events[0].payload).toEqual(payload);
|
|
65
|
-
// Drain via poll
|
|
66
|
-
const result = await source.poll(null);
|
|
67
|
-
expect(result.events).toHaveLength(1);
|
|
68
|
-
});
|
|
69
|
-
it('rejects non-POST', async () => {
|
|
70
|
-
const source = new WebhookSource();
|
|
71
|
-
await source.init({ id: 'webhook', connector: '@orgloop/connector-webhook', config: {} });
|
|
72
|
-
const handler = source.webhook();
|
|
73
|
-
const req = createMockRequest('', 'GET');
|
|
74
|
-
const res = createMockResponse();
|
|
75
|
-
const events = await handler(req, res);
|
|
76
|
-
expect(res.statusCode).toBe(405);
|
|
77
|
-
expect(events).toHaveLength(0);
|
|
78
|
-
});
|
|
79
|
-
it('rejects invalid JSON', async () => {
|
|
80
|
-
const source = new WebhookSource();
|
|
81
|
-
await source.init({ id: 'webhook', connector: '@orgloop/connector-webhook', config: {} });
|
|
82
|
-
const handler = source.webhook();
|
|
83
|
-
const req = createMockRequest('{invalid');
|
|
84
|
-
const res = createMockResponse();
|
|
85
|
-
const events = await handler(req, res);
|
|
86
|
-
expect(res.statusCode).toBe(400);
|
|
87
|
-
expect(events).toHaveLength(0);
|
|
88
|
-
});
|
|
89
|
-
it('clears pending events on shutdown', async () => {
|
|
90
|
-
const source = new WebhookSource();
|
|
91
|
-
await source.init({ id: 'webhook', connector: '@orgloop/connector-webhook', config: {} });
|
|
92
|
-
const handler = source.webhook();
|
|
93
|
-
const req = createMockRequest(JSON.stringify({ test: true }));
|
|
94
|
-
const res = createMockResponse();
|
|
95
|
-
await handler(req, res);
|
|
96
|
-
await source.shutdown();
|
|
97
|
-
const result = await source.poll(null);
|
|
98
|
-
expect(result.events).toHaveLength(0);
|
|
99
|
-
});
|
|
100
|
-
// ─── HMAC Validation ────────────────────────────────────────────────────
|
|
101
|
-
describe('HMAC validation', () => {
|
|
102
|
-
const SECRET = 'test-webhook-secret';
|
|
103
|
-
it('accepts valid HMAC-SHA256 signature via x-hub-signature-256', async () => {
|
|
104
|
-
const source = new WebhookSource();
|
|
105
|
-
await source.init({
|
|
106
|
-
id: 'webhook',
|
|
107
|
-
connector: '@orgloop/connector-webhook',
|
|
108
|
-
config: { secret: SECRET },
|
|
109
|
-
});
|
|
110
|
-
const handler = source.webhook();
|
|
111
|
-
const body = JSON.stringify({ type: 'push', ref: 'refs/heads/main' });
|
|
112
|
-
const signature = signPayload(body, SECRET);
|
|
113
|
-
const req = createMockRequest(body, 'POST', { 'x-hub-signature-256': signature });
|
|
114
|
-
const res = createMockResponse();
|
|
115
|
-
const events = await handler(req, res);
|
|
116
|
-
expect(res.statusCode).toBe(200);
|
|
117
|
-
expect(events).toHaveLength(1);
|
|
118
|
-
expect(events[0].provenance.platform_event).toBe('push');
|
|
119
|
-
});
|
|
120
|
-
it('accepts valid HMAC-SHA256 signature via x-signature header', async () => {
|
|
121
|
-
const source = new WebhookSource();
|
|
122
|
-
await source.init({
|
|
123
|
-
id: 'webhook',
|
|
124
|
-
connector: '@orgloop/connector-webhook',
|
|
125
|
-
config: { secret: SECRET },
|
|
126
|
-
});
|
|
127
|
-
const handler = source.webhook();
|
|
128
|
-
const body = JSON.stringify({ type: 'deploy', env: 'prod' });
|
|
129
|
-
const signature = signPayload(body, SECRET);
|
|
130
|
-
const req = createMockRequest(body, 'POST', { 'x-signature': signature });
|
|
131
|
-
const res = createMockResponse();
|
|
132
|
-
const events = await handler(req, res);
|
|
133
|
-
expect(res.statusCode).toBe(200);
|
|
134
|
-
expect(events).toHaveLength(1);
|
|
135
|
-
});
|
|
136
|
-
it('rejects invalid signature with 401', async () => {
|
|
137
|
-
const source = new WebhookSource();
|
|
138
|
-
await source.init({
|
|
139
|
-
id: 'webhook',
|
|
140
|
-
connector: '@orgloop/connector-webhook',
|
|
141
|
-
config: { secret: SECRET },
|
|
142
|
-
});
|
|
143
|
-
const handler = source.webhook();
|
|
144
|
-
const body = JSON.stringify({ type: 'push' });
|
|
145
|
-
const req = createMockRequest(body, 'POST', {
|
|
146
|
-
'x-hub-signature-256': 'sha256=invalid_signature_value',
|
|
147
|
-
});
|
|
148
|
-
const res = createMockResponse();
|
|
149
|
-
const events = await handler(req, res);
|
|
150
|
-
expect(res.statusCode).toBe(401);
|
|
151
|
-
expect(events).toHaveLength(0);
|
|
152
|
-
expect(JSON.parse(res.body).error).toBe('Invalid signature');
|
|
153
|
-
});
|
|
154
|
-
it('rejects missing signature when secret is configured with 401', async () => {
|
|
155
|
-
const source = new WebhookSource();
|
|
156
|
-
await source.init({
|
|
157
|
-
id: 'webhook',
|
|
158
|
-
connector: '@orgloop/connector-webhook',
|
|
159
|
-
config: { secret: SECRET },
|
|
160
|
-
});
|
|
161
|
-
const handler = source.webhook();
|
|
162
|
-
const body = JSON.stringify({ type: 'push' });
|
|
163
|
-
const req = createMockRequest(body, 'POST');
|
|
164
|
-
const res = createMockResponse();
|
|
165
|
-
const events = await handler(req, res);
|
|
166
|
-
expect(res.statusCode).toBe(401);
|
|
167
|
-
expect(events).toHaveLength(0);
|
|
168
|
-
expect(JSON.parse(res.body).error).toBe('Missing signature');
|
|
169
|
-
});
|
|
170
|
-
it('accepts all requests when no secret is configured', async () => {
|
|
171
|
-
const source = new WebhookSource();
|
|
172
|
-
await source.init({
|
|
173
|
-
id: 'webhook',
|
|
174
|
-
connector: '@orgloop/connector-webhook',
|
|
175
|
-
config: {},
|
|
176
|
-
});
|
|
177
|
-
const handler = source.webhook();
|
|
178
|
-
const body = JSON.stringify({ type: 'anything' });
|
|
179
|
-
const req = createMockRequest(body, 'POST');
|
|
180
|
-
const res = createMockResponse();
|
|
181
|
-
const events = await handler(req, res);
|
|
182
|
-
expect(res.statusCode).toBe(200);
|
|
183
|
-
expect(events).toHaveLength(1);
|
|
184
|
-
});
|
|
185
|
-
it('prefers x-hub-signature-256 over x-signature', async () => {
|
|
186
|
-
const source = new WebhookSource();
|
|
187
|
-
await source.init({
|
|
188
|
-
id: 'webhook',
|
|
189
|
-
connector: '@orgloop/connector-webhook',
|
|
190
|
-
config: { secret: SECRET },
|
|
191
|
-
});
|
|
192
|
-
const handler = source.webhook();
|
|
193
|
-
const body = JSON.stringify({ type: 'push' });
|
|
194
|
-
const validSig = signPayload(body, SECRET);
|
|
195
|
-
const req = createMockRequest(body, 'POST', {
|
|
196
|
-
'x-hub-signature-256': validSig,
|
|
197
|
-
'x-signature': 'sha256=wrong',
|
|
198
|
-
});
|
|
199
|
-
const res = createMockResponse();
|
|
200
|
-
const events = await handler(req, res);
|
|
201
|
-
// Should succeed because x-hub-signature-256 is valid (checked first)
|
|
202
|
-
expect(res.statusCode).toBe(200);
|
|
203
|
-
expect(events).toHaveLength(1);
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
// ─── Buffer Persistence ─────────────────────────────────────────────────
|
|
207
|
-
describe('buffer persistence', () => {
|
|
208
|
-
const bufferDir = join(tmpdir(), `webhook-test-${Date.now()}`);
|
|
209
|
-
afterEach(() => {
|
|
210
|
-
if (existsSync(bufferDir)) {
|
|
211
|
-
rmSync(bufferDir, { recursive: true });
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
it('persists events to JSONL file', async () => {
|
|
215
|
-
const source = new WebhookSource();
|
|
216
|
-
await source.init({
|
|
217
|
-
id: 'test-src',
|
|
218
|
-
connector: '@orgloop/connector-webhook',
|
|
219
|
-
config: { buffer_dir: bufferDir },
|
|
220
|
-
});
|
|
221
|
-
const handler = source.webhook();
|
|
222
|
-
const body = JSON.stringify({ type: 'deploy' });
|
|
223
|
-
const req = createMockRequest(body);
|
|
224
|
-
const res = createMockResponse();
|
|
225
|
-
await handler(req, res);
|
|
226
|
-
expect(res.statusCode).toBe(200);
|
|
227
|
-
// Verify the file exists with content
|
|
228
|
-
const bufferPath = join(bufferDir, 'webhook-test-src.jsonl');
|
|
229
|
-
expect(existsSync(bufferPath)).toBe(true);
|
|
230
|
-
const content = readFileSync(bufferPath, 'utf-8').trim();
|
|
231
|
-
const lines = content.split('\n');
|
|
232
|
-
expect(lines).toHaveLength(1);
|
|
233
|
-
const event = JSON.parse(lines[0]);
|
|
234
|
-
expect(event.type).toBe('resource.changed');
|
|
235
|
-
});
|
|
236
|
-
it('drains buffer on poll and truncates file', async () => {
|
|
237
|
-
const source = new WebhookSource();
|
|
238
|
-
await source.init({
|
|
239
|
-
id: 'test-src',
|
|
240
|
-
connector: '@orgloop/connector-webhook',
|
|
241
|
-
config: { buffer_dir: bufferDir },
|
|
242
|
-
});
|
|
243
|
-
const handler = source.webhook();
|
|
244
|
-
// Send two webhooks
|
|
245
|
-
for (let i = 0; i < 2; i++) {
|
|
246
|
-
const body = JSON.stringify({ type: 'event', index: i });
|
|
247
|
-
const req = createMockRequest(body);
|
|
248
|
-
const res = createMockResponse();
|
|
249
|
-
await handler(req, res);
|
|
250
|
-
}
|
|
251
|
-
// Poll should return both events
|
|
252
|
-
const result = await source.poll(null);
|
|
253
|
-
expect(result.events).toHaveLength(2);
|
|
254
|
-
// Buffer file should be empty after poll
|
|
255
|
-
const bufferPath = join(bufferDir, 'webhook-test-src.jsonl');
|
|
256
|
-
const content = readFileSync(bufferPath, 'utf-8');
|
|
257
|
-
expect(content).toBe('');
|
|
258
|
-
// Next poll should return zero events
|
|
259
|
-
const result2 = await source.poll(null);
|
|
260
|
-
expect(result2.events).toHaveLength(0);
|
|
261
|
-
});
|
|
262
|
-
it('creates buffer directory if it does not exist', async () => {
|
|
263
|
-
const nestedDir = join(bufferDir, 'nested', 'dir');
|
|
264
|
-
const source = new WebhookSource();
|
|
265
|
-
await source.init({
|
|
266
|
-
id: 'test-src',
|
|
267
|
-
connector: '@orgloop/connector-webhook',
|
|
268
|
-
config: { buffer_dir: nestedDir },
|
|
269
|
-
});
|
|
270
|
-
expect(existsSync(nestedDir)).toBe(true);
|
|
271
|
-
});
|
|
272
|
-
it('survives simulated restart by reading existing buffer', async () => {
|
|
273
|
-
// Create buffer directory and write events directly
|
|
274
|
-
mkdirSync(bufferDir, { recursive: true });
|
|
275
|
-
const bufferPath = join(bufferDir, 'webhook-persist.jsonl');
|
|
276
|
-
const fakeEvent = {
|
|
277
|
-
id: 'evt_test123',
|
|
278
|
-
timestamp: new Date().toISOString(),
|
|
279
|
-
source: 'webhook',
|
|
280
|
-
type: 'resource.changed',
|
|
281
|
-
provenance: { platform: 'webhook' },
|
|
282
|
-
payload: { survived: true },
|
|
283
|
-
};
|
|
284
|
-
writeFileSync(bufferPath, `${JSON.stringify(fakeEvent)}\n`);
|
|
285
|
-
// Init source — should pick up the pre-existing buffer
|
|
286
|
-
const source = new WebhookSource();
|
|
287
|
-
await source.init({
|
|
288
|
-
id: 'persist',
|
|
289
|
-
connector: '@orgloop/connector-webhook',
|
|
290
|
-
config: { buffer_dir: bufferDir },
|
|
291
|
-
});
|
|
292
|
-
const result = await source.poll(null);
|
|
293
|
-
expect(result.events).toHaveLength(1);
|
|
294
|
-
expect(result.events[0].payload).toEqual({ survived: true });
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
// ─── WebhookTarget ────────────────────────────────────────────────────────────
|
|
299
|
-
describe('WebhookTarget', () => {
|
|
300
|
-
let fetchMock;
|
|
301
|
-
beforeEach(() => {
|
|
302
|
-
fetchMock = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: 'OK' });
|
|
303
|
-
vi.stubGlobal('fetch', fetchMock);
|
|
304
|
-
});
|
|
305
|
-
afterEach(() => {
|
|
306
|
-
vi.restoreAllMocks();
|
|
307
|
-
});
|
|
308
|
-
it('delivers event to configured URL', async () => {
|
|
309
|
-
const target = new WebhookTarget();
|
|
310
|
-
await target.init({
|
|
311
|
-
id: 'webhook-target',
|
|
312
|
-
connector: '@orgloop/connector-webhook',
|
|
313
|
-
config: { url: 'https://example.com/hook' },
|
|
314
|
-
});
|
|
315
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
316
|
-
const event = createTestEvent();
|
|
317
|
-
const result = await target.deliver(event, {});
|
|
318
|
-
expect(result.status).toBe('delivered');
|
|
319
|
-
expect(fetchMock).toHaveBeenCalledOnce();
|
|
320
|
-
const [url] = fetchMock.mock.calls[0];
|
|
321
|
-
expect(url).toBe('https://example.com/hook');
|
|
322
|
-
});
|
|
323
|
-
it('sends event and launch_prompt in body', async () => {
|
|
324
|
-
const target = new WebhookTarget();
|
|
325
|
-
await target.init({
|
|
326
|
-
id: 'webhook-target',
|
|
327
|
-
connector: '@orgloop/connector-webhook',
|
|
328
|
-
config: { url: 'https://example.com/hook' },
|
|
329
|
-
});
|
|
330
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
331
|
-
const event = createTestEvent();
|
|
332
|
-
await target.deliver(event, { launch_prompt: 'Do the thing' });
|
|
333
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
334
|
-
expect(body.event.id).toBe(event.id);
|
|
335
|
-
expect(body.launch_prompt).toBe('Do the thing');
|
|
336
|
-
});
|
|
337
|
-
it('handles 429 rate limit', async () => {
|
|
338
|
-
fetchMock.mockResolvedValueOnce({ ok: false, status: 429, statusText: 'Too Many Requests' });
|
|
339
|
-
const target = new WebhookTarget();
|
|
340
|
-
await target.init({
|
|
341
|
-
id: 'webhook-target',
|
|
342
|
-
connector: '@orgloop/connector-webhook',
|
|
343
|
-
config: { url: 'https://example.com/hook' },
|
|
344
|
-
});
|
|
345
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
346
|
-
const result = await target.deliver(createTestEvent(), {});
|
|
347
|
-
expect(result.status).toBe('error');
|
|
348
|
-
expect(result.error?.message).toContain('429');
|
|
349
|
-
});
|
|
350
|
-
it('handles 4xx rejection', async () => {
|
|
351
|
-
fetchMock.mockResolvedValueOnce({ ok: false, status: 422, statusText: 'Unprocessable Entity' });
|
|
352
|
-
const target = new WebhookTarget();
|
|
353
|
-
await target.init({
|
|
354
|
-
id: 'webhook-target',
|
|
355
|
-
connector: '@orgloop/connector-webhook',
|
|
356
|
-
config: { url: 'https://example.com/hook' },
|
|
357
|
-
});
|
|
358
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
359
|
-
const result = await target.deliver(createTestEvent(), {});
|
|
360
|
-
expect(result.status).toBe('rejected');
|
|
361
|
-
});
|
|
362
|
-
it('handles network error', async () => {
|
|
363
|
-
fetchMock.mockRejectedValueOnce(new Error('ECONNREFUSED'));
|
|
364
|
-
const target = new WebhookTarget();
|
|
365
|
-
await target.init({
|
|
366
|
-
id: 'webhook-target',
|
|
367
|
-
connector: '@orgloop/connector-webhook',
|
|
368
|
-
config: { url: 'https://example.com/hook' },
|
|
369
|
-
});
|
|
370
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
371
|
-
const result = await target.deliver(createTestEvent(), {});
|
|
372
|
-
expect(result.status).toBe('error');
|
|
373
|
-
expect(result.error?.message).toContain('ECONNREFUSED');
|
|
374
|
-
});
|
|
375
|
-
// ─── Auth Tests ─────────────────────────────────────────────────────────
|
|
376
|
-
describe('authentication', () => {
|
|
377
|
-
it('sends Bearer token in Authorization header', async () => {
|
|
378
|
-
const target = new WebhookTarget();
|
|
379
|
-
await target.init({
|
|
380
|
-
id: 'webhook-target',
|
|
381
|
-
connector: '@orgloop/connector-webhook',
|
|
382
|
-
config: {
|
|
383
|
-
url: 'https://example.com/hook',
|
|
384
|
-
auth: { type: 'bearer', token: 'my-secret-token' },
|
|
385
|
-
},
|
|
386
|
-
});
|
|
387
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
388
|
-
await target.deliver(createTestEvent(), {});
|
|
389
|
-
const opts = fetchMock.mock.calls[0][1];
|
|
390
|
-
expect(opts.headers.Authorization).toBe('Bearer my-secret-token');
|
|
391
|
-
});
|
|
392
|
-
it('sends Basic auth with base64-encoded credentials', async () => {
|
|
393
|
-
const target = new WebhookTarget();
|
|
394
|
-
await target.init({
|
|
395
|
-
id: 'webhook-target',
|
|
396
|
-
connector: '@orgloop/connector-webhook',
|
|
397
|
-
config: {
|
|
398
|
-
url: 'https://example.com/hook',
|
|
399
|
-
auth: { type: 'basic', username: 'alice', password: 'secret123' },
|
|
400
|
-
},
|
|
401
|
-
});
|
|
402
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
403
|
-
await target.deliver(createTestEvent(), {});
|
|
404
|
-
const opts = fetchMock.mock.calls[0][1];
|
|
405
|
-
const expected = `Basic ${Buffer.from('alice:secret123').toString('base64')}`;
|
|
406
|
-
expect(opts.headers.Authorization).toBe(expected);
|
|
407
|
-
});
|
|
408
|
-
it('sends no Authorization header when no auth configured', async () => {
|
|
409
|
-
const target = new WebhookTarget();
|
|
410
|
-
await target.init({
|
|
411
|
-
id: 'webhook-target',
|
|
412
|
-
connector: '@orgloop/connector-webhook',
|
|
413
|
-
config: { url: 'https://example.com/hook' },
|
|
414
|
-
});
|
|
415
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
416
|
-
await target.deliver(createTestEvent(), {});
|
|
417
|
-
const opts = fetchMock.mock.calls[0][1];
|
|
418
|
-
expect(opts.headers.Authorization).toBeUndefined();
|
|
419
|
-
});
|
|
420
|
-
it('passes custom headers through', async () => {
|
|
421
|
-
const target = new WebhookTarget();
|
|
422
|
-
await target.init({
|
|
423
|
-
id: 'webhook-target',
|
|
424
|
-
connector: '@orgloop/connector-webhook',
|
|
425
|
-
config: {
|
|
426
|
-
url: 'https://example.com/hook',
|
|
427
|
-
headers: { 'X-Custom-Header': 'custom-value', 'X-Request-Id': 'req-123' },
|
|
428
|
-
},
|
|
429
|
-
});
|
|
430
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
431
|
-
await target.deliver(createTestEvent(), {});
|
|
432
|
-
const opts = fetchMock.mock.calls[0][1];
|
|
433
|
-
expect(opts.headers['X-Custom-Header']).toBe('custom-value');
|
|
434
|
-
expect(opts.headers['X-Request-Id']).toBe('req-123');
|
|
435
|
-
expect(opts.headers['Content-Type']).toBe('application/json');
|
|
436
|
-
});
|
|
437
|
-
});
|
|
438
|
-
// ─── Body Template Tests ────────────────────────────────────────────────
|
|
439
|
-
describe('body template', () => {
|
|
440
|
-
it('falls back to default body when no template configured', async () => {
|
|
441
|
-
const target = new WebhookTarget();
|
|
442
|
-
await target.init({
|
|
443
|
-
id: 'webhook-target',
|
|
444
|
-
connector: '@orgloop/connector-webhook',
|
|
445
|
-
config: { url: 'https://example.com/hook' },
|
|
446
|
-
});
|
|
447
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
448
|
-
const event = createTestEvent();
|
|
449
|
-
await target.deliver(event, { launch_prompt: 'Do something' });
|
|
450
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
451
|
-
expect(body.event.id).toBe(event.id);
|
|
452
|
-
expect(body.launch_prompt).toBe('Do something');
|
|
453
|
-
});
|
|
454
|
-
it('expands simple template with event fields', async () => {
|
|
455
|
-
const target = new WebhookTarget();
|
|
456
|
-
await target.init({
|
|
457
|
-
id: 'webhook-target',
|
|
458
|
-
connector: '@orgloop/connector-webhook',
|
|
459
|
-
config: {
|
|
460
|
-
url: 'https://hooks.slack.com/test',
|
|
461
|
-
body_template: {
|
|
462
|
-
text: '{{ event.provenance.platform_event }} by {{ event.provenance.author }}',
|
|
463
|
-
channel: '#engineering',
|
|
464
|
-
},
|
|
465
|
-
},
|
|
466
|
-
});
|
|
467
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
468
|
-
const event = createTestEvent({
|
|
469
|
-
provenance: {
|
|
470
|
-
platform: 'github',
|
|
471
|
-
platform_event: 'pull_request.opened',
|
|
472
|
-
author: 'alice',
|
|
473
|
-
},
|
|
474
|
-
});
|
|
475
|
-
await target.deliver(event, {});
|
|
476
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
477
|
-
expect(body.text).toBe('pull_request.opened by alice');
|
|
478
|
-
expect(body.channel).toBe('#engineering');
|
|
479
|
-
});
|
|
480
|
-
it('expands launch_prompt in template', async () => {
|
|
481
|
-
const target = new WebhookTarget();
|
|
482
|
-
await target.init({
|
|
483
|
-
id: 'webhook-target',
|
|
484
|
-
connector: '@orgloop/connector-webhook',
|
|
485
|
-
config: {
|
|
486
|
-
url: 'https://example.com/hook',
|
|
487
|
-
body_template: {
|
|
488
|
-
prompt: '{{ launch_prompt }}',
|
|
489
|
-
source: '{{ event.source }}',
|
|
490
|
-
},
|
|
491
|
-
},
|
|
492
|
-
});
|
|
493
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
494
|
-
const event = createTestEvent({ source: 'my-source' });
|
|
495
|
-
await target.deliver(event, { launch_prompt: 'Review this PR' });
|
|
496
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
497
|
-
expect(body.prompt).toBe('Review this PR');
|
|
498
|
-
expect(body.source).toBe('my-source');
|
|
499
|
-
});
|
|
500
|
-
it('handles missing template paths gracefully (empty string)', async () => {
|
|
501
|
-
const target = new WebhookTarget();
|
|
502
|
-
await target.init({
|
|
503
|
-
id: 'webhook-target',
|
|
504
|
-
connector: '@orgloop/connector-webhook',
|
|
505
|
-
config: {
|
|
506
|
-
url: 'https://example.com/hook',
|
|
507
|
-
body_template: {
|
|
508
|
-
text: '{{ event.nonexistent.field }}',
|
|
509
|
-
},
|
|
510
|
-
},
|
|
511
|
-
});
|
|
512
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
513
|
-
await target.deliver(createTestEvent(), {});
|
|
514
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
515
|
-
expect(body.text).toBe('');
|
|
516
|
-
});
|
|
517
|
-
it('expands nested template objects', async () => {
|
|
518
|
-
const target = new WebhookTarget();
|
|
519
|
-
await target.init({
|
|
520
|
-
id: 'webhook-target',
|
|
521
|
-
connector: '@orgloop/connector-webhook',
|
|
522
|
-
config: {
|
|
523
|
-
url: 'https://example.com/hook',
|
|
524
|
-
body_template: {
|
|
525
|
-
message: {
|
|
526
|
-
text: '{{ event.provenance.platform }}',
|
|
527
|
-
metadata: {
|
|
528
|
-
event_id: '{{ event.id }}',
|
|
529
|
-
},
|
|
530
|
-
},
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
});
|
|
534
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
535
|
-
const event = createTestEvent({
|
|
536
|
-
provenance: { platform: 'github' },
|
|
537
|
-
});
|
|
538
|
-
await target.deliver(event, {});
|
|
539
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
540
|
-
expect(body.message.text).toBe('github');
|
|
541
|
-
expect(body.message.metadata.event_id).toBe(event.id);
|
|
542
|
-
});
|
|
543
|
-
it('preserves literal values (non-template strings, numbers, booleans)', async () => {
|
|
544
|
-
const target = new WebhookTarget();
|
|
545
|
-
await target.init({
|
|
546
|
-
id: 'webhook-target',
|
|
547
|
-
connector: '@orgloop/connector-webhook',
|
|
548
|
-
config: {
|
|
549
|
-
url: 'https://example.com/hook',
|
|
550
|
-
body_template: {
|
|
551
|
-
text: '{{ event.source }}',
|
|
552
|
-
count: 42,
|
|
553
|
-
active: true,
|
|
554
|
-
static_text: 'hello world',
|
|
555
|
-
},
|
|
556
|
-
},
|
|
557
|
-
});
|
|
558
|
-
const { createTestEvent } = await import('@orgloop/sdk');
|
|
559
|
-
await target.deliver(createTestEvent(), {});
|
|
560
|
-
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
561
|
-
expect(body.count).toBe(42);
|
|
562
|
-
expect(body.active).toBe(true);
|
|
563
|
-
expect(body.static_text).toBe('hello world');
|
|
564
|
-
});
|
|
565
|
-
});
|
|
566
|
-
});
|
|
567
|
-
//# sourceMappingURL=webhook.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.test.js","sourceRoot":"","sources":["../../src/__tests__/webhook.test.ts"],"names":[],"mappings":"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"}
|