@pikku/core 0.7.8 → 0.8.0

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 (151) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/dist/errors/error-handler.d.ts +2 -0
  3. package/dist/errors/errors.js +2 -0
  4. package/dist/{channel → events/channel}/channel-handler.d.ts +1 -1
  5. package/dist/{channel → events/channel}/channel-handler.js +2 -2
  6. package/dist/{channel → events/channel}/channel-runner.d.ts +1 -1
  7. package/dist/{channel → events/channel}/channel-runner.js +4 -4
  8. package/dist/{channel → events/channel}/channel-store.d.ts +1 -1
  9. package/dist/{channel → events/channel}/channel.types.d.ts +3 -3
  10. package/dist/{channel → events/channel}/local/local-channel-runner.js +6 -6
  11. package/dist/{channel → events/channel}/log-channels.d.ts +1 -1
  12. package/dist/{channel → events/channel}/log-channels.js +1 -1
  13. package/dist/{channel → events/channel}/serverless/serverless-channel-runner.js +7 -7
  14. package/dist/{http → events/http}/http-runner.d.ts +1 -1
  15. package/dist/{http → events/http}/http-runner.js +8 -8
  16. package/dist/{http → events/http}/http.types.d.ts +3 -3
  17. package/dist/{http → events/http}/index.d.ts +0 -1
  18. package/dist/{http → events/http}/index.js +0 -1
  19. package/dist/{http → events/http}/log-http-routes.d.ts +1 -1
  20. package/dist/{http → events/http}/log-http-routes.js +1 -1
  21. package/dist/{http → events/http}/pikku-fetch-http-request.js +1 -1
  22. package/dist/events/mcp/index.d.ts +2 -0
  23. package/dist/events/mcp/index.js +2 -0
  24. package/dist/events/mcp/mcp-runner.d.ts +30 -0
  25. package/dist/events/mcp/mcp-runner.js +192 -0
  26. package/dist/events/mcp/mcp.types.d.ts +117 -0
  27. package/dist/events/queue/index.d.ts +6 -0
  28. package/dist/events/queue/index.js +6 -0
  29. package/dist/events/queue/queue-runner.d.ts +24 -0
  30. package/dist/events/queue/queue-runner.js +83 -0
  31. package/dist/events/queue/queue.types.d.ts +154 -0
  32. package/dist/events/queue/register-queue-helper.d.ts +17 -0
  33. package/dist/events/queue/register-queue-helper.js +34 -0
  34. package/dist/events/queue/validate-worker-config.d.ts +41 -0
  35. package/dist/events/queue/validate-worker-config.js +50 -0
  36. package/dist/events/rpc/index.d.ts +2 -0
  37. package/dist/events/rpc/rpc-runner.d.ts +28 -0
  38. package/dist/{rpc → events/rpc}/rpc-runner.js +2 -2
  39. package/dist/events/scheduler/index.d.ts +3 -0
  40. package/dist/events/scheduler/index.js +3 -0
  41. package/dist/{scheduler → events/scheduler}/log-schedulers.d.ts +1 -1
  42. package/dist/{scheduler → events/scheduler}/log-schedulers.js +1 -1
  43. package/dist/{scheduler → events/scheduler}/scheduler-runner.d.ts +4 -3
  44. package/dist/{scheduler → events/scheduler}/scheduler-runner.js +7 -4
  45. package/dist/{scheduler → events/scheduler}/scheduler.types.d.ts +3 -4
  46. package/dist/function/function-runner.js +8 -0
  47. package/dist/function/functions.types.d.ts +3 -2
  48. package/dist/handle-error.d.ts +2 -2
  49. package/dist/handle-error.js +1 -1
  50. package/dist/index.d.ts +10 -6
  51. package/dist/index.js +10 -6
  52. package/dist/middleware-runner.d.ts +4 -4
  53. package/dist/middleware-runner.js +3 -1
  54. package/dist/pikku-state.d.ts +18 -4
  55. package/dist/pikku-state.js +12 -0
  56. package/dist/services/user-session-service.d.ts +1 -1
  57. package/dist/types/core.types.d.ts +17 -5
  58. package/dist/types/core.types.js +2 -0
  59. package/lcov.info +3191 -3123
  60. package/package.json +8 -7
  61. package/src/errors/error-handler.ts +2 -1
  62. package/src/errors/errors.ts +2 -0
  63. package/src/{channel → events/channel}/channel-handler.ts +3 -3
  64. package/src/{channel → events/channel}/channel-runner.ts +5 -5
  65. package/src/{channel → events/channel}/channel-store.ts +1 -1
  66. package/src/{channel → events/channel}/channel.types.ts +3 -3
  67. package/src/{channel → events/channel}/local/local-channel-runner.test.ts +1 -1
  68. package/src/{channel → events/channel}/local/local-channel-runner.ts +7 -7
  69. package/src/{channel → events/channel}/local/local-eventhub-service.test.ts +1 -1
  70. package/src/{channel → events/channel}/log-channels.ts +2 -2
  71. package/src/{channel → events/channel}/serverless/serverless-channel-runner.ts +8 -8
  72. package/src/{http → events/http}/http-runner.test.ts +4 -4
  73. package/src/{http → events/http}/http-runner.ts +9 -9
  74. package/src/{http → events/http}/http.types.ts +3 -3
  75. package/src/{http → events/http}/index.ts +0 -1
  76. package/src/{http → events/http}/log-http-routes.ts +2 -2
  77. package/src/{http → events/http}/pikku-fetch-http-request.ts +1 -1
  78. package/src/events/mcp/index.ts +2 -0
  79. package/src/events/mcp/mcp-runner.ts +321 -0
  80. package/src/events/mcp/mcp.types.ts +150 -0
  81. package/src/events/queue/index.ts +18 -0
  82. package/src/events/queue/queue-runner.ts +125 -0
  83. package/src/events/queue/queue.types.ts +176 -0
  84. package/src/events/queue/register-queue-helper.ts +62 -0
  85. package/src/events/queue/validate-worker-config.ts +113 -0
  86. package/src/events/rpc/index.ts +2 -0
  87. package/src/{rpc → events/rpc}/rpc-runner.ts +3 -3
  88. package/src/events/scheduler/index.ts +9 -0
  89. package/src/{scheduler → events/scheduler}/log-schedulers.ts +2 -2
  90. package/src/{scheduler → events/scheduler}/scheduler-runner.ts +11 -10
  91. package/src/{scheduler → events/scheduler}/scheduler.types.ts +2 -4
  92. package/src/function/function-runner.ts +19 -1
  93. package/src/function/functions.types.ts +3 -1
  94. package/src/handle-error.ts +2 -2
  95. package/src/index.ts +23 -6
  96. package/src/middleware-runner.ts +14 -7
  97. package/src/pikku-state.ts +40 -4
  98. package/src/services/user-session-service.ts +1 -1
  99. package/src/types/core.types.ts +24 -4
  100. package/tsconfig.json +3 -2
  101. package/tsconfig.tsbuildinfo +1 -1
  102. package/dist/rpc/index.d.ts +0 -2
  103. package/dist/rpc/rpc-runner.d.ts +0 -27
  104. package/dist/scheduler/index.d.ts +0 -3
  105. package/dist/scheduler/index.js +0 -3
  106. package/src/http/incomingmessage-to-request-convertor.ts +0 -0
  107. package/src/rpc/index.ts +0 -2
  108. package/src/scheduler/index.ts +0 -5
  109. /package/dist/{channel → events/channel}/channel-store.js +0 -0
  110. /package/dist/{channel → events/channel}/channel.types.js +0 -0
  111. /package/dist/{channel → events/channel}/eventhub-service.d.ts +0 -0
  112. /package/dist/{channel → events/channel}/eventhub-service.js +0 -0
  113. /package/dist/{channel → events/channel}/eventhub-store.d.ts +0 -0
  114. /package/dist/{channel → events/channel}/eventhub-store.js +0 -0
  115. /package/dist/{channel → events/channel}/index.d.ts +0 -0
  116. /package/dist/{channel → events/channel}/index.js +0 -0
  117. /package/dist/{channel → events/channel}/local/index.d.ts +0 -0
  118. /package/dist/{channel → events/channel}/local/index.js +0 -0
  119. /package/dist/{channel → events/channel}/local/local-channel-handler.d.ts +0 -0
  120. /package/dist/{channel → events/channel}/local/local-channel-handler.js +0 -0
  121. /package/dist/{channel → events/channel}/local/local-channel-runner.d.ts +0 -0
  122. /package/dist/{channel → events/channel}/local/local-eventhub-service.d.ts +0 -0
  123. /package/dist/{channel → events/channel}/local/local-eventhub-service.js +0 -0
  124. /package/dist/{channel → events/channel}/pikku-abstract-channel-handler.d.ts +0 -0
  125. /package/dist/{channel → events/channel}/pikku-abstract-channel-handler.js +0 -0
  126. /package/dist/{channel → events/channel}/serverless/index.d.ts +0 -0
  127. /package/dist/{channel → events/channel}/serverless/index.js +0 -0
  128. /package/dist/{channel → events/channel}/serverless/serverless-channel-runner.d.ts +0 -0
  129. /package/dist/{http → events/http}/http.types.js +0 -0
  130. /package/dist/{http → events/http}/pikku-fetch-http-request.d.ts +0 -0
  131. /package/dist/{http → events/http}/pikku-fetch-http-response.d.ts +0 -0
  132. /package/dist/{http → events/http}/pikku-fetch-http-response.js +0 -0
  133. /package/dist/{http/incomingmessage-to-request-convertor.d.ts → events/mcp/mcp.types.js} +0 -0
  134. /package/dist/{http/incomingmessage-to-request-convertor.js → events/queue/queue.types.js} +0 -0
  135. /package/dist/{rpc → events/rpc}/index.js +0 -0
  136. /package/dist/{rpc → events/rpc}/rpc-types.d.ts +0 -0
  137. /package/dist/{rpc → events/rpc}/rpc-types.js +0 -0
  138. /package/dist/{scheduler → events/scheduler}/scheduler.types.js +0 -0
  139. /package/src/{channel → events/channel}/eventhub-service.ts +0 -0
  140. /package/src/{channel → events/channel}/eventhub-store.ts +0 -0
  141. /package/src/{channel → events/channel}/index.ts +0 -0
  142. /package/src/{channel → events/channel}/local/index.ts +0 -0
  143. /package/src/{channel → events/channel}/local/local-channel-handler.ts +0 -0
  144. /package/src/{channel → events/channel}/local/local-eventhub-service.ts +0 -0
  145. /package/src/{channel → events/channel}/pikku-abstract-channel-handler.test.ts +0 -0
  146. /package/src/{channel → events/channel}/pikku-abstract-channel-handler.ts +0 -0
  147. /package/src/{channel → events/channel}/serverless/index.ts +0 -0
  148. /package/src/{http → events/http}/pikku-fetch-http-request.test.ts +0 -0
  149. /package/src/{http → events/http}/pikku-fetch-http-response.test.ts +0 -0
  150. /package/src/{http → events/http}/pikku-fetch-http-response.ts +0 -0
  151. /package/src/{rpc → events/rpc}/rpc-types.ts +0 -0
@@ -0,0 +1,150 @@
1
+ import { CoreAPIFunctionSessionless } from '../../function/functions.types.js'
2
+
3
+ export type PikkuMCP<Tools extends string = any> = {
4
+ // elicitInput: <Input>(message: string) => Promise<{ action: string, content: Input }>
5
+ uri?: string
6
+ sendResourceUpdated: (uri: string) => void
7
+ enableResources: (resources: Record<string, boolean>) => Promise<boolean>
8
+ enablePrompts: (prompts: Record<string, boolean>) => Promise<boolean>
9
+ enableTools: (tools: Record<Tools, boolean>) => Promise<boolean>
10
+ }
11
+
12
+ /**
13
+ * Represents metadata for MCP resources, including name, description, and documentation.
14
+ */
15
+ export type MCPResourceMeta = Record<
16
+ string,
17
+ Omit<CoreMCPResource, 'func'> & {
18
+ pikkuFuncName: string
19
+ inputSchema: string | null
20
+ outputSchema: string | null
21
+ }
22
+ >
23
+
24
+ /**
25
+ * Represents metadata for MCP tools, including name, description, and documentation.
26
+ */
27
+ export type MCPToolMeta = Record<
28
+ string,
29
+ Omit<CoreMCPTool, 'func'> & {
30
+ pikkuFuncName: string
31
+ inputSchema: string | null
32
+ outputSchema: string | null
33
+ }
34
+ >
35
+
36
+ /**
37
+ * Represents metadata for MCP prompts, including name, description, and arguments.
38
+ */
39
+ export type MCPPromptMeta = Record<
40
+ string,
41
+ Omit<CoreMCPPrompt, 'func'> & {
42
+ pikkuFuncName: string
43
+ inputSchema: string | null
44
+ outputSchema: string | null
45
+ arguments: Array<{
46
+ name: string
47
+ description: string
48
+ required: boolean
49
+ }>
50
+ }
51
+ >
52
+
53
+ /**
54
+ * Represents an MCP resource with specific properties.
55
+ */
56
+ export type CoreMCPResource<
57
+ APIFunction = CoreAPIFunctionSessionless<any, any>,
58
+ > = {
59
+ uri: string
60
+ title: string
61
+ description?: string
62
+ mimeType?: string
63
+ size?: number
64
+ streaming?: boolean
65
+ func: APIFunction
66
+ tags?: string[]
67
+ }
68
+
69
+ /**
70
+ * Represents an MCP tool with specific properties.
71
+ */
72
+ export type CoreMCPTool<APIFunction = CoreAPIFunctionSessionless<any, any>> = {
73
+ name: string
74
+ title?: string
75
+ description: string
76
+ annotations?: Record<string, any>
77
+ func: APIFunction
78
+ tags?: string[]
79
+ streaming?: boolean
80
+ }
81
+
82
+ /**
83
+ * Represents an MCP prompt with specific properties.
84
+ */
85
+ export type CoreMCPPrompt<
86
+ APIFunction = CoreAPIFunctionSessionless<any, MCPPromptResponse>,
87
+ > = {
88
+ name: string
89
+ description?: string
90
+ func: APIFunction
91
+ tags?: string[]
92
+ }
93
+
94
+ export type JsonRpcRequest = {
95
+ jsonrpc: string
96
+ id?: string | number | null
97
+ params?: any
98
+ }
99
+
100
+ export type JsonRpcResponse = {
101
+ id?: string | number | null
102
+ result?: any
103
+ }
104
+
105
+ export type JsonRpcErrorResponse = {
106
+ id?: string | number | null
107
+ code: number
108
+ message: string
109
+ data?: any
110
+ }
111
+
112
+ /**
113
+ * Represents a message in an MCP prompt response
114
+ */
115
+ export type MCPPromptMessage = {
116
+ role: 'user' | 'assistant' | 'system'
117
+ content: {
118
+ type: 'text' | 'image'
119
+ text: string
120
+ data?: string // for image content
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Standard response type for MCP prompts - array of messages
126
+ */
127
+ export type MCPPromptResponse = MCPPromptMessage[]
128
+
129
+ export type MCPResourceMessage = {
130
+ uri: string
131
+ text: string
132
+ }
133
+
134
+ export type MCPResourceResponse = MCPResourceMessage[]
135
+
136
+ /**
137
+ * Standard response type for MCP prompts - array of messages
138
+ */
139
+
140
+ export type MCPToolMessage =
141
+ | {
142
+ type: 'text'
143
+ text: string
144
+ }
145
+ | {
146
+ type: 'image'
147
+ data: string // base64 encoded image data
148
+ }
149
+
150
+ export type MCPToolResponse = MCPToolMessage[]
@@ -0,0 +1,18 @@
1
+ // Queue types
2
+ export type * from './queue.types.js'
3
+
4
+ // Queue processor management
5
+ export {
6
+ addQueueWorker,
7
+ runQueueJob,
8
+ getQueueWorkers,
9
+ removeQueueWorker,
10
+ } from './queue-runner.js'
11
+
12
+ // Configuration validation
13
+ export { validateWorkerConfig } from './validate-worker-config.js'
14
+ export type { QueueConfigMapping } from './validate-worker-config.js'
15
+
16
+ // Queue registration helper
17
+ export { registerqueueWorkers } from './register-queue-helper.js'
18
+ export type { QueueRegistrationCallback } from './register-queue-helper.js'
@@ -0,0 +1,125 @@
1
+ import type { CoreServices } from '../../types/core.types.js'
2
+ import type { CoreQueueWorker, QueueJob } from './queue.types.js'
3
+ import type { CoreAPIFunctionSessionless } from '../../function/functions.types.js'
4
+ import { getErrorResponse } from '../../errors/error-handler.js'
5
+ import { pikkuState } from '../../pikku-state.js'
6
+ import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
7
+ import { CreateSessionServices } from '../../types/core.types.js'
8
+
9
+ /**
10
+ * Error class for queue processor not found
11
+ */
12
+ class QueueWorkerNotFoundError extends Error {
13
+ constructor(name: string) {
14
+ super(`Queue processor not found: ${name}`)
15
+ }
16
+ }
17
+ /**
18
+ * Add a queue processor to the system
19
+ */
20
+ export const addQueueWorker = <
21
+ InputData = any,
22
+ OutputData = any,
23
+ APIFunction extends CoreAPIFunctionSessionless<
24
+ InputData,
25
+ OutputData
26
+ > = CoreAPIFunctionSessionless<InputData, OutputData>,
27
+ >(
28
+ queueWorker: CoreQueueWorker<APIFunction>
29
+ ) => {
30
+ // Get processor metadata
31
+ const meta = pikkuState('queue', 'meta')
32
+ const processorMeta = meta[queueWorker.queueName]
33
+ if (!processorMeta) {
34
+ throw new Error(
35
+ `Queue processor metadata not found for '${queueWorker.queueName}'. Make sure to run the CLI to generate metadata.`
36
+ )
37
+ }
38
+
39
+ // Register the function with pikku
40
+ addFunction(processorMeta.pikkuFuncName, {
41
+ func: queueWorker.func,
42
+ })
43
+
44
+ // Store processor definition in state - runtime adapters will pick this up
45
+ const registrations = pikkuState('queue', 'registrations')
46
+ registrations.set(queueWorker.queueName, queueWorker)
47
+ }
48
+
49
+ /**
50
+ * Get all registered queue processors
51
+ */
52
+ export function getQueueWorkers(): Map<string, CoreQueueWorker> {
53
+ return pikkuState('queue', 'registrations')
54
+ }
55
+
56
+ /**
57
+ * Stop and remove a queue processor
58
+ */
59
+ export async function removeQueueWorker(name: string): Promise<void> {
60
+ const registrations = pikkuState('queue', 'registrations')
61
+ const registration = registrations.get(name)
62
+
63
+ if (!registration) {
64
+ throw new QueueWorkerNotFoundError(name)
65
+ }
66
+
67
+ registrations.delete(name)
68
+ }
69
+
70
+ /**
71
+ * Process a single queue job - this function is called by queue consumers
72
+ */
73
+ export async function runQueueJob({
74
+ singletonServices,
75
+ createSessionServices,
76
+ job,
77
+ }: {
78
+ singletonServices: CoreServices
79
+ createSessionServices?: CreateSessionServices
80
+ job: QueueJob
81
+ }): Promise<void> {
82
+ const logger = singletonServices.logger
83
+
84
+ const meta = pikkuState('queue', 'meta')
85
+ const processorMeta = meta[job.queueName]
86
+ if (!processorMeta) {
87
+ throw new Error(`Processor metadata not found for: ${job.queueName}`)
88
+ }
89
+
90
+ try {
91
+ logger.info(`Processing job ${job.id} in queue ${job.queueName}`)
92
+
93
+ // Use provided singleton services
94
+ const getAllServices = () => ({
95
+ ...singletonServices,
96
+ ...(createSessionServices
97
+ ? createSessionServices(singletonServices, {}, undefined)
98
+ : {}),
99
+ })
100
+
101
+ // Execute the pikku function with the job data
102
+ const result = await runPikkuFunc(processorMeta.pikkuFuncName, {
103
+ getAllServices,
104
+ data: job.data,
105
+ })
106
+
107
+ logger.debug(
108
+ `Successfully processed job ${job.id} in queue ${job.queueName}`
109
+ )
110
+ return result
111
+ } catch (error: any) {
112
+ logger.error(
113
+ `Error processing job ${job.id} in queue ${job.queueName}:`,
114
+ error
115
+ )
116
+
117
+ const errorResponse = getErrorResponse(error)
118
+ if (errorResponse != null) {
119
+ logger.error('Processed error response:', errorResponse)
120
+ }
121
+
122
+ // Re-throw the error so the queue service can handle retries/DLQ
123
+ throw error
124
+ }
125
+ }
@@ -0,0 +1,176 @@
1
+ import { APIDocs } from '../../types/core.types.js'
2
+ import { CoreAPIFunctionSessionless } from '../../function/functions.types.js'
3
+ import { QueueConfigMapping } from './validate-worker-config.js'
4
+
5
+ /**
6
+ * Configuration for queue workers - how jobs are processed
7
+ */
8
+ /**
9
+ * Configuration for queue workers - how jobs are processed
10
+ */
11
+ export interface PikkuWorkerConfig {
12
+ /** Optional worker name for identification and monitoring */
13
+ name?: string
14
+ /** Number of messages to process in batch / in parallel */
15
+ batchSize?: number
16
+ /** Number of messages to prefetch for efficiency */
17
+ prefetch?: number
18
+ /** Polling interval for pull-based queues in ms */
19
+ pollInterval?: number
20
+ /** Message visibility timeout in seconds */
21
+ visibilityTimeout?: number
22
+ /** Duration of job lock in milliseconds */
23
+ lockDuration?: number
24
+ /** Number of seconds to wait when queue is empty before polling again */
25
+ drainDelay?: number
26
+ /** Keep N completed jobs for inspection */
27
+ removeOnComplete?: number
28
+ /** Keep N failed jobs for inspection */
29
+ removeOnFail?: number
30
+ /** Maximum number of times a job can be recovered from stalled state */
31
+ maxStalledCount?: number
32
+ /** Condition to start processor at instance creation */
33
+ autorun?: boolean
34
+ }
35
+
36
+ /**
37
+ * Configuration for individual jobs - how jobs behave
38
+ */
39
+ export interface PikkuJobConfig {
40
+ /** Maximum retry attempts for failed jobs */
41
+ retryAttempts?: number
42
+ /** Initial retry delay in milliseconds */
43
+ retryDelay?: number
44
+ /** Retry backoff strategy */
45
+ retryBackoff?: 'linear' | 'exponential' | 'fixed'
46
+ /** Queue for failed messages after max retries */
47
+ deadLetterQueue?: string
48
+ /** How long to retain completed jobs in seconds */
49
+ messageRetention?: number
50
+ /** Job priority (higher numbers = higher priority) */
51
+ priority?: number
52
+ /** Enable FIFO ordering where supported */
53
+ fifo?: boolean
54
+ /** Job timeout in milliseconds */
55
+ timeout?: number
56
+ /** Delay before job execution in milliseconds */
57
+ delay?: number
58
+ }
59
+
60
+ /**
61
+ * Configuration validation result with warnings and fallbacks
62
+ */
63
+ export interface ConfigValidationResult {
64
+ applied: Partial<PikkuWorkerConfig>
65
+ ignored: Partial<PikkuWorkerConfig>
66
+ warnings: string[]
67
+ fallbacks: { [key: string]: any }
68
+ }
69
+
70
+ /**
71
+ * Queue job representation
72
+ */
73
+ export type QueueJobStatus =
74
+ | 'waiting'
75
+ | 'active'
76
+ | 'completed'
77
+ | 'failed'
78
+ | 'delayed'
79
+
80
+ export type QueueJobMetadata = {
81
+ progress?: number | string | object | undefined | boolean
82
+ attemptsMade?: number
83
+ maxAttempts?: number
84
+ processedAt?: Date
85
+ completedAt?: Date
86
+ failedAt?: Date
87
+ error?: string
88
+ createdAt: Date
89
+ }
90
+
91
+ export interface QueueJob<T = any, R = any> {
92
+ id: string
93
+ queueName: string
94
+ status: () => Promise<QueueJobStatus> | QueueJobStatus
95
+ data: T
96
+ result?: R
97
+ waitForCompletion?: (ttl?: number) => Promise<R>
98
+ metadata?: () => Promise<QueueJobMetadata> | QueueJobMetadata
99
+ }
100
+
101
+ /**
102
+ * Job options for queue operations
103
+ */
104
+ export interface JobOptions {
105
+ priority?: number
106
+ delay?: number
107
+ attempts?: number
108
+ backoff?: string | { type: string; delay?: number }
109
+ removeOnComplete?: number
110
+ removeOnFail?: number
111
+ jobId?: string
112
+ }
113
+
114
+ /**
115
+ * Queue provider interface for job publishing operations
116
+ */
117
+ export interface QueueService {
118
+ /** Whether this queue provider supports job results */
119
+ readonly supportsResults: boolean
120
+
121
+ /** Add a job to the queue with type safety */
122
+ add<T>(queueName: string, data: T, options?: JobOptions): Promise<string>
123
+
124
+ /** Get job status and result */
125
+ getJob<T, R>(queueName: string, jobId: string): Promise<QueueJob<T, R> | null>
126
+ }
127
+
128
+ /**
129
+ * Queue service interface that queue adapters implement
130
+ */
131
+ export interface QueueWorkers {
132
+ /** Service name identifier */
133
+ name: string
134
+
135
+ /** Whether this queue service supports job results */
136
+ supportsResults: boolean
137
+
138
+ /** Configuration mapping for validation */
139
+ configMappings: QueueConfigMapping
140
+
141
+ /** Scan state and register all compatible processors */
142
+ registerQueues(): Promise<Record<string, ConfigValidationResult[]>>
143
+
144
+ /** Close all queues and connections */
145
+ close(): Promise<void>
146
+ }
147
+
148
+ /**
149
+ * Queue processor metadata
150
+ */
151
+ export type queueWorkersMeta = Record<
152
+ string,
153
+ {
154
+ pikkuFuncName: string
155
+ schemaName?: string
156
+ queueName: string
157
+ session?: undefined
158
+ docs?: APIDocs
159
+ tags?: string[]
160
+ config?: PikkuWorkerConfig
161
+ }
162
+ >
163
+
164
+ /**
165
+ * Core queue processor definition
166
+ */
167
+ export type CoreQueueWorker<
168
+ APIFunction = CoreAPIFunctionSessionless<any, any>,
169
+ > = {
170
+ queueName: string
171
+ func: APIFunction
172
+ config?: PikkuWorkerConfig
173
+ docs?: APIDocs
174
+ session?: undefined
175
+ tags?: string[]
176
+ }
@@ -0,0 +1,62 @@
1
+ import type { ConfigValidationResult, CoreQueueWorker } from './queue.types.js'
2
+ import { getQueueWorkers } from './queue-runner.js'
3
+ import {
4
+ QueueConfigMapping,
5
+ validateWorkerConfig,
6
+ } from './validate-worker-config.js'
7
+ import { Logger } from '../../services/logger.js'
8
+
9
+ /**
10
+ * Queue processor registration callback
11
+ */
12
+ export type QueueRegistrationCallback<T = any> = (
13
+ queueName: string,
14
+ processor: CoreQueueWorker
15
+ ) => Promise<T>
16
+
17
+ /**
18
+ * Helper function to register queue processors with validation
19
+ * This centralizes the common logic for looping over processors and validating configs
20
+ *
21
+ * @param configMappings - Configuration mapping for the queue implementation
22
+ * @param registerCallback - Callback to register each individual queue processor
23
+ * @param logger - Optional logger for info/error messages
24
+ * @returns Record of validation results by queue name
25
+ */
26
+ export async function registerqueueWorkers<T = any>(
27
+ configMappings: QueueConfigMapping,
28
+ logger: Logger,
29
+ registerCallback: QueueRegistrationCallback<T>
30
+ ): Promise<Record<string, ConfigValidationResult[]>> {
31
+ const configValidation: Record<string, ConfigValidationResult[]> = {}
32
+ const queueWorkers = getQueueWorkers()
33
+
34
+ for (const [queueName, processor] of queueWorkers) {
35
+ logger?.info(`Registering queue processor: ${queueName}`)
36
+ // Validate the processor configuration
37
+ const validationResult = validateWorkerConfig(
38
+ configMappings,
39
+ processor.config
40
+ )
41
+
42
+ // Store validation results
43
+ configValidation[queueName] = configValidation[queueName] || []
44
+ configValidation[queueName].push(validationResult)
45
+
46
+ if (validationResult.warnings.length > 0) {
47
+ logger?.warn(
48
+ `Configuration warnings for queue ${queueName}:`,
49
+ validationResult.warnings
50
+ )
51
+ }
52
+
53
+ try {
54
+ await registerCallback(queueName, processor)
55
+ logger?.info(`Successfully registered queue processor: ${queueName}`)
56
+ } catch (error) {
57
+ logger?.error(`Failed to register queue processor ${queueName}:`, error)
58
+ }
59
+ }
60
+
61
+ return configValidation
62
+ }
@@ -0,0 +1,113 @@
1
+ import { PikkuWorkerConfig, ConfigValidationResult } from './queue.types.js'
2
+
3
+ /**
4
+ * Configuration mapping structure for queue implementations
5
+ */
6
+ export interface QueueConfigMapping {
7
+ /** Configurations that are directly supported */
8
+ supported: Partial<
9
+ Record<
10
+ keyof PikkuWorkerConfig,
11
+ {
12
+ /** The property name in the underlying queue system */
13
+ queueProperty?: string
14
+ /** Optional transform function for the value */
15
+ transform?: (value: any) => any
16
+ /** Description of what this configuration does */
17
+ description: string
18
+ }
19
+ >
20
+ >
21
+
22
+ /** Configurations that are not supported */
23
+ unsupported: Partial<
24
+ Record<
25
+ keyof PikkuWorkerConfig,
26
+ {
27
+ /** Why this configuration is not supported */
28
+ reason: string
29
+ /** Detailed explanation of what the queue system does instead */
30
+ explanation: string
31
+ }
32
+ >
33
+ >
34
+
35
+ /** Configurations that have partial support or workarounds */
36
+ fallbacks: Partial<
37
+ Record<
38
+ keyof PikkuWorkerConfig,
39
+ {
40
+ /** Why this configuration uses a fallback */
41
+ reason: string
42
+ /** Detailed explanation of the fallback behavior */
43
+ explanation: string
44
+ /** The fallback value or description */
45
+ fallbackValue: string
46
+ }
47
+ >
48
+ >
49
+ }
50
+
51
+ /**
52
+ * Validates worker configuration using a mapping table
53
+ * This provides a flexible, maintainable way to validate configurations
54
+ * across different queue implementations
55
+ *
56
+ * @param config - The worker configuration to validate
57
+ * @param configMapping - The mapping table defining supported/unsupported configurations
58
+ * @returns Validation result with applied, ignored, warnings, and fallbacks
59
+ */
60
+ export function validateWorkerConfig(
61
+ configMapping: QueueConfigMapping,
62
+ config: PikkuWorkerConfig = {}
63
+ ): ConfigValidationResult {
64
+ const applied: Partial<PikkuWorkerConfig> = {}
65
+ const ignored: Partial<PikkuWorkerConfig> = {}
66
+ const warnings: string[] = []
67
+ const fallbacks: { [key: string]: any } = {}
68
+
69
+ // Process each configuration property
70
+ for (const [key, value] of Object.entries(config)) {
71
+ if (value === undefined) continue
72
+
73
+ const configKey = key as keyof PikkuWorkerConfig
74
+
75
+ // Check if it's a supported configuration
76
+ if (configKey in configMapping.supported) {
77
+ applied[configKey] = value
78
+ continue
79
+ }
80
+
81
+ // Check if it's a fallback configuration
82
+ if (configKey in configMapping.fallbacks) {
83
+ const fallbackMapping = configMapping.fallbacks[configKey]!
84
+ applied[configKey] = value
85
+ fallbacks[key] = fallbackMapping.fallbackValue
86
+ warnings.push(
87
+ `${key}: ${fallbackMapping.reason}. ${fallbackMapping.explanation}`
88
+ )
89
+ continue
90
+ }
91
+
92
+ // Check if it's an unsupported configuration
93
+ if (configKey in configMapping.unsupported) {
94
+ ignored[configKey] = value
95
+ const mapping = configMapping.unsupported[configKey]!
96
+ warnings.push(`${key}: ${mapping.reason}. ${mapping.explanation}`)
97
+ continue
98
+ }
99
+
100
+ // Unknown configuration
101
+ ignored[configKey] = value
102
+ warnings.push(
103
+ `${key}: Unknown configuration option for this queue implementation`
104
+ )
105
+ }
106
+
107
+ return {
108
+ applied,
109
+ ignored,
110
+ warnings,
111
+ fallbacks,
112
+ }
113
+ }
@@ -0,0 +1,2 @@
1
+ export { initialize } from './rpc-runner.js'
2
+ export type { PikkuRPC, RPCMeta } from './rpc-types.js'
@@ -1,6 +1,6 @@
1
- import { CoreServices } from '../types/core.types.js'
2
- import { runPikkuFunc } from '../function/function-runner.js'
3
- import { pikkuState } from '../pikku-state.js'
1
+ import { CoreServices } from '../../types/core.types.js'
2
+ import { runPikkuFunc } from '../../function/function-runner.js'
3
+ import { pikkuState } from '../../pikku-state.js'
4
4
  import { RPCMeta } from './rpc-types.js'
5
5
 
6
6
  // Type for the RPC service configuration
@@ -0,0 +1,9 @@
1
+ export * from './scheduler.types.js'
2
+
3
+ export {
4
+ runScheduledTask,
5
+ addScheduledTask,
6
+ getScheduledTasks,
7
+ } from './scheduler-runner.js'
8
+
9
+ export * from './log-schedulers.js'
@@ -1,5 +1,5 @@
1
- import { pikkuState } from '../pikku-state.js'
2
- import { Logger } from '../services/index.js'
1
+ import { pikkuState } from '../../pikku-state.js'
2
+ import { Logger } from '../../services/index.js'
3
3
 
4
4
  /**
5
5
  * Logs all the loaded scheduled tasks.