@pikku/core 0.8.0 → 0.8.1

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/events/channel/channel-handler.js +2 -0
  3. package/dist/events/mcp/index.d.ts +1 -0
  4. package/dist/events/mcp/index.js +1 -0
  5. package/dist/events/mcp/mcp-endpoint-registry.d.ts +48 -0
  6. package/dist/events/mcp/mcp-endpoint-registry.js +122 -0
  7. package/dist/events/queue/index.d.ts +1 -1
  8. package/dist/events/queue/index.js +1 -1
  9. package/dist/events/queue/register-queue-helper.d.ts +1 -1
  10. package/dist/events/queue/register-queue-helper.js +1 -1
  11. package/dist/events/rpc/rpc-runner.d.ts +1 -4
  12. package/dist/function/function-runner.d.ts +3 -2
  13. package/dist/function/function-runner.js +10 -42
  14. package/dist/index.d.ts +5 -1
  15. package/dist/index.js +5 -1
  16. package/dist/services/index.d.ts +2 -2
  17. package/dist/services/index.js +2 -2
  18. package/dist/services/jwt-service.d.ts +1 -1
  19. package/dist/types/core.types.d.ts +1 -10
  20. package/dist/types/core.types.js +1 -1
  21. package/lcov.info +1092 -397
  22. package/package.json +2 -1
  23. package/src/events/channel/channel-handler.ts +4 -0
  24. package/src/events/http/http-runner.test.ts +2 -3
  25. package/src/events/mcp/index.ts +1 -0
  26. package/src/events/mcp/mcp-endpoint-registry.test.d.ts +1 -0
  27. package/src/events/mcp/mcp-endpoint-registry.test.ts +389 -0
  28. package/src/events/mcp/mcp-endpoint-registry.ts +165 -0
  29. package/src/events/queue/index.ts +1 -1
  30. package/src/events/queue/register-queue-helper.ts +1 -1
  31. package/src/function/function-runner.ts +21 -66
  32. package/src/index.ts +5 -1
  33. package/src/middleware/auth-apikey.ts +1 -1
  34. package/src/middleware/auth-bearer.ts +1 -1
  35. package/src/middleware/auth-cookie.ts +1 -1
  36. package/src/services/index.ts +2 -2
  37. package/src/services/jwt-service.ts +1 -1
  38. package/src/types/core.types.ts +1 -10
  39. package/tsconfig.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/core",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -27,6 +27,7 @@
27
27
  "./queue": "./dist/events/queue/index.js",
28
28
  "./scheduler": "./dist/events/scheduler/index.js",
29
29
  "./rpc": "./dist/events/rpc/index.js",
30
+ "./mcp": "./dist/events/mcp/index.js",
30
31
  "./errors": "./dist/errors/index.js",
31
32
  "./services": "./dist/services/index.js",
32
33
  "./schema": "./dist/schema.js",
@@ -95,6 +95,9 @@ export const processMessageHandlers = (
95
95
  const permissions =
96
96
  typeof onMessage === 'function' ? {} : onMessage.permissions
97
97
 
98
+ const middleware =
99
+ typeof onMessage === 'function' ? [] : onMessage.middleware
100
+
98
101
  return await runPikkuFunc(pikkuFuncName, {
99
102
  getAllServices: () => ({
100
103
  ...services,
@@ -103,6 +106,7 @@ export const processMessageHandlers = (
103
106
  data,
104
107
  session,
105
108
  permissions,
109
+ middleware,
106
110
  })
107
111
  }
108
112
 
@@ -27,8 +27,6 @@ const setHTTPFunctionMap = (func: any) => {
27
27
  pikkuFuncName: 'pikku_func_name',
28
28
  route: 'test',
29
29
  method: 'get',
30
- input: null,
31
- output: null,
32
30
  },
33
31
  ])
34
32
  addFunction('pikku_func_name', { func })
@@ -56,7 +54,8 @@ describe('fetch', () => {
56
54
  response = new PikkuMockResponse()
57
55
 
58
56
  request.getData = async () => ({})
59
- request.getHeader = () => 'application/json'
57
+ request.getHeader = (name: string) =>
58
+ name === 'content-type' ? 'application/json' : undefined
60
59
  response.setStatus = (status: number) => {}
61
60
  response.setJson = (json: JSONValue) => {}
62
61
  })
@@ -1,2 +1,3 @@
1
1
  export * from './mcp.types.js'
2
2
  export * from './mcp-runner.js'
3
+ export * from './mcp-endpoint-registry.js'
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,389 @@
1
+ import { test, describe, beforeEach } from 'node:test'
2
+ import * as assert from 'assert'
3
+ import { MCPEndpointRegistry } from './mcp-endpoint-registry.js'
4
+
5
+ describe('MCPEndpointRegistry', () => {
6
+ let registry: MCPEndpointRegistry
7
+
8
+ beforeEach(() => {
9
+ registry = new MCPEndpointRegistry()
10
+ })
11
+
12
+ describe('constructor', () => {
13
+ test('should initialize with empty maps', () => {
14
+ assert.deepStrictEqual(registry.getTools(), [])
15
+ assert.deepStrictEqual(registry.getResources(), [])
16
+ assert.deepStrictEqual(registry.getPrompts(), [])
17
+ })
18
+ })
19
+
20
+ describe('loadFromMCPJson', () => {
21
+ test('should load tools from MCP JSON', async () => {
22
+ const mockData = {
23
+ tools: [
24
+ {
25
+ name: 'test-tool',
26
+ title: 'Test Tool',
27
+ description: 'A test tool',
28
+ parameters: { type: 'object' },
29
+ returns: { type: 'string' },
30
+ enabled: true,
31
+ },
32
+ ],
33
+ }
34
+
35
+ await registry.loadFromMCPJson(mockData)
36
+
37
+ const tools = registry.getTools()
38
+ assert.strictEqual(tools.length, 1)
39
+ assert.strictEqual(tools[0].name, 'test-tool')
40
+ assert.strictEqual(tools[0].title, 'Test Tool')
41
+ assert.strictEqual(tools[0].description, 'A test tool')
42
+ assert.deepStrictEqual(tools[0].inputSchema, { type: 'object' })
43
+ assert.deepStrictEqual(tools[0].outputSchema, { type: 'string' })
44
+ assert.strictEqual(tools[0].enabled, true)
45
+ })
46
+
47
+ test('should load resources from MCP JSON', async () => {
48
+ const mockData = {
49
+ resources: [
50
+ {
51
+ name: 'test-resource',
52
+ uri: 'file://test.txt',
53
+ description: 'A test resource',
54
+ parameters: { type: 'object' },
55
+ enabled: false,
56
+ },
57
+ ],
58
+ }
59
+
60
+ await registry.loadFromMCPJson(mockData)
61
+
62
+ const resources = registry.getResources()
63
+ assert.strictEqual(resources.length, 1)
64
+ assert.strictEqual(resources[0].title, 'test-resource')
65
+ assert.strictEqual(resources[0].uri, 'file://test.txt')
66
+ assert.strictEqual(resources[0].description, 'A test resource')
67
+ assert.deepStrictEqual(resources[0].inputSchema, { type: 'object' })
68
+ assert.strictEqual(resources[0].enabled, false)
69
+ })
70
+
71
+ test('should load prompts from MCP JSON', async () => {
72
+ const mockData = {
73
+ prompts: [
74
+ {
75
+ name: 'test-prompt',
76
+ description: 'A test prompt',
77
+ arguments: { type: 'object' },
78
+ },
79
+ ],
80
+ }
81
+
82
+ await registry.loadFromMCPJson(mockData)
83
+
84
+ const prompts = registry.getPrompts()
85
+ assert.strictEqual(prompts.length, 1)
86
+ assert.strictEqual(prompts[0].name, 'test-prompt')
87
+ assert.strictEqual(prompts[0].description, 'A test prompt')
88
+ assert.deepStrictEqual(prompts[0].inputSchema, { type: 'object' })
89
+ assert.strictEqual(prompts[0].enabled, true)
90
+ })
91
+
92
+ test('should handle tools with default enabled state', async () => {
93
+ const mockData = {
94
+ tools: [
95
+ {
96
+ name: 'default-tool',
97
+ title: 'Default Tool',
98
+ description: 'Tool with default enabled state',
99
+ },
100
+ ],
101
+ }
102
+
103
+ await registry.loadFromMCPJson(mockData)
104
+
105
+ const tools = registry.getTools()
106
+ assert.strictEqual(tools.length, 1)
107
+ assert.strictEqual(tools[0].enabled, true)
108
+ })
109
+
110
+ test('should handle empty arrays', async () => {
111
+ const mockData = {
112
+ tools: [],
113
+ resources: [],
114
+ prompts: [],
115
+ }
116
+
117
+ await registry.loadFromMCPJson(mockData)
118
+
119
+ assert.deepStrictEqual(registry.getTools(), [])
120
+ assert.deepStrictEqual(registry.getResources(), [])
121
+ assert.deepStrictEqual(registry.getPrompts(), [])
122
+ })
123
+
124
+ test('should handle missing arrays', async () => {
125
+ const mockData = {}
126
+
127
+ await registry.loadFromMCPJson(mockData)
128
+
129
+ assert.deepStrictEqual(registry.getTools(), [])
130
+ assert.deepStrictEqual(registry.getResources(), [])
131
+ assert.deepStrictEqual(registry.getPrompts(), [])
132
+ })
133
+
134
+ test('should handle empty object gracefully', async () => {
135
+ // Test with empty object
136
+ await registry.loadFromMCPJson({})
137
+ assert.deepStrictEqual(registry.getTools(), [])
138
+ assert.deepStrictEqual(registry.getResources(), [])
139
+ assert.deepStrictEqual(registry.getPrompts(), [])
140
+ })
141
+ })
142
+
143
+ describe('meta setters and getters', () => {
144
+ test('should set and check resource meta', () => {
145
+ const meta = {
146
+ 'test-resource': {
147
+ uri: 'file://test.txt',
148
+ title: 'Test Resource',
149
+ description: 'Test description',
150
+ pikkuFuncName: 'testResource',
151
+ inputSchema: null,
152
+ outputSchema: null,
153
+ mimeType: 'text/plain',
154
+ },
155
+ }
156
+ registry.setResourcesMeta(meta)
157
+ assert.strictEqual(registry.hasResource('test-resource'), true)
158
+ assert.strictEqual(registry.hasResource('nonexistent'), false)
159
+ })
160
+
161
+ test('should set and check tool meta', () => {
162
+ const meta = {
163
+ 'test-tool': {
164
+ name: 'test-tool',
165
+ title: 'Test Tool',
166
+ description: 'Test description',
167
+ pikkuFuncName: 'testTool',
168
+ inputSchema: null,
169
+ outputSchema: null,
170
+ },
171
+ }
172
+ registry.setToolsMeta(meta)
173
+ assert.strictEqual(registry.hasTool('test-tool'), true)
174
+ assert.strictEqual(registry.hasTool('nonexistent'), false)
175
+ })
176
+
177
+ test('should set and check prompt meta', () => {
178
+ const meta = {
179
+ 'test-prompt': {
180
+ name: 'test-prompt',
181
+ description: 'Test Prompt',
182
+ pikkuFuncName: 'testPrompt',
183
+ inputSchema: null,
184
+ outputSchema: null,
185
+ arguments: [],
186
+ },
187
+ }
188
+ registry.setPromptsMeta(meta)
189
+ assert.strictEqual(registry.hasPrompt('test-prompt'), true)
190
+ assert.strictEqual(registry.hasPrompt('nonexistent'), false)
191
+ })
192
+ })
193
+
194
+ describe('individual item getters', () => {
195
+ beforeEach(async () => {
196
+ const mockData = {
197
+ tools: [
198
+ {
199
+ name: 'tool1',
200
+ title: 'Tool 1',
201
+ description: 'First tool',
202
+ enabled: true,
203
+ },
204
+ ],
205
+ resources: [
206
+ {
207
+ name: 'resource1',
208
+ uri: 'file://resource1.txt',
209
+ description: 'First resource',
210
+ enabled: true,
211
+ },
212
+ ],
213
+ prompts: [
214
+ {
215
+ name: 'prompt1',
216
+ description: 'First prompt',
217
+ enabled: true,
218
+ },
219
+ ],
220
+ }
221
+
222
+ await registry.loadFromMCPJson(mockData)
223
+ })
224
+
225
+ test('should get tool by name', () => {
226
+ const tool = registry.getTool('tool1')
227
+ assert.strictEqual(tool?.name, 'tool1')
228
+ assert.strictEqual(tool?.title, 'Tool 1')
229
+ assert.strictEqual(registry.getTool('nonexistent'), undefined)
230
+ })
231
+
232
+ test('should get resource by name', () => {
233
+ const resource = registry.getResource('resource1')
234
+ assert.strictEqual(resource?.title, 'resource1')
235
+ assert.strictEqual(resource?.uri, 'file://resource1.txt')
236
+ assert.strictEqual(registry.getResource('nonexistent'), undefined)
237
+ })
238
+
239
+ test('should get prompt by name', () => {
240
+ const prompt = registry.getPrompt('prompt1')
241
+ assert.strictEqual(prompt?.name, 'prompt1')
242
+ assert.strictEqual(prompt?.description, 'First prompt')
243
+ assert.strictEqual(registry.getPrompt('nonexistent'), undefined)
244
+ })
245
+ })
246
+
247
+ describe('getTools filters enabled tools', () => {
248
+ test('should only return enabled tools', async () => {
249
+ const mockData = {
250
+ tools: [
251
+ {
252
+ name: 'enabled-tool',
253
+ title: 'Enabled Tool',
254
+ description: 'This tool is enabled',
255
+ enabled: true,
256
+ },
257
+ {
258
+ name: 'disabled-tool',
259
+ title: 'Disabled Tool',
260
+ description: 'This tool is disabled',
261
+ enabled: false,
262
+ },
263
+ ],
264
+ }
265
+
266
+ await registry.loadFromMCPJson(mockData)
267
+
268
+ const tools = registry.getTools()
269
+ assert.strictEqual(tools.length, 1)
270
+ assert.strictEqual(tools[0].name, 'enabled-tool')
271
+ })
272
+ })
273
+
274
+ describe('enable/disable methods', () => {
275
+ beforeEach(async () => {
276
+ const mockData = {
277
+ tools: [
278
+ {
279
+ name: 'tool1',
280
+ title: 'Tool 1',
281
+ description: 'First tool',
282
+ enabled: true,
283
+ },
284
+ {
285
+ name: 'tool2',
286
+ title: 'Tool 2',
287
+ description: 'Second tool',
288
+ enabled: false,
289
+ },
290
+ ],
291
+ resources: [
292
+ {
293
+ name: 'resource1',
294
+ uri: 'file://resource1.txt',
295
+ description: 'First resource',
296
+ enabled: true,
297
+ },
298
+ ],
299
+ prompts: [
300
+ {
301
+ name: 'prompt1',
302
+ description: 'First prompt',
303
+ enabled: true,
304
+ },
305
+ ],
306
+ }
307
+
308
+ await registry.loadFromMCPJson(mockData)
309
+ })
310
+
311
+ test('should enable/disable tools and return change status', () => {
312
+ let changed = registry.enableTools({ tool1: false, tool2: true })
313
+ assert.strictEqual(changed, true)
314
+
315
+ const tool1 = registry.getTool('tool1')
316
+ const tool2 = registry.getTool('tool2')
317
+ assert.strictEqual(tool1?.enabled, false)
318
+ assert.strictEqual(tool2?.enabled, true)
319
+
320
+ changed = registry.enableTools({ tool1: false, tool2: true })
321
+ assert.strictEqual(changed, false)
322
+ })
323
+
324
+ test('should handle nonexistent tools', () => {
325
+ const changed = registry.enableTools({ nonexistent: true })
326
+ assert.strictEqual(changed, false)
327
+ })
328
+
329
+ test('should enable/disable prompts and return change status', () => {
330
+ let changed = registry.enablePrompts({ prompt1: false })
331
+ assert.strictEqual(changed, true)
332
+
333
+ const prompt1 = registry.getPrompt('prompt1')
334
+ assert.strictEqual(prompt1?.enabled, false)
335
+
336
+ changed = registry.enablePrompts({ prompt1: false })
337
+ assert.strictEqual(changed, false)
338
+ })
339
+
340
+ test('should handle nonexistent prompts', () => {
341
+ const changed = registry.enablePrompts({ nonexistent: true })
342
+ assert.strictEqual(changed, false)
343
+ })
344
+
345
+ test('should enable/disable resources', () => {
346
+ const changed = registry.enableResources({ resource1: false })
347
+ assert.strictEqual(changed, true)
348
+
349
+ const resource1 = registry.getResource('resource1')
350
+ assert.strictEqual(resource1?.enabled, false)
351
+ })
352
+ })
353
+
354
+ describe('edge cases', () => {
355
+ test('should handle null/undefined values in MCP JSON', async () => {
356
+ const mockData = {
357
+ tools: [
358
+ {
359
+ name: 'incomplete-tool',
360
+ title: null,
361
+ description: undefined,
362
+ },
363
+ ],
364
+ }
365
+
366
+ await registry.loadFromMCPJson(mockData)
367
+
368
+ const tools = registry.getTools()
369
+ assert.strictEqual(tools.length, 1)
370
+ assert.strictEqual(tools[0].name, 'incomplete-tool')
371
+ assert.strictEqual(tools[0].title, null)
372
+ assert.strictEqual(tools[0].description, undefined)
373
+ })
374
+
375
+ test('should handle non-array values for tools/resources/prompts', async () => {
376
+ const mockData = {
377
+ tools: 'not an array',
378
+ resources: null,
379
+ prompts: undefined,
380
+ }
381
+
382
+ await registry.loadFromMCPJson(mockData)
383
+
384
+ assert.deepStrictEqual(registry.getTools(), [])
385
+ assert.deepStrictEqual(registry.getResources(), [])
386
+ assert.deepStrictEqual(registry.getPrompts(), [])
387
+ })
388
+ })
389
+ })
@@ -0,0 +1,165 @@
1
+ import { readFile } from 'fs/promises'
2
+ import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core'
3
+
4
+ export interface MCPToolEndpoint {
5
+ name: string
6
+ title: string
7
+ description: string
8
+ inputSchema?: any
9
+ outputSchema?: any
10
+ enabled: boolean
11
+ }
12
+
13
+ export interface MCPResourceEndpoint {
14
+ uri: string
15
+ title: string
16
+ description: string
17
+ inputSchema?: any
18
+ mimeType?: string
19
+ enabled: boolean
20
+ }
21
+
22
+ export interface MCPPromptEndpoint {
23
+ name: string
24
+ description: string
25
+ inputSchema?: any
26
+ enabled: boolean
27
+ }
28
+
29
+ export class MCPEndpointRegistry {
30
+ private tools: Map<string, MCPToolEndpoint> = new Map()
31
+ private resources: Map<string, MCPResourceEndpoint> = new Map()
32
+ private prompts: Map<string, MCPPromptEndpoint> = new Map()
33
+ private resourcesMeta: MCPResourceMeta = {}
34
+ private toolsMeta: MCPToolMeta = {}
35
+ private promptsMeta: MCPPromptMeta = {}
36
+
37
+ async loadFromMCPJsonFile(mcpJsonPath: string): Promise<void> {
38
+ try {
39
+ const mcpJsonContent = await readFile(mcpJsonPath, 'utf-8')
40
+ await this.loadFromMCPJson(JSON.parse(mcpJsonContent))
41
+ } catch (error) {
42
+ throw new Error(`Failed to load MCP JSON from ${mcpJsonPath}: ${error}`)
43
+ }
44
+ }
45
+
46
+ async loadFromMCPJson(mcpData: any): Promise<void> {
47
+ if (mcpData.tools && Array.isArray(mcpData.tools)) {
48
+ for (const tool of mcpData.tools) {
49
+ this.tools.set(tool.name, {
50
+ name: tool.name,
51
+ title: tool.title,
52
+ description: tool.description,
53
+ inputSchema: tool.parameters,
54
+ outputSchema: tool.returns,
55
+ enabled: tool.enabled !== undefined ? tool.enabled : true,
56
+ })
57
+ }
58
+ }
59
+ if (mcpData.resources && Array.isArray(mcpData.resources)) {
60
+ for (const resource of mcpData.resources) {
61
+ this.resources.set(resource.name, {
62
+ title: resource.name,
63
+ uri: resource.uri,
64
+ description: resource.description,
65
+ inputSchema: resource.parameters,
66
+ enabled: resource.enabled !== undefined ? resource.enabled : true,
67
+ })
68
+ }
69
+ }
70
+ if (mcpData.prompts && Array.isArray(mcpData.prompts)) {
71
+ for (const prompt of mcpData.prompts) {
72
+ this.prompts.set(prompt.name, {
73
+ name: prompt.name,
74
+ description: prompt.description,
75
+ inputSchema: prompt.arguments,
76
+ enabled: prompt.enabled !== undefined ? prompt.enabled : true,
77
+ })
78
+ }
79
+ }
80
+ }
81
+
82
+ setResourcesMeta(meta: MCPResourceMeta): void {
83
+ this.resourcesMeta = meta
84
+ }
85
+
86
+ setToolsMeta(meta: MCPToolMeta): void {
87
+ this.toolsMeta = meta
88
+ }
89
+
90
+ setPromptsMeta(meta: MCPPromptMeta): void {
91
+ this.promptsMeta = meta
92
+ }
93
+
94
+ getTools(): MCPToolEndpoint[] {
95
+ return Array.from(this.tools.values()).filter((tool) => tool.enabled)
96
+ }
97
+
98
+ getResources(): MCPResourceEndpoint[] {
99
+ return Array.from(this.resources.values())
100
+ }
101
+
102
+ getPrompts(): MCPPromptEndpoint[] {
103
+ return Array.from(this.prompts.values())
104
+ }
105
+
106
+ getTool(name: string): MCPToolEndpoint | undefined {
107
+ return this.tools.get(name)
108
+ }
109
+
110
+ getResource(name: string): MCPResourceEndpoint | undefined {
111
+ return this.resources.get(name)
112
+ }
113
+
114
+ getPrompt(name: string): MCPPromptEndpoint | undefined {
115
+ return this.prompts.get(name)
116
+ }
117
+
118
+ hasResource(name: string): boolean {
119
+ return name in this.resourcesMeta
120
+ }
121
+
122
+ hasTool(name: string): boolean {
123
+ return name in this.toolsMeta
124
+ }
125
+
126
+ hasPrompt(name: string): boolean {
127
+ return name in this.promptsMeta
128
+ }
129
+
130
+ enableTools(tools: Record<any, boolean>): boolean {
131
+ let changed = false
132
+ for (const [name, enabled] of Object.entries(tools)) {
133
+ const tool = this.tools.get(name)
134
+ if (tool && tool.enabled !== enabled) {
135
+ tool.enabled = enabled
136
+ changed = true
137
+ }
138
+ }
139
+ return changed
140
+ }
141
+
142
+ enablePrompts(prompts: Record<any, boolean>): boolean {
143
+ let changed = false
144
+ for (const [name, enabled] of Object.entries(prompts)) {
145
+ const prompt = this.prompts.get(name)
146
+ if (prompt && prompt.enabled !== enabled) {
147
+ prompt.enabled = enabled
148
+ changed = true
149
+ }
150
+ }
151
+ return changed
152
+ }
153
+
154
+ enableResources(resources: Record<any, boolean>): boolean {
155
+ let changed = false
156
+ for (const [name, enabled] of Object.entries(resources)) {
157
+ const resource = this.resources.get(name)
158
+ if (resource && resource.enabled !== enabled) {
159
+ resource.enabled = enabled
160
+ changed = true
161
+ }
162
+ }
163
+ return changed
164
+ }
165
+ }
@@ -14,5 +14,5 @@ export { validateWorkerConfig } from './validate-worker-config.js'
14
14
  export type { QueueConfigMapping } from './validate-worker-config.js'
15
15
 
16
16
  // Queue registration helper
17
- export { registerqueueWorkers } from './register-queue-helper.js'
17
+ export { registerQueueWorkers } from './register-queue-helper.js'
18
18
  export type { QueueRegistrationCallback } from './register-queue-helper.js'
@@ -23,7 +23,7 @@ export type QueueRegistrationCallback<T = any> = (
23
23
  * @param logger - Optional logger for info/error messages
24
24
  * @returns Record of validation results by queue name
25
25
  */
26
- export async function registerqueueWorkers<T = any>(
26
+ export async function registerQueueWorkers<T = any>(
27
27
  configMappings: QueueConfigMapping,
28
28
  logger: Logger,
29
29
  registerCallback: QueueRegistrationCallback<T>