@pikku/core 0.9.3 → 0.9.5
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 +25 -0
- package/dist/function/function-runner.d.ts +2 -1
- package/dist/function/function-runner.js +22 -15
- package/dist/function/functions.types.d.ts +3 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/middleware-runner.d.ts +70 -0
- package/dist/middleware-runner.js +105 -2
- package/dist/permissions.d.ts +57 -1
- package/dist/permissions.js +122 -0
- package/dist/pikku-state.d.ts +3 -1
- package/dist/pikku-state.js +3 -1
- package/dist/types/core.types.d.ts +10 -5
- package/dist/wirings/channel/channel-handler.js +1 -0
- package/dist/wirings/channel/local/local-channel-runner.js +26 -15
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +5 -2
- package/dist/wirings/http/http-runner.js +20 -3
- package/dist/wirings/http/http.types.d.ts +5 -4
- package/dist/wirings/mcp/mcp-runner.js +27 -14
- package/dist/wirings/mcp/mcp.types.d.ts +7 -3
- package/dist/wirings/queue/index.d.ts +1 -1
- package/dist/wirings/queue/index.js +1 -1
- package/dist/wirings/queue/queue-runner.d.ts +15 -1
- package/dist/wirings/queue/queue-runner.js +71 -16
- package/dist/wirings/queue/queue.types.d.ts +19 -2
- package/dist/wirings/rpc/rpc-runner.d.ts +4 -2
- package/dist/wirings/scheduler/scheduler-runner.js +54 -24
- package/dist/wirings/scheduler/scheduler.types.d.ts +17 -2
- package/package.json +1 -1
- package/src/function/function-runner.test.ts +450 -0
- package/src/function/function-runner.ts +25 -26
- package/src/function/functions.types.ts +3 -1
- package/src/index.ts +10 -1
- package/src/middleware-runner.test.ts +329 -0
- package/src/middleware-runner.ts +131 -2
- package/src/permissions.test.ts +403 -42
- package/src/permissions.ts +182 -1
- package/src/pikku-state.ts +10 -2
- package/src/types/core.types.ts +10 -5
- package/src/wirings/channel/channel-handler.ts +1 -0
- package/src/wirings/channel/local/local-channel-runner.ts +33 -16
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +5 -2
- package/src/wirings/http/http-runner.ts +21 -3
- package/src/wirings/http/http.types.ts +5 -4
- package/src/wirings/mcp/mcp-runner.ts +37 -17
- package/src/wirings/mcp/mcp.types.ts +7 -0
- package/src/wirings/queue/index.ts +2 -0
- package/src/wirings/queue/queue-runner.ts +92 -19
- package/src/wirings/queue/queue.types.ts +20 -1
- package/src/wirings/scheduler/scheduler-runner.ts +80 -32
- package/src/wirings/scheduler/scheduler.types.ts +22 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
import { describe, test, beforeEach } from 'node:test'
|
|
2
|
+
import * as assert from 'node:assert'
|
|
3
|
+
import { addFunction, runPikkuFunc } from './function-runner.js'
|
|
4
|
+
import { addMiddleware, addPermission } from '../index.js'
|
|
5
|
+
import { resetPikkuState, pikkuState } from '../pikku-state.js'
|
|
6
|
+
import { CoreServices, CorePikkuMiddleware } from '../types/core.types.js'
|
|
7
|
+
import { CorePermissionGroup } from './functions.types.js'
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
resetPikkuState()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
// Helper function to add function with metadata for tests
|
|
14
|
+
const addTestFunction = (funcName: string, funcConfig: any) => {
|
|
15
|
+
addFunction(funcName, funcConfig)
|
|
16
|
+
pikkuState('function', 'meta')[funcName] = {
|
|
17
|
+
pikkuFuncName: funcName,
|
|
18
|
+
inputSchemaName: null,
|
|
19
|
+
outputSchemaName: null,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const mockServices: CoreServices = {
|
|
24
|
+
logger: {
|
|
25
|
+
info: () => {},
|
|
26
|
+
warn: () => {},
|
|
27
|
+
error: () => {},
|
|
28
|
+
debug: () => {},
|
|
29
|
+
},
|
|
30
|
+
} as any
|
|
31
|
+
|
|
32
|
+
describe('runPikkuFunc - Integration Tests', () => {
|
|
33
|
+
test('should execute middleware in correct order: wiringTags → wiringMiddleware → funcMiddleware → funcTags', async () => {
|
|
34
|
+
const executionOrder: string[] = []
|
|
35
|
+
const createMiddleware = (name: string): CorePikkuMiddleware => {
|
|
36
|
+
return async (services, interaction, next) => {
|
|
37
|
+
executionOrder.push(name)
|
|
38
|
+
await next()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
addMiddleware('wiringTag', [createMiddleware('wiringTag')])
|
|
43
|
+
addMiddleware('funcTag', [createMiddleware('funcTag')])
|
|
44
|
+
|
|
45
|
+
// Register function with middleware and tags
|
|
46
|
+
addTestFunction('testFunc', {
|
|
47
|
+
func: async () => {
|
|
48
|
+
executionOrder.push('main')
|
|
49
|
+
return 'success'
|
|
50
|
+
},
|
|
51
|
+
middleware: [createMiddleware('funcMiddleware')],
|
|
52
|
+
tags: ['funcTag'],
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const result = await runPikkuFunc('testFunc', {
|
|
56
|
+
getAllServices: () => mockServices,
|
|
57
|
+
data: {},
|
|
58
|
+
middleware: [createMiddleware('wiringMiddleware')],
|
|
59
|
+
tags: ['wiringTag'],
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
assert.equal(result, 'success')
|
|
63
|
+
// Order: wiringTags, wiringMiddleware, funcMiddleware, funcTags
|
|
64
|
+
assert.deepEqual(executionOrder, [
|
|
65
|
+
'wiringTag',
|
|
66
|
+
'wiringMiddleware',
|
|
67
|
+
'funcMiddleware',
|
|
68
|
+
'funcTag',
|
|
69
|
+
'main',
|
|
70
|
+
])
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('should execute permissions in correct order: wiringTags → wiringPermissions → funcTags → funcPermissions', async () => {
|
|
74
|
+
const executionOrder: string[] = []
|
|
75
|
+
|
|
76
|
+
// Setup tagged permissions
|
|
77
|
+
const wiringTagPermission = async () => {
|
|
78
|
+
executionOrder.push('wiringTag')
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
const funcTagPermission = async () => {
|
|
82
|
+
executionOrder.push('funcTag')
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
addPermission('wiringTag', [wiringTagPermission])
|
|
87
|
+
addPermission('funcTag', [funcTagPermission])
|
|
88
|
+
|
|
89
|
+
// Setup direct permissions
|
|
90
|
+
const wiringPermissions: CorePermissionGroup = {
|
|
91
|
+
permissions: [
|
|
92
|
+
async () => {
|
|
93
|
+
executionOrder.push('wiringPermission')
|
|
94
|
+
return true
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
}
|
|
98
|
+
const funcPermissions: CorePermissionGroup = {
|
|
99
|
+
permissions: [
|
|
100
|
+
async () => {
|
|
101
|
+
executionOrder.push('funcPermission')
|
|
102
|
+
return true
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Register function with permissions and tags
|
|
108
|
+
addTestFunction('testFunc', {
|
|
109
|
+
func: async () => {
|
|
110
|
+
executionOrder.push('main')
|
|
111
|
+
return 'success'
|
|
112
|
+
},
|
|
113
|
+
permissions: funcPermissions,
|
|
114
|
+
tags: ['funcTag'],
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const result = await runPikkuFunc('testFunc', {
|
|
118
|
+
getAllServices: () => mockServices,
|
|
119
|
+
data: {},
|
|
120
|
+
permissions: wiringPermissions,
|
|
121
|
+
tags: ['wiringTag'],
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
assert.equal(result, 'success')
|
|
125
|
+
// Order: wiringTags → wiringPermissions → funcTags → funcPermissions
|
|
126
|
+
assert.deepEqual(executionOrder, [
|
|
127
|
+
'wiringTag',
|
|
128
|
+
'wiringPermission',
|
|
129
|
+
'funcTag',
|
|
130
|
+
'funcPermission',
|
|
131
|
+
'main',
|
|
132
|
+
])
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('should throw specific error for wiring tag permission failures', async () => {
|
|
136
|
+
const failingWiringTagPermission = async () => false
|
|
137
|
+
|
|
138
|
+
addPermission('wiringTag', [failingWiringTagPermission])
|
|
139
|
+
|
|
140
|
+
addTestFunction('testFunc', {
|
|
141
|
+
func: async () => 'success',
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
await assert.rejects(
|
|
145
|
+
runPikkuFunc('testFunc', {
|
|
146
|
+
getAllServices: () => mockServices,
|
|
147
|
+
data: {},
|
|
148
|
+
tags: ['wiringTag'],
|
|
149
|
+
}),
|
|
150
|
+
{
|
|
151
|
+
message: 'Permission denied - wiring tag permissions',
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('should throw specific error for wiring permission failures', async () => {
|
|
157
|
+
const wiringPermissions: CorePermissionGroup = {
|
|
158
|
+
permissions: [async () => false],
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
addTestFunction('testFunc', {
|
|
162
|
+
func: async () => 'success',
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
await assert.rejects(
|
|
166
|
+
runPikkuFunc('testFunc', {
|
|
167
|
+
getAllServices: () => mockServices,
|
|
168
|
+
data: {},
|
|
169
|
+
permissions: wiringPermissions,
|
|
170
|
+
}),
|
|
171
|
+
{
|
|
172
|
+
message: 'Permission denied - wiring permissions',
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test('should throw specific error for function tag permission failures', async () => {
|
|
178
|
+
const failingFuncTagPermission = async () => false
|
|
179
|
+
|
|
180
|
+
addPermission('funcTag', [failingFuncTagPermission])
|
|
181
|
+
|
|
182
|
+
addTestFunction('testFunc', {
|
|
183
|
+
func: async () => 'success',
|
|
184
|
+
tags: ['funcTag'],
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
await assert.rejects(
|
|
188
|
+
runPikkuFunc('testFunc', {
|
|
189
|
+
getAllServices: () => mockServices,
|
|
190
|
+
data: {},
|
|
191
|
+
}),
|
|
192
|
+
{
|
|
193
|
+
message: 'Permission denied - function tag permissions',
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test('should throw specific error for function permission failures', async () => {
|
|
199
|
+
const funcPermissions: CorePermissionGroup = {
|
|
200
|
+
permissions: [async () => false],
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
addTestFunction('testFunc', {
|
|
204
|
+
func: async () => 'success',
|
|
205
|
+
permissions: funcPermissions,
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
await assert.rejects(
|
|
209
|
+
runPikkuFunc('testFunc', {
|
|
210
|
+
getAllServices: () => mockServices,
|
|
211
|
+
data: {},
|
|
212
|
+
}),
|
|
213
|
+
{
|
|
214
|
+
message: 'Permission denied - function permissions',
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
test('should deduplicate middleware when same middleware appears in tags and direct', async () => {
|
|
220
|
+
let executionCount = 0
|
|
221
|
+
|
|
222
|
+
const duplicatedMiddleware: CorePikkuMiddleware = async (
|
|
223
|
+
services,
|
|
224
|
+
interaction,
|
|
225
|
+
next
|
|
226
|
+
) => {
|
|
227
|
+
executionCount++
|
|
228
|
+
await next()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Add same middleware to tag and directly
|
|
232
|
+
addMiddleware('testTag', [duplicatedMiddleware])
|
|
233
|
+
|
|
234
|
+
addTestFunction('testFunc', {
|
|
235
|
+
func: async () => 'success',
|
|
236
|
+
middleware: [duplicatedMiddleware], // Same middleware directly
|
|
237
|
+
tags: ['testTag'], // Same middleware via tag
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
await runPikkuFunc('testFunc', {
|
|
241
|
+
getAllServices: () => mockServices,
|
|
242
|
+
data: {},
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
// Should only execute once due to deduplication
|
|
246
|
+
assert.equal(executionCount, 1)
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
test('should handle mixed permission types correctly', async () => {
|
|
250
|
+
const executionOrder: string[] = []
|
|
251
|
+
|
|
252
|
+
// Mix of array and object permissions
|
|
253
|
+
const arrayPermission = [
|
|
254
|
+
async () => {
|
|
255
|
+
executionOrder.push('arrayPermission1')
|
|
256
|
+
return false
|
|
257
|
+
},
|
|
258
|
+
async () => {
|
|
259
|
+
executionOrder.push('arrayPermission2')
|
|
260
|
+
return true
|
|
261
|
+
},
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
const objectPermission: CorePermissionGroup = {
|
|
265
|
+
permissions: [
|
|
266
|
+
async () => {
|
|
267
|
+
executionOrder.push('objectPermission')
|
|
268
|
+
return true
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
addPermission('mixedTag', arrayPermission)
|
|
274
|
+
|
|
275
|
+
addTestFunction('testFunc', {
|
|
276
|
+
func: async () => {
|
|
277
|
+
executionOrder.push('main')
|
|
278
|
+
return 'success'
|
|
279
|
+
},
|
|
280
|
+
permissions: objectPermission,
|
|
281
|
+
tags: ['mixedTag'],
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
const result = await runPikkuFunc('testFunc', {
|
|
285
|
+
getAllServices: () => mockServices,
|
|
286
|
+
data: {},
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
assert.equal(result, 'success')
|
|
290
|
+
// Should execute tag permissions first, then function permissions
|
|
291
|
+
assert.deepEqual(executionOrder, [
|
|
292
|
+
'arrayPermission1',
|
|
293
|
+
'arrayPermission2',
|
|
294
|
+
'objectPermission',
|
|
295
|
+
'main',
|
|
296
|
+
])
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
test('should work without any middleware or permissions', async () => {
|
|
300
|
+
addTestFunction('simpleFunc', {
|
|
301
|
+
func: async () => 'simple success',
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
const result = await runPikkuFunc('simpleFunc', {
|
|
305
|
+
getAllServices: () => mockServices,
|
|
306
|
+
data: {},
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
assert.equal(result, 'simple success')
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
test('should work with only wiring-level middleware and permissions', async () => {
|
|
313
|
+
const executionOrder: string[] = []
|
|
314
|
+
|
|
315
|
+
const wiringMiddleware: CorePikkuMiddleware = async (
|
|
316
|
+
services,
|
|
317
|
+
interaction,
|
|
318
|
+
next
|
|
319
|
+
) => {
|
|
320
|
+
executionOrder.push('wiringMiddleware')
|
|
321
|
+
await next()
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const wiringPermissions: CorePermissionGroup = {
|
|
325
|
+
permissions: [
|
|
326
|
+
async () => {
|
|
327
|
+
executionOrder.push('wiringPermission')
|
|
328
|
+
return true
|
|
329
|
+
},
|
|
330
|
+
],
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
addTestFunction('testFunc', {
|
|
334
|
+
func: async () => {
|
|
335
|
+
executionOrder.push('main')
|
|
336
|
+
return 'success'
|
|
337
|
+
},
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
const result = await runPikkuFunc('testFunc', {
|
|
341
|
+
getAllServices: () => mockServices,
|
|
342
|
+
data: {},
|
|
343
|
+
middleware: [wiringMiddleware],
|
|
344
|
+
permissions: wiringPermissions,
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
assert.equal(result, 'success')
|
|
348
|
+
assert.deepEqual(executionOrder, [
|
|
349
|
+
'wiringPermission',
|
|
350
|
+
'wiringMiddleware',
|
|
351
|
+
'main',
|
|
352
|
+
])
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
test('should work with only function-level middleware and permissions', async () => {
|
|
356
|
+
const executionOrder: string[] = []
|
|
357
|
+
|
|
358
|
+
const funcMiddleware: CorePikkuMiddleware = async (
|
|
359
|
+
services,
|
|
360
|
+
interaction,
|
|
361
|
+
next
|
|
362
|
+
) => {
|
|
363
|
+
executionOrder.push('funcMiddleware')
|
|
364
|
+
await next()
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const funcPermissions: CorePermissionGroup = {
|
|
368
|
+
permissions: [
|
|
369
|
+
async () => {
|
|
370
|
+
executionOrder.push('funcPermission')
|
|
371
|
+
return true
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
addTestFunction('testFunc', {
|
|
377
|
+
func: async () => {
|
|
378
|
+
executionOrder.push('main')
|
|
379
|
+
return 'success'
|
|
380
|
+
},
|
|
381
|
+
middleware: [funcMiddleware],
|
|
382
|
+
permissions: funcPermissions,
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
const result = await runPikkuFunc('testFunc', {
|
|
386
|
+
getAllServices: () => mockServices,
|
|
387
|
+
data: {},
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
assert.equal(result, 'success')
|
|
391
|
+
assert.deepEqual(executionOrder, [
|
|
392
|
+
'funcPermission',
|
|
393
|
+
'funcMiddleware',
|
|
394
|
+
'main',
|
|
395
|
+
])
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
test('should pass correct parameters to function', async () => {
|
|
399
|
+
let receivedServices: any
|
|
400
|
+
let receivedData: any
|
|
401
|
+
let receivedSession: any
|
|
402
|
+
|
|
403
|
+
const testData = { test: 'data' }
|
|
404
|
+
const testSession = { userId: 'test-user' }
|
|
405
|
+
|
|
406
|
+
addTestFunction('testFunc', {
|
|
407
|
+
func: async (services, data, session) => {
|
|
408
|
+
receivedServices = services
|
|
409
|
+
receivedData = data
|
|
410
|
+
receivedSession = session
|
|
411
|
+
return 'success'
|
|
412
|
+
},
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
await runPikkuFunc('testFunc', {
|
|
416
|
+
getAllServices: () => mockServices,
|
|
417
|
+
data: testData,
|
|
418
|
+
session: testSession,
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
assert.equal(receivedServices, mockServices)
|
|
422
|
+
assert.equal(receivedData, testData)
|
|
423
|
+
assert.equal(receivedSession, testSession)
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
test('should handle async getAllServices function', async () => {
|
|
427
|
+
let servicesProvided: any
|
|
428
|
+
|
|
429
|
+
addTestFunction('testFunc', {
|
|
430
|
+
func: async (services) => {
|
|
431
|
+
servicesProvided = services
|
|
432
|
+
return 'success'
|
|
433
|
+
},
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
const asyncGetServices = async () => {
|
|
437
|
+
// Simulate async service creation
|
|
438
|
+
await new Promise((resolve) => setTimeout(resolve, 1))
|
|
439
|
+
return mockServices
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const result = await runPikkuFunc('testFunc', {
|
|
443
|
+
getAllServices: asyncGetServices,
|
|
444
|
+
data: {},
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
assert.equal(result, 'success')
|
|
448
|
+
assert.equal(servicesProvided, mockServices)
|
|
449
|
+
})
|
|
450
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ForbiddenError } from '../errors/errors.js'
|
|
2
|
-
import { runMiddleware } from '../middleware-runner.js'
|
|
3
|
-
import {
|
|
2
|
+
import { runMiddleware, combineMiddleware } from '../middleware-runner.js'
|
|
3
|
+
import { runPermissions } from '../permissions.js'
|
|
4
4
|
import { pikkuState } from '../pikku-state.js'
|
|
5
5
|
import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js'
|
|
6
6
|
import {
|
|
@@ -47,9 +47,10 @@ export const runPikkuFunc = async <In = any, Out = any>(
|
|
|
47
47
|
getAllServices,
|
|
48
48
|
data,
|
|
49
49
|
session,
|
|
50
|
-
permissions:
|
|
51
|
-
middleware:
|
|
50
|
+
permissions: wiringPermissions,
|
|
51
|
+
middleware: wiringMiddleware,
|
|
52
52
|
coerceDataFromSchema,
|
|
53
|
+
tags = [],
|
|
53
54
|
}: {
|
|
54
55
|
getAllServices: () => Promise<CoreServices> | CoreServices
|
|
55
56
|
data: In
|
|
@@ -57,6 +58,7 @@ export const runPikkuFunc = async <In = any, Out = any>(
|
|
|
57
58
|
permissions?: CorePermissionGroup
|
|
58
59
|
middleware?: CorePikkuMiddleware[]
|
|
59
60
|
coerceDataFromSchema?: boolean
|
|
61
|
+
tags?: string[]
|
|
60
62
|
}
|
|
61
63
|
): Promise<Out> => {
|
|
62
64
|
const funcConfig = pikkuState('function', 'functions').get(funcName)
|
|
@@ -91,29 +93,26 @@ export const runPikkuFunc = async <In = any, Out = any>(
|
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
permissioned = await verifyPermissions(
|
|
105
|
-
transportPermissions,
|
|
106
|
-
allServices,
|
|
107
|
-
data,
|
|
108
|
-
session
|
|
109
|
-
)
|
|
110
|
-
}
|
|
96
|
+
// Run permission checks in the specified order
|
|
97
|
+
await runPermissions({
|
|
98
|
+
wiringTags: tags,
|
|
99
|
+
wiringPermissions,
|
|
100
|
+
funcTags: funcConfig.tags,
|
|
101
|
+
funcPermissions: funcConfig.permissions,
|
|
102
|
+
allServices,
|
|
103
|
+
data,
|
|
104
|
+
session,
|
|
105
|
+
})
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
// Combine all middleware: wiring tags → wiring middleware → func middleware → func tags
|
|
108
|
+
const allMiddleware = combineMiddleware({
|
|
109
|
+
wiringTags: tags,
|
|
110
|
+
wiringMiddleware,
|
|
111
|
+
funcMiddleware: funcConfig.middleware,
|
|
112
|
+
funcTags: funcConfig.tags,
|
|
113
|
+
})
|
|
115
114
|
|
|
116
|
-
if (
|
|
115
|
+
if (allMiddleware.length > 0) {
|
|
117
116
|
return (await runMiddleware<CorePikkuMiddleware>(
|
|
118
117
|
allServices,
|
|
119
118
|
{
|
|
@@ -121,7 +120,7 @@ export const runPikkuFunc = async <In = any, Out = any>(
|
|
|
121
120
|
mcp: allServices.mcp,
|
|
122
121
|
rpc: allServices.rpc,
|
|
123
122
|
},
|
|
124
|
-
|
|
123
|
+
allMiddleware,
|
|
125
124
|
async () => await funcConfig.func(allServices, data, session!)
|
|
126
125
|
)) as Out
|
|
127
126
|
}
|
|
@@ -87,12 +87,14 @@ export type CorePikkuFunctionConfig<
|
|
|
87
87
|
any,
|
|
88
88
|
any
|
|
89
89
|
> = CorePikkuPermission<any>,
|
|
90
|
+
PikkuMiddleware extends CorePikkuMiddleware<any> = CorePikkuMiddleware<any>,
|
|
90
91
|
> = {
|
|
91
92
|
name?: string
|
|
92
93
|
expose?: boolean
|
|
93
94
|
func: PikkuFunction
|
|
94
95
|
auth?: boolean
|
|
95
96
|
permissions?: CorePermissionGroup<PikkuPermission>
|
|
96
|
-
middleware?:
|
|
97
|
+
middleware?: PikkuMiddleware[]
|
|
98
|
+
tags?: string[]
|
|
97
99
|
docs?: PikkuDocs
|
|
98
100
|
}
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,16 @@ export * from './middleware/index.js'
|
|
|
21
21
|
export * from './time-utils.js'
|
|
22
22
|
export * from './utils.js'
|
|
23
23
|
export { pikkuState } from './pikku-state.js'
|
|
24
|
-
export {
|
|
24
|
+
export {
|
|
25
|
+
runMiddleware,
|
|
26
|
+
addMiddleware,
|
|
27
|
+
combineMiddleware,
|
|
28
|
+
} from './middleware-runner.js'
|
|
29
|
+
export {
|
|
30
|
+
addPermission,
|
|
31
|
+
getPermissionsForTags,
|
|
32
|
+
runPermissions,
|
|
33
|
+
} from './permissions.js'
|
|
25
34
|
export { wireHTTP, addHTTPMiddleware } from './wirings/http/http-runner.js'
|
|
26
35
|
export { wireChannel } from './wirings/channel/channel-runner.js'
|
|
27
36
|
export { wireScheduler } from './wirings/scheduler/scheduler-runner.js'
|