@pikku/core 0.12.1 → 0.12.2
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 +16 -0
- package/dist/middleware-runner.js +1 -0
- package/dist/permissions.js +1 -0
- package/dist/pikku-state.js +4 -0
- package/dist/services/gateway-service.d.ts +19 -0
- package/dist/services/gateway-service.js +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +1 -0
- package/dist/services/local-gateway-service.d.ts +22 -0
- package/dist/services/local-gateway-service.js +51 -0
- package/dist/types/core.types.d.ts +3 -1
- package/dist/types/state.types.d.ts +5 -0
- package/dist/utils.js +1 -1
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +27 -5
- package/dist/wirings/ai-agent/ai-agent-memory.js +13 -2
- package/dist/wirings/ai-agent/ai-agent-prepare.js +14 -1
- package/dist/wirings/ai-agent/ai-agent-stream.js +17 -2
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +35 -2
- package/dist/wirings/ai-agent/index.d.ts +1 -1
- package/dist/wirings/channel/channel-handler.d.ts +5 -2
- package/dist/wirings/channel/channel-handler.js +11 -1
- package/dist/wirings/channel/channel-middleware-runner.js +1 -0
- package/dist/wirings/channel/channel.types.d.ts +6 -0
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +7 -0
- package/dist/wirings/channel/local/local-channel-handler.js +17 -0
- package/dist/wirings/channel/local/local-channel-runner.js +14 -1
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +2 -1
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +1 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +1 -1
- package/dist/wirings/cli/cli-runner.js +3 -0
- package/dist/wirings/gateway/gateway-runner.d.ts +24 -0
- package/dist/wirings/gateway/gateway-runner.js +325 -0
- package/dist/wirings/gateway/gateway.types.d.ts +127 -0
- package/dist/wirings/gateway/gateway.types.js +1 -0
- package/dist/wirings/gateway/index.d.ts +2 -0
- package/dist/wirings/gateway/index.js +1 -0
- package/dist/wirings/http/http-runner.js +3 -0
- package/package.json +3 -2
- package/src/middleware-runner.ts +1 -0
- package/src/permissions.ts +1 -0
- package/src/pikku-state.ts +5 -0
- package/src/services/gateway-service.ts +20 -0
- package/src/services/index.ts +2 -0
- package/src/services/local-gateway-service.ts +62 -0
- package/src/types/core.types.ts +3 -0
- package/src/types/state.types.ts +8 -0
- package/src/utils.ts +1 -1
- package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +33 -9
- package/src/wirings/ai-agent/ai-agent-memory.ts +10 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +19 -1
- package/src/wirings/ai-agent/ai-agent-stream.ts +13 -2
- package/src/wirings/ai-agent/ai-agent.types.ts +34 -2
- package/src/wirings/ai-agent/index.ts +2 -0
- package/src/wirings/channel/channel-handler.ts +30 -2
- package/src/wirings/channel/channel-middleware-runner.ts +1 -0
- package/src/wirings/channel/channel.types.ts +11 -0
- package/src/wirings/channel/index.ts +1 -0
- package/src/wirings/channel/local/local-channel-handler.ts +26 -0
- package/src/wirings/channel/local/local-channel-runner.ts +15 -1
- package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +2 -0
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +8 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +1 -1
- package/src/wirings/cli/cli-runner.ts +3 -0
- package/src/wirings/gateway/gateway-runner.test.ts +474 -0
- package/src/wirings/gateway/gateway-runner.ts +411 -0
- package/src/wirings/gateway/gateway.types.ts +149 -0
- package/src/wirings/gateway/index.ts +13 -0
- package/src/wirings/http/http-runner.ts +3 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { test, describe, beforeEach } from 'node:test'
|
|
2
|
+
import * as assert from 'assert'
|
|
3
|
+
import { wireGateway, createListenerMessageHandler } from './gateway-runner.js'
|
|
4
|
+
import { pikkuState, resetPikkuState } from '../../pikku-state.js'
|
|
5
|
+
import { httpRouter } from '../http/routers/http-router.js'
|
|
6
|
+
import { fetch } from '../http/http-runner.js'
|
|
7
|
+
import type {
|
|
8
|
+
GatewayAdapter,
|
|
9
|
+
GatewayInboundMessage,
|
|
10
|
+
GatewayOutboundMessage,
|
|
11
|
+
} from './gateway.types.js'
|
|
12
|
+
import type { CorePikkuMiddleware } from '../../types/core.types.js'
|
|
13
|
+
|
|
14
|
+
// --- Mock adapter ----------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
const createMockAdapter = (
|
|
17
|
+
opts: {
|
|
18
|
+
name?: string
|
|
19
|
+
parseResult?: GatewayInboundMessage | null
|
|
20
|
+
verifyResult?: { verified: true; response: unknown } | { verified: false }
|
|
21
|
+
} = {}
|
|
22
|
+
): GatewayAdapter & {
|
|
23
|
+
sentMessages: Array<{ senderId: string; message: GatewayOutboundMessage }>
|
|
24
|
+
simulateMessage: (data: unknown) => Promise<void>
|
|
25
|
+
} => {
|
|
26
|
+
const sentMessages: Array<{
|
|
27
|
+
senderId: string
|
|
28
|
+
message: GatewayOutboundMessage
|
|
29
|
+
}> = []
|
|
30
|
+
|
|
31
|
+
let onMessage: ((data: unknown) => Promise<void>) | undefined
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
name: opts.name ?? 'mock',
|
|
35
|
+
sentMessages,
|
|
36
|
+
parse(data: unknown): GatewayInboundMessage | null {
|
|
37
|
+
if (opts.parseResult !== undefined) return opts.parseResult
|
|
38
|
+
const d = data as Record<string, any>
|
|
39
|
+
if (!d?.text) return null
|
|
40
|
+
return {
|
|
41
|
+
senderId: d.senderId ?? 'sender-1',
|
|
42
|
+
text: d.text,
|
|
43
|
+
raw: data,
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
send: async (senderId, message) => {
|
|
47
|
+
sentMessages.push({ senderId, message })
|
|
48
|
+
},
|
|
49
|
+
init: async (cb) => {
|
|
50
|
+
onMessage = cb
|
|
51
|
+
},
|
|
52
|
+
close: async () => {
|
|
53
|
+
onMessage = undefined
|
|
54
|
+
},
|
|
55
|
+
async simulateMessage(data: unknown) {
|
|
56
|
+
if (onMessage) await onMessage(data)
|
|
57
|
+
},
|
|
58
|
+
...(opts.verifyResult
|
|
59
|
+
? {
|
|
60
|
+
verifyWebhook: () => opts.verifyResult!,
|
|
61
|
+
}
|
|
62
|
+
: {}),
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// --- Test helpers -----------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
const setupState = () => {
|
|
69
|
+
resetPikkuState()
|
|
70
|
+
httpRouter.reset()
|
|
71
|
+
|
|
72
|
+
const singletonServices = {
|
|
73
|
+
config: {},
|
|
74
|
+
logger: {
|
|
75
|
+
info: () => {},
|
|
76
|
+
warn: () => {},
|
|
77
|
+
error: () => {},
|
|
78
|
+
},
|
|
79
|
+
variables: {},
|
|
80
|
+
secrets: {},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pikkuState(null, 'package', 'singletonServices', singletonServices as any)
|
|
84
|
+
pikkuState(null, 'package', 'factories', {
|
|
85
|
+
createWireServices: async () => ({}),
|
|
86
|
+
} as any)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// --- Tests ------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
describe('wireGateway', () => {
|
|
92
|
+
beforeEach(() => {
|
|
93
|
+
setupState()
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('type: webhook', () => {
|
|
97
|
+
test('registers POST route and processes messages', async () => {
|
|
98
|
+
const adapter = createMockAdapter()
|
|
99
|
+
const funcCalls: any[] = []
|
|
100
|
+
|
|
101
|
+
wireGateway({
|
|
102
|
+
name: 'test-webhook',
|
|
103
|
+
type: 'webhook',
|
|
104
|
+
route: '/webhooks/test',
|
|
105
|
+
adapter,
|
|
106
|
+
func: {
|
|
107
|
+
func: async (_services: any, data: any, wire: any) => {
|
|
108
|
+
funcCalls.push({ data, gateway: wire.gateway })
|
|
109
|
+
return { text: 'reply' }
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
httpRouter.initialize()
|
|
115
|
+
|
|
116
|
+
const request = new Request('http://localhost/webhooks/test', {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
body: JSON.stringify({ senderId: 'user-1', text: 'hello' }),
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
const response = await fetch(request)
|
|
123
|
+
assert.equal(response.status, 200)
|
|
124
|
+
|
|
125
|
+
// Verify func was called with parsed message
|
|
126
|
+
assert.equal(funcCalls.length, 1)
|
|
127
|
+
assert.equal(funcCalls[0].data.senderId, 'user-1')
|
|
128
|
+
assert.equal(funcCalls[0].data.text, 'hello')
|
|
129
|
+
|
|
130
|
+
// Verify wire.gateway was populated
|
|
131
|
+
assert.equal(funcCalls[0].gateway.gatewayName, 'test-webhook')
|
|
132
|
+
assert.equal(funcCalls[0].gateway.senderId, 'user-1')
|
|
133
|
+
assert.equal(funcCalls[0].gateway.platform, 'mock')
|
|
134
|
+
assert.equal(typeof funcCalls[0].gateway.send, 'function')
|
|
135
|
+
|
|
136
|
+
// Verify auto-send of response
|
|
137
|
+
assert.equal(adapter.sentMessages.length, 1)
|
|
138
|
+
assert.equal(adapter.sentMessages[0].senderId, 'user-1')
|
|
139
|
+
assert.equal(adapter.sentMessages[0].message.text, 'reply')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('returns 200 OK for ignored events (adapter returns null)', async () => {
|
|
143
|
+
const adapter = createMockAdapter({ parseResult: null })
|
|
144
|
+
const funcCalls: any[] = []
|
|
145
|
+
|
|
146
|
+
wireGateway({
|
|
147
|
+
name: 'test-ignore',
|
|
148
|
+
type: 'webhook',
|
|
149
|
+
route: '/webhooks/ignore',
|
|
150
|
+
adapter,
|
|
151
|
+
func: {
|
|
152
|
+
func: async () => {
|
|
153
|
+
funcCalls.push(true)
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
httpRouter.initialize()
|
|
159
|
+
|
|
160
|
+
const request = new Request('http://localhost/webhooks/ignore', {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers: { 'Content-Type': 'application/json' },
|
|
163
|
+
body: JSON.stringify({ type: 'delivery_receipt' }),
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const response = await fetch(request)
|
|
167
|
+
assert.equal(response.status, 200)
|
|
168
|
+
|
|
169
|
+
// Func should NOT be called
|
|
170
|
+
assert.equal(funcCalls.length, 0)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test('runs middleware before func with wire.gateway available', async () => {
|
|
174
|
+
const adapter = createMockAdapter()
|
|
175
|
+
const middlewareCalls: any[] = []
|
|
176
|
+
|
|
177
|
+
const testMiddleware: CorePikkuMiddleware = async (
|
|
178
|
+
_services,
|
|
179
|
+
wire,
|
|
180
|
+
next
|
|
181
|
+
) => {
|
|
182
|
+
middlewareCalls.push({
|
|
183
|
+
gateway: (wire as any).gateway,
|
|
184
|
+
hasSession: !!wire.session,
|
|
185
|
+
})
|
|
186
|
+
wire.setSession?.({ userId: 'resolved-user' } as any)
|
|
187
|
+
await next()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
wireGateway({
|
|
191
|
+
name: 'test-middleware',
|
|
192
|
+
type: 'webhook',
|
|
193
|
+
route: '/webhooks/mw',
|
|
194
|
+
adapter,
|
|
195
|
+
middleware: [testMiddleware],
|
|
196
|
+
func: {
|
|
197
|
+
func: async (_services: any, _data: any, wire: any) => {
|
|
198
|
+
return { text: `hello ${wire.session?.userId ?? 'unknown'}` }
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
httpRouter.initialize()
|
|
204
|
+
|
|
205
|
+
const request = new Request('http://localhost/webhooks/mw', {
|
|
206
|
+
method: 'POST',
|
|
207
|
+
headers: { 'Content-Type': 'application/json' },
|
|
208
|
+
body: JSON.stringify({ senderId: 'user-2', text: 'hi' }),
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
await fetch(request)
|
|
212
|
+
|
|
213
|
+
// Middleware should have run
|
|
214
|
+
assert.equal(middlewareCalls.length, 1)
|
|
215
|
+
// Middleware should see wire.gateway
|
|
216
|
+
assert.equal(middlewareCalls[0].gateway.senderId, 'user-2')
|
|
217
|
+
assert.equal(middlewareCalls[0].gateway.platform, 'mock')
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
test('handles webhook verification via GET', async () => {
|
|
221
|
+
const adapter = createMockAdapter({
|
|
222
|
+
verifyResult: { verified: true, response: 'challenge-token-123' },
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
wireGateway({
|
|
226
|
+
name: 'test-verify',
|
|
227
|
+
type: 'webhook',
|
|
228
|
+
route: '/webhooks/verify',
|
|
229
|
+
adapter,
|
|
230
|
+
func: { func: async () => {} },
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
httpRouter.initialize()
|
|
234
|
+
|
|
235
|
+
const request = new Request(
|
|
236
|
+
'http://localhost/webhooks/verify?hub.mode=subscribe&hub.verify_token=tok&hub.challenge=challenge-token-123',
|
|
237
|
+
{ method: 'GET' }
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
const response = await fetch(request)
|
|
241
|
+
assert.equal(response.status, 200)
|
|
242
|
+
|
|
243
|
+
const body = await response.json()
|
|
244
|
+
assert.equal(body, 'challenge-token-123')
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
test('handles POST-based verification (Slack style)', async () => {
|
|
248
|
+
const adapter = createMockAdapter({
|
|
249
|
+
parseResult: null,
|
|
250
|
+
verifyResult: {
|
|
251
|
+
verified: true,
|
|
252
|
+
response: { challenge: 'abc123' },
|
|
253
|
+
},
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
wireGateway({
|
|
257
|
+
name: 'test-slack-verify',
|
|
258
|
+
type: 'webhook',
|
|
259
|
+
route: '/webhooks/slack',
|
|
260
|
+
adapter,
|
|
261
|
+
func: { func: async () => {} },
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
httpRouter.initialize()
|
|
265
|
+
|
|
266
|
+
const request = new Request('http://localhost/webhooks/slack', {
|
|
267
|
+
method: 'POST',
|
|
268
|
+
headers: { 'Content-Type': 'application/json' },
|
|
269
|
+
body: JSON.stringify({
|
|
270
|
+
type: 'url_verification',
|
|
271
|
+
challenge: 'abc123',
|
|
272
|
+
}),
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
const response = await fetch(request)
|
|
276
|
+
assert.equal(response.status, 200)
|
|
277
|
+
|
|
278
|
+
const body = await response.json()
|
|
279
|
+
assert.deepEqual(body, { challenge: 'abc123' })
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
test('wire.gateway.send() sends proactive messages', async () => {
|
|
283
|
+
const adapter = createMockAdapter()
|
|
284
|
+
let capturedGateway: any
|
|
285
|
+
|
|
286
|
+
wireGateway({
|
|
287
|
+
name: 'test-proactive',
|
|
288
|
+
type: 'webhook',
|
|
289
|
+
route: '/webhooks/proactive',
|
|
290
|
+
adapter,
|
|
291
|
+
func: {
|
|
292
|
+
func: async (_services: any, _data: any, wire: any) => {
|
|
293
|
+
capturedGateway = wire.gateway
|
|
294
|
+
// Send a proactive message via gateway
|
|
295
|
+
await wire.gateway.send({ text: 'proactive msg' })
|
|
296
|
+
// Don't return a response (no auto-send)
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
httpRouter.initialize()
|
|
302
|
+
|
|
303
|
+
const request = new Request('http://localhost/webhooks/proactive', {
|
|
304
|
+
method: 'POST',
|
|
305
|
+
headers: { 'Content-Type': 'application/json' },
|
|
306
|
+
body: JSON.stringify({ senderId: 'user-3', text: 'trigger' }),
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
await fetch(request)
|
|
310
|
+
|
|
311
|
+
// Proactive message was sent
|
|
312
|
+
assert.equal(adapter.sentMessages.length, 1)
|
|
313
|
+
assert.equal(adapter.sentMessages[0].message.text, 'proactive msg')
|
|
314
|
+
})
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
describe('type: webhook errors', () => {
|
|
318
|
+
test('throws if no route provided for webhook', () => {
|
|
319
|
+
const adapter = createMockAdapter()
|
|
320
|
+
|
|
321
|
+
assert.throws(
|
|
322
|
+
() =>
|
|
323
|
+
wireGateway({
|
|
324
|
+
name: 'no-route',
|
|
325
|
+
type: 'webhook',
|
|
326
|
+
adapter,
|
|
327
|
+
func: { func: async () => {} },
|
|
328
|
+
}),
|
|
329
|
+
/requires a route/
|
|
330
|
+
)
|
|
331
|
+
})
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
describe('type: listener', () => {
|
|
335
|
+
test('stores gateway config in pikkuState', () => {
|
|
336
|
+
const adapter = createMockAdapter()
|
|
337
|
+
|
|
338
|
+
wireGateway({
|
|
339
|
+
name: 'test-listener',
|
|
340
|
+
type: 'listener',
|
|
341
|
+
adapter,
|
|
342
|
+
func: { func: async () => {} },
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
const gateways = pikkuState(null, 'gateway', 'gateways')
|
|
346
|
+
assert.ok(gateways.has('test-listener'))
|
|
347
|
+
assert.equal(gateways.get('test-listener').type, 'listener')
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
describe('createListenerMessageHandler', () => {
|
|
352
|
+
test('creates handler that processes messages', async () => {
|
|
353
|
+
const adapter = createMockAdapter()
|
|
354
|
+
const funcCalls: any[] = []
|
|
355
|
+
|
|
356
|
+
const config = {
|
|
357
|
+
name: 'test-listener',
|
|
358
|
+
type: 'listener' as const,
|
|
359
|
+
adapter,
|
|
360
|
+
func: {
|
|
361
|
+
func: async (_services: any, data: any, wire: any) => {
|
|
362
|
+
funcCalls.push({ data, gateway: wire.gateway })
|
|
363
|
+
return { text: 'listener-reply' }
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
wireGateway(config)
|
|
369
|
+
|
|
370
|
+
const singletonServices = pikkuState(null, 'package', 'singletonServices')
|
|
371
|
+
const handleMessage = createListenerMessageHandler(
|
|
372
|
+
'test-listener',
|
|
373
|
+
config,
|
|
374
|
+
singletonServices
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
// Simulate incoming message
|
|
378
|
+
await handleMessage({
|
|
379
|
+
senderId: 'listener-user',
|
|
380
|
+
text: 'hello from listener',
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
assert.equal(funcCalls.length, 1)
|
|
384
|
+
assert.equal(funcCalls[0].data.senderId, 'listener-user')
|
|
385
|
+
assert.equal(funcCalls[0].data.text, 'hello from listener')
|
|
386
|
+
assert.equal(funcCalls[0].gateway.platform, 'mock')
|
|
387
|
+
|
|
388
|
+
// Auto-send response
|
|
389
|
+
assert.equal(adapter.sentMessages.length, 1)
|
|
390
|
+
assert.equal(adapter.sentMessages[0].message.text, 'listener-reply')
|
|
391
|
+
})
|
|
392
|
+
|
|
393
|
+
test('handler ignores events when adapter returns null', async () => {
|
|
394
|
+
const adapter = createMockAdapter({ parseResult: null })
|
|
395
|
+
const funcCalls: any[] = []
|
|
396
|
+
|
|
397
|
+
const config = {
|
|
398
|
+
name: 'test-listener-ignore',
|
|
399
|
+
type: 'listener' as const,
|
|
400
|
+
adapter,
|
|
401
|
+
func: {
|
|
402
|
+
func: async () => {
|
|
403
|
+
funcCalls.push(true)
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
wireGateway(config)
|
|
409
|
+
|
|
410
|
+
const singletonServices = pikkuState(null, 'package', 'singletonServices')
|
|
411
|
+
const handleMessage = createListenerMessageHandler(
|
|
412
|
+
'test-listener-ignore',
|
|
413
|
+
config,
|
|
414
|
+
singletonServices
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
await handleMessage({ type: 'delivery_receipt' })
|
|
418
|
+
|
|
419
|
+
assert.equal(funcCalls.length, 0)
|
|
420
|
+
})
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
describe('gateway: true metadata flag', () => {
|
|
424
|
+
test('webhook gateway adds gateway meta to pikkuState', () => {
|
|
425
|
+
const adapter = createMockAdapter()
|
|
426
|
+
|
|
427
|
+
wireGateway({
|
|
428
|
+
name: 'test-meta',
|
|
429
|
+
type: 'webhook',
|
|
430
|
+
route: '/webhooks/meta',
|
|
431
|
+
adapter,
|
|
432
|
+
func: { func: async () => {} },
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
const gateways = pikkuState(null, 'gateway', 'gateways')
|
|
436
|
+
const config = gateways.get('test-meta')
|
|
437
|
+
assert.ok(config)
|
|
438
|
+
assert.equal(config.type, 'webhook')
|
|
439
|
+
assert.equal(config.name, 'test-meta')
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
describe('type: websocket', () => {
|
|
444
|
+
test('registers channel config', () => {
|
|
445
|
+
const adapter = createMockAdapter()
|
|
446
|
+
|
|
447
|
+
wireGateway({
|
|
448
|
+
name: 'test-ws',
|
|
449
|
+
type: 'websocket',
|
|
450
|
+
route: '/gateway/ws',
|
|
451
|
+
adapter,
|
|
452
|
+
func: { func: async () => {} },
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
const channels = pikkuState(null, 'channel', 'channels')
|
|
456
|
+
assert.ok(channels.has('test-ws'))
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
test('throws if no route provided', () => {
|
|
460
|
+
const adapter = createMockAdapter()
|
|
461
|
+
|
|
462
|
+
assert.throws(
|
|
463
|
+
() =>
|
|
464
|
+
wireGateway({
|
|
465
|
+
name: 'no-route-ws',
|
|
466
|
+
type: 'websocket',
|
|
467
|
+
adapter,
|
|
468
|
+
func: { func: async () => {} },
|
|
469
|
+
}),
|
|
470
|
+
/requires a route/
|
|
471
|
+
)
|
|
472
|
+
})
|
|
473
|
+
})
|
|
474
|
+
})
|