@pikku/core 0.7.8 → 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 (165) hide show
  1. package/CHANGELOG.md +26 -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 +4 -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 +3 -0
  23. package/dist/events/mcp/index.js +3 -0
  24. package/dist/events/mcp/mcp-endpoint-registry.d.ts +48 -0
  25. package/dist/events/mcp/mcp-endpoint-registry.js +122 -0
  26. package/dist/events/mcp/mcp-runner.d.ts +30 -0
  27. package/dist/events/mcp/mcp-runner.js +192 -0
  28. package/dist/events/mcp/mcp.types.d.ts +117 -0
  29. package/dist/events/queue/index.d.ts +6 -0
  30. package/dist/events/queue/index.js +6 -0
  31. package/dist/events/queue/queue-runner.d.ts +24 -0
  32. package/dist/events/queue/queue-runner.js +83 -0
  33. package/dist/events/queue/queue.types.d.ts +154 -0
  34. package/dist/events/queue/register-queue-helper.d.ts +17 -0
  35. package/dist/events/queue/register-queue-helper.js +34 -0
  36. package/dist/events/queue/validate-worker-config.d.ts +41 -0
  37. package/dist/events/queue/validate-worker-config.js +50 -0
  38. package/dist/events/rpc/index.d.ts +2 -0
  39. package/dist/events/rpc/rpc-runner.d.ts +25 -0
  40. package/dist/{rpc → events/rpc}/rpc-runner.js +2 -2
  41. package/dist/events/scheduler/index.d.ts +3 -0
  42. package/dist/events/scheduler/index.js +3 -0
  43. package/dist/{scheduler → events/scheduler}/log-schedulers.d.ts +1 -1
  44. package/dist/{scheduler → events/scheduler}/log-schedulers.js +1 -1
  45. package/dist/{scheduler → events/scheduler}/scheduler-runner.d.ts +4 -3
  46. package/dist/{scheduler → events/scheduler}/scheduler-runner.js +7 -4
  47. package/dist/{scheduler → events/scheduler}/scheduler.types.d.ts +3 -4
  48. package/dist/function/function-runner.d.ts +3 -2
  49. package/dist/function/function-runner.js +16 -40
  50. package/dist/function/functions.types.d.ts +3 -2
  51. package/dist/handle-error.d.ts +2 -2
  52. package/dist/handle-error.js +1 -1
  53. package/dist/index.d.ts +15 -7
  54. package/dist/index.js +15 -7
  55. package/dist/middleware-runner.d.ts +4 -4
  56. package/dist/middleware-runner.js +3 -1
  57. package/dist/pikku-state.d.ts +18 -4
  58. package/dist/pikku-state.js +12 -0
  59. package/dist/services/index.d.ts +2 -2
  60. package/dist/services/index.js +2 -2
  61. package/dist/services/jwt-service.d.ts +1 -1
  62. package/dist/services/user-session-service.d.ts +1 -1
  63. package/dist/types/core.types.d.ts +17 -14
  64. package/dist/types/core.types.js +3 -1
  65. package/lcov.info +3947 -3184
  66. package/package.json +9 -7
  67. package/src/errors/error-handler.ts +2 -1
  68. package/src/errors/errors.ts +2 -0
  69. package/src/{channel → events/channel}/channel-handler.ts +7 -3
  70. package/src/{channel → events/channel}/channel-runner.ts +5 -5
  71. package/src/{channel → events/channel}/channel-store.ts +1 -1
  72. package/src/{channel → events/channel}/channel.types.ts +3 -3
  73. package/src/{channel → events/channel}/local/local-channel-runner.test.ts +1 -1
  74. package/src/{channel → events/channel}/local/local-channel-runner.ts +7 -7
  75. package/src/{channel → events/channel}/local/local-eventhub-service.test.ts +1 -1
  76. package/src/{channel → events/channel}/log-channels.ts +2 -2
  77. package/src/{channel → events/channel}/serverless/serverless-channel-runner.ts +8 -8
  78. package/src/{http → events/http}/http-runner.test.ts +6 -7
  79. package/src/{http → events/http}/http-runner.ts +9 -9
  80. package/src/{http → events/http}/http.types.ts +3 -3
  81. package/src/{http → events/http}/index.ts +0 -1
  82. package/src/{http → events/http}/log-http-routes.ts +2 -2
  83. package/src/{http → events/http}/pikku-fetch-http-request.ts +1 -1
  84. package/src/events/mcp/index.ts +3 -0
  85. package/src/events/mcp/mcp-endpoint-registry.test.d.ts +1 -0
  86. package/src/events/mcp/mcp-endpoint-registry.test.ts +389 -0
  87. package/src/events/mcp/mcp-endpoint-registry.ts +165 -0
  88. package/src/events/mcp/mcp-runner.ts +321 -0
  89. package/src/events/mcp/mcp.types.ts +150 -0
  90. package/src/events/queue/index.ts +18 -0
  91. package/src/events/queue/queue-runner.ts +125 -0
  92. package/src/events/queue/queue.types.ts +176 -0
  93. package/src/events/queue/register-queue-helper.ts +62 -0
  94. package/src/events/queue/validate-worker-config.ts +113 -0
  95. package/src/events/rpc/index.ts +2 -0
  96. package/src/{rpc → events/rpc}/rpc-runner.ts +3 -3
  97. package/src/events/scheduler/index.ts +9 -0
  98. package/src/{scheduler → events/scheduler}/log-schedulers.ts +2 -2
  99. package/src/{scheduler → events/scheduler}/scheduler-runner.ts +11 -10
  100. package/src/{scheduler → events/scheduler}/scheduler.types.ts +2 -4
  101. package/src/function/function-runner.ts +38 -65
  102. package/src/function/functions.types.ts +3 -1
  103. package/src/handle-error.ts +2 -2
  104. package/src/index.ts +28 -7
  105. package/src/middleware/auth-apikey.ts +1 -1
  106. package/src/middleware/auth-bearer.ts +1 -1
  107. package/src/middleware/auth-cookie.ts +1 -1
  108. package/src/middleware-runner.ts +14 -7
  109. package/src/pikku-state.ts +40 -4
  110. package/src/services/index.ts +2 -2
  111. package/src/services/jwt-service.ts +1 -1
  112. package/src/services/user-session-service.ts +1 -1
  113. package/src/types/core.types.ts +24 -13
  114. package/tsconfig.json +3 -2
  115. package/tsconfig.tsbuildinfo +1 -1
  116. package/dist/rpc/index.d.ts +0 -2
  117. package/dist/rpc/rpc-runner.d.ts +0 -27
  118. package/dist/scheduler/index.d.ts +0 -3
  119. package/dist/scheduler/index.js +0 -3
  120. package/src/http/incomingmessage-to-request-convertor.ts +0 -0
  121. package/src/rpc/index.ts +0 -2
  122. package/src/scheduler/index.ts +0 -5
  123. /package/dist/{channel → events/channel}/channel-store.js +0 -0
  124. /package/dist/{channel → events/channel}/channel.types.js +0 -0
  125. /package/dist/{channel → events/channel}/eventhub-service.d.ts +0 -0
  126. /package/dist/{channel → events/channel}/eventhub-service.js +0 -0
  127. /package/dist/{channel → events/channel}/eventhub-store.d.ts +0 -0
  128. /package/dist/{channel → events/channel}/eventhub-store.js +0 -0
  129. /package/dist/{channel → events/channel}/index.d.ts +0 -0
  130. /package/dist/{channel → events/channel}/index.js +0 -0
  131. /package/dist/{channel → events/channel}/local/index.d.ts +0 -0
  132. /package/dist/{channel → events/channel}/local/index.js +0 -0
  133. /package/dist/{channel → events/channel}/local/local-channel-handler.d.ts +0 -0
  134. /package/dist/{channel → events/channel}/local/local-channel-handler.js +0 -0
  135. /package/dist/{channel → events/channel}/local/local-channel-runner.d.ts +0 -0
  136. /package/dist/{channel → events/channel}/local/local-eventhub-service.d.ts +0 -0
  137. /package/dist/{channel → events/channel}/local/local-eventhub-service.js +0 -0
  138. /package/dist/{channel → events/channel}/pikku-abstract-channel-handler.d.ts +0 -0
  139. /package/dist/{channel → events/channel}/pikku-abstract-channel-handler.js +0 -0
  140. /package/dist/{channel → events/channel}/serverless/index.d.ts +0 -0
  141. /package/dist/{channel → events/channel}/serverless/index.js +0 -0
  142. /package/dist/{channel → events/channel}/serverless/serverless-channel-runner.d.ts +0 -0
  143. /package/dist/{http → events/http}/http.types.js +0 -0
  144. /package/dist/{http → events/http}/pikku-fetch-http-request.d.ts +0 -0
  145. /package/dist/{http → events/http}/pikku-fetch-http-response.d.ts +0 -0
  146. /package/dist/{http → events/http}/pikku-fetch-http-response.js +0 -0
  147. /package/dist/{http/incomingmessage-to-request-convertor.d.ts → events/mcp/mcp.types.js} +0 -0
  148. /package/dist/{http/incomingmessage-to-request-convertor.js → events/queue/queue.types.js} +0 -0
  149. /package/dist/{rpc → events/rpc}/index.js +0 -0
  150. /package/dist/{rpc → events/rpc}/rpc-types.d.ts +0 -0
  151. /package/dist/{rpc → events/rpc}/rpc-types.js +0 -0
  152. /package/dist/{scheduler → events/scheduler}/scheduler.types.js +0 -0
  153. /package/src/{channel → events/channel}/eventhub-service.ts +0 -0
  154. /package/src/{channel → events/channel}/eventhub-store.ts +0 -0
  155. /package/src/{channel → events/channel}/index.ts +0 -0
  156. /package/src/{channel → events/channel}/local/index.ts +0 -0
  157. /package/src/{channel → events/channel}/local/local-channel-handler.ts +0 -0
  158. /package/src/{channel → events/channel}/local/local-eventhub-service.ts +0 -0
  159. /package/src/{channel → events/channel}/pikku-abstract-channel-handler.test.ts +0 -0
  160. /package/src/{channel → events/channel}/pikku-abstract-channel-handler.ts +0 -0
  161. /package/src/{channel → events/channel}/serverless/index.ts +0 -0
  162. /package/src/{http → events/http}/pikku-fetch-http-request.test.ts +0 -0
  163. /package/src/{http → events/http}/pikku-fetch-http-response.test.ts +0 -0
  164. /package/src/{http → events/http}/pikku-fetch-http-response.ts +0 -0
  165. /package/src/{rpc → events/rpc}/rpc-types.ts +0 -0
@@ -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.
@@ -3,13 +3,13 @@ import type {
3
3
  CoreSingletonServices,
4
4
  CoreUserSession,
5
5
  CreateSessionServices,
6
- } from '../types/core.types.js'
6
+ } from '../../types/core.types.js'
7
7
  import type { CoreScheduledTask } from './scheduler.types.js'
8
- import type { CoreAPIFunctionSessionless } from '../function/functions.types.js'
9
- import { getErrorResponse } from '../errors/error-handler.js'
10
- import { closeSessionServices } from '../utils.js'
11
- import { pikkuState } from '../pikku-state.js'
12
- import { addFunction, runPikkuFunc } from '../function/function-runner.js'
8
+ import type { CoreAPIFunctionSessionless } from '../../function/functions.types.js'
9
+ import { getErrorResponse } from '../../errors/error-handler.js'
10
+ import { closeSessionServices } from '../../utils.js'
11
+ import { pikkuState } from '../../pikku-state.js'
12
+ import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
13
13
  import { rpcService } from '../rpc/rpc-runner.js'
14
14
 
15
15
  export type RunScheduledTasksParams = {
@@ -50,10 +50,7 @@ class ScheduledTaskNotFoundError extends Error {
50
50
  }
51
51
  }
52
52
 
53
- export async function runScheduledTask<
54
- SingletonServices extends CoreSingletonServices = CoreSingletonServices,
55
- UserSession extends CoreUserSession = CoreUserSession,
56
- >({
53
+ export async function runScheduledTask({
57
54
  name,
58
55
  session,
59
56
  singletonServices,
@@ -108,3 +105,7 @@ export async function runScheduledTask<
108
105
  }
109
106
  }
110
107
  }
108
+
109
+ export const getScheduledTasks = () => {
110
+ return pikkuState('scheduler', 'tasks')
111
+ }
@@ -1,5 +1,5 @@
1
- import { APIDocs, CoreUserSession } from '../types/core.types.js'
2
- import { CoreAPIFunctionSessionless } from '../function/functions.types.js'
1
+ import { APIDocs, CoreUserSession } from '../../types/core.types.js'
2
+ import { CoreAPIFunctionSessionless } from '../../function/functions.types.js'
3
3
 
4
4
  /**
5
5
  * Represents metadata for scheduled tasks, including title, schedule, and documentation.
@@ -22,12 +22,10 @@ export type ScheduledTasksMeta<UserSession extends CoreUserSession = any> =
22
22
  */
23
23
  export type CoreScheduledTask<
24
24
  APIFunction = CoreAPIFunctionSessionless<void, void>,
25
- UserSession extends CoreUserSession = CoreUserSession,
26
25
  > = {
27
26
  name: string
28
27
  schedule: string
29
28
  func: APIFunction
30
29
  docs?: APIDocs
31
- session?: UserSession
32
30
  tags?: string[]
33
31
  }
@@ -1,64 +1,18 @@
1
1
  import { ForbiddenError } from '../errors/errors.js'
2
+ import { runMiddleware } from '../middleware-runner.js'
2
3
  import { verifyPermissions } from '../permissions.js'
3
4
  import { pikkuState } from '../pikku-state.js'
4
5
  import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js'
5
- import { Logger } from '../services/logger.js'
6
- import { CoreServices, CoreUserSession } from '../types/core.types.js'
6
+ import {
7
+ CoreServices,
8
+ CoreUserSession,
9
+ PikkuFunctionMiddleware,
10
+ } from '../types/core.types.js'
7
11
  import {
8
12
  CorePermissionGroup,
9
13
  CorePikkuFunctionConfig,
10
14
  } from './functions.types.js'
11
15
 
12
- // Permission merging function
13
- function mergePermissions(
14
- logger: Logger,
15
- funcName: string,
16
- funcPermissions?: CorePermissionGroup,
17
- transportPermissions?: CorePermissionGroup
18
- ): CorePermissionGroup | undefined {
19
- if (!funcPermissions && !transportPermissions) {
20
- return undefined
21
- }
22
-
23
- if (!funcPermissions) {
24
- return transportPermissions
25
- }
26
-
27
- if (!transportPermissions) {
28
- return funcPermissions
29
- }
30
-
31
- // Start with a copy of function permissions
32
- const mergedPermissions = { ...funcPermissions }
33
-
34
- // Merge in transport permissions
35
- for (const [key, transportValue] of Object.entries(transportPermissions)) {
36
- if (key in mergedPermissions) {
37
- // For permission arrays, concatenate and deduplicate values
38
- if (
39
- Array.isArray(mergedPermissions[key]) &&
40
- Array.isArray(transportValue)
41
- ) {
42
- mergedPermissions[key] = [
43
- ...new Set([...mergedPermissions[key], ...transportValue]),
44
- ]
45
- }
46
- // For other types, warn about conflict and use the more restrictive (transport-level) value
47
- else {
48
- logger.warn(
49
- `Permission conflict on key "${key}" for function "${funcName}". Using transport-level permission.`
50
- )
51
- mergedPermissions[key] = transportValue
52
- }
53
- } else {
54
- // If key doesn't exist in function permissions, add it
55
- mergedPermissions[key] = transportValue
56
- }
57
- }
58
-
59
- return mergedPermissions
60
- }
61
-
62
16
  export const addFunction = (
63
17
  funcName: string,
64
18
  funcConfig: CorePikkuFunctionConfig<any, any>
@@ -86,12 +40,14 @@ export const runPikkuFunc = async <In = any, Out = any>(
86
40
  data,
87
41
  session,
88
42
  permissions: transportPermissions,
43
+ middleware: transportMiddleware,
89
44
  coerceDataFromSchema,
90
45
  }: {
91
46
  getAllServices: () => Promise<CoreServices> | CoreServices
92
47
  data: In
93
48
  session?: CoreUserSession
94
49
  permissions?: CorePermissionGroup
50
+ middleware?: PikkuFunctionMiddleware[]
95
51
  coerceDataFromSchema?: boolean
96
52
  }
97
53
  ): Promise<Out> => {
@@ -127,23 +83,40 @@ export const runPikkuFunc = async <In = any, Out = any>(
127
83
  }
128
84
  }
129
85
 
130
- // Execute permission checks
131
- const mergedPermissions = mergePermissions(
132
- allServices.logger,
133
- funcName,
134
- funcConfig.permissions,
135
- transportPermissions
136
- )
137
- const permissioned = await verifyPermissions(
138
- mergedPermissions,
139
- allServices,
140
- data,
141
- session
142
- )
86
+ let permissioned = true
87
+ if (funcConfig.permissions) {
88
+ permissioned = await verifyPermissions(
89
+ funcConfig.permissions,
90
+ allServices,
91
+ data,
92
+ session
93
+ )
94
+ }
95
+ if (!permissioned && transportPermissions) {
96
+ permissioned = await verifyPermissions(
97
+ transportPermissions,
98
+ allServices,
99
+ data,
100
+ session
101
+ )
102
+ }
143
103
 
144
104
  if (permissioned === false) {
145
105
  throw new ForbiddenError('Permission denied')
146
106
  }
147
107
 
108
+ if (transportMiddleware || funcConfig.middleware) {
109
+ return (await runMiddleware<PikkuFunctionMiddleware>(
110
+ allServices,
111
+ {
112
+ http: allServices.http,
113
+ mcp: allServices.mcp,
114
+ rpc: allServices.rpc,
115
+ },
116
+ [...(transportMiddleware || []), ...(funcConfig.middleware || [])],
117
+ async () => await funcConfig.func(allServices, data, session!)
118
+ )) as Out
119
+ }
120
+
148
121
  return (await funcConfig.func(allServices, data, session!)) as Out
149
122
  }
@@ -1,8 +1,9 @@
1
- import { PikkuChannel } from '../channel/channel.types.js'
1
+ import { PikkuChannel } from '../events/channel/channel.types.js'
2
2
  import type {
3
3
  CoreServices,
4
4
  CoreSingletonServices,
5
5
  CoreUserSession,
6
+ PikkuFunctionMiddleware,
6
7
  } from '../types/core.types.js'
7
8
 
8
9
  /**
@@ -85,4 +86,5 @@ export type CorePikkuFunctionConfig<
85
86
  func: APIFunction
86
87
  auth?: boolean
87
88
  permissions?: CorePermissionGroup<APIPermission>
89
+ middleware?: PikkuFunctionMiddleware[]
88
90
  }
@@ -1,7 +1,7 @@
1
1
  import { getErrorResponse } from './errors/error-handler.js'
2
2
  import { NotFoundError } from './errors/errors.js'
3
3
  import { Logger } from './services/logger.js'
4
- import { PikkuHTTP } from './http/http.types.js'
4
+ import { PikkuHTTP } from './events/http/http.types.js'
5
5
 
6
6
  /**
7
7
  * Handle errors that occur during route processing
@@ -14,7 +14,7 @@ import { PikkuHTTP } from './http/http.types.js'
14
14
  * @param {boolean} respondWith404 - Whether to respond with 404 for NotFoundError
15
15
  * @param {boolean} bubbleError - Whether to throw the error after handling
16
16
  */
17
- export const handleError = (
17
+ export const handleHTTPError = (
18
18
  e: any,
19
19
  http: PikkuHTTP | undefined,
20
20
  trackerId: string | undefined,
package/src/index.ts CHANGED
@@ -5,16 +5,37 @@ export * from './types/core.types.js'
5
5
  export * from './function/index.js'
6
6
  export * from './pikku-request.js'
7
7
  export * from './pikku-response.js'
8
- export * from './services/index.js'
9
- export * from './http/index.js'
10
- export * from './channel/index.js'
11
- export * from './scheduler/index.js'
8
+ export * from './services/logger.js'
9
+ export * from './services/schema-service.js'
10
+ export * from './services/jwt-service.js'
11
+ export * from './services/secret-service.js'
12
+ export * from './services/user-session-service.js'
13
+ export * from './events/http/index.js'
14
+ export * from './events/channel/index.js'
15
+ export * from './events/scheduler/index.js'
16
+ export * from './events/rpc/index.js'
17
+ export * from './events/queue/index.js'
18
+ export * from './events/mcp/index.js'
12
19
  export * from './errors/index.js'
13
20
  export * from './middleware/index.js'
14
21
  export * from './time-utils.js'
15
22
  export * from './utils.js'
16
23
  export { pikkuState } from './pikku-state.js'
17
24
  export { runMiddleware } from './middleware-runner.js'
18
- export { addHTTPRoute, addMiddleware } from './http/http-runner.js'
19
- export { addChannel } from './channel/channel-runner.js'
20
- export { addScheduledTask } from './scheduler/scheduler-runner.js'
25
+ export { addHTTPRoute, addMiddleware } from './events/http/http-runner.js'
26
+ export { addChannel } from './events/channel/channel-runner.js'
27
+ export { addScheduledTask } from './events/scheduler/scheduler-runner.js'
28
+ export {
29
+ addMCPResource,
30
+ addMCPTool,
31
+ addMCPPrompt,
32
+ runMCPResource,
33
+ runMCPTool,
34
+ runMCPPrompt,
35
+ getMCPTools,
36
+ getMCPResources,
37
+ getMCPPrompts,
38
+ getMCPResourcesMeta,
39
+ getMCPToolsMeta,
40
+ getMCPPromptsMeta,
41
+ } from './events/mcp/mcp-runner.js'
@@ -33,7 +33,7 @@ export const authAPIKey = <
33
33
  }
34
34
  )) => {
35
35
  const middleware: PikkuMiddleware = async (services, { http }, next) => {
36
- const { userSession: userSessionService, jwt: jwtService } = services
36
+ const { userSession: userSessionService, jwt: jwtService } = services as any
37
37
  if (!http?.request || userSessionService.get()) {
38
38
  return next()
39
39
  }
@@ -28,7 +28,7 @@ export const authBearer = <
28
28
  ) => Promise<UserSession> | UserSession
29
29
  } = {}): PikkuMiddleware => {
30
30
  const middleware: PikkuMiddleware = async (services, { http }, next) => {
31
- const { userSession: userSessionService, jwt: jwtService } = services
31
+ const { userSession: userSessionService, jwt: jwtService } = services as any
32
32
  // Skip if session already exists.
33
33
  if (!http?.request || userSessionService.get()) {
34
34
  return next()