@pikku/core 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/errors/error-handler.js +3 -3
  3. package/dist/errors/errors.d.ts +1 -1
  4. package/dist/errors/errors.js +3 -3
  5. package/dist/function/function-runner.d.ts +8 -8
  6. package/dist/function/function-runner.js +88 -23
  7. package/dist/function/functions.types.d.ts +104 -33
  8. package/dist/function/functions.types.js +50 -7
  9. package/dist/handle-error.d.ts +1 -1
  10. package/dist/handle-error.js +1 -1
  11. package/dist/index.d.ts +6 -2
  12. package/dist/index.js +5 -2
  13. package/dist/middleware/auth-apikey.d.ts +1 -1
  14. package/dist/middleware/auth-apikey.js +3 -3
  15. package/dist/middleware/auth-bearer.d.ts +1 -1
  16. package/dist/middleware/auth-bearer.js +3 -3
  17. package/dist/middleware/auth-cookie.d.ts +1 -1
  18. package/dist/middleware/auth-cookie.js +5 -5
  19. package/dist/middleware/timeout.d.ts +1 -1
  20. package/dist/middleware/timeout.js +3 -2
  21. package/dist/middleware-runner.d.ts +6 -20
  22. package/dist/middleware-runner.js +19 -20
  23. package/dist/permissions.d.ts +6 -89
  24. package/dist/permissions.js +24 -81
  25. package/dist/pikku-state.d.ts +32 -104
  26. package/dist/pikku-state.js +140 -66
  27. package/dist/schema.d.ts +8 -6
  28. package/dist/schema.js +25 -13
  29. package/dist/services/user-session-service.d.ts +7 -3
  30. package/dist/services/user-session-service.js +8 -1
  31. package/dist/services/workflow-service.d.ts +38 -0
  32. package/dist/services/workflow-service.js +1 -0
  33. package/dist/types/core.types.d.ts +40 -41
  34. package/dist/types/core.types.js +4 -15
  35. package/dist/types/state.types.d.ts +135 -0
  36. package/dist/types/state.types.js +1 -0
  37. package/dist/utils.d.ts +9 -1
  38. package/dist/utils.js +48 -3
  39. package/dist/wirings/channel/channel-common.js +2 -3
  40. package/dist/wirings/channel/channel-handler.d.ts +3 -2
  41. package/dist/wirings/channel/channel-handler.js +7 -10
  42. package/dist/wirings/channel/channel-runner.d.ts +2 -2
  43. package/dist/wirings/channel/channel-runner.js +5 -5
  44. package/dist/wirings/channel/channel.types.d.ts +10 -5
  45. package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
  46. package/dist/wirings/channel/local/local-channel-runner.js +19 -26
  47. package/dist/wirings/channel/log-channels.js +1 -1
  48. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
  49. package/dist/wirings/channel/serverless/serverless-channel-runner.js +43 -48
  50. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -2
  51. package/dist/wirings/cli/cli-runner.d.ts +5 -5
  52. package/dist/wirings/cli/cli-runner.js +20 -38
  53. package/dist/wirings/cli/cli.types.d.ts +16 -11
  54. package/dist/wirings/forge-node/forge-node.types.d.ts +120 -0
  55. package/dist/wirings/forge-node/forge-node.types.js +38 -0
  56. package/dist/wirings/forge-node/index.d.ts +1 -0
  57. package/dist/wirings/forge-node/index.js +1 -0
  58. package/dist/wirings/http/http-runner.d.ts +8 -8
  59. package/dist/wirings/http/http-runner.js +46 -51
  60. package/dist/wirings/http/http.types.d.ts +19 -11
  61. package/dist/wirings/http/log-http-routes.js +1 -1
  62. package/dist/wirings/http/routers/path-to-regex.js +2 -2
  63. package/dist/wirings/mcp/mcp-runner.d.ts +2 -2
  64. package/dist/wirings/mcp/mcp-runner.js +33 -40
  65. package/dist/wirings/mcp/mcp.types.d.ts +6 -0
  66. package/dist/wirings/queue/queue-runner.d.ts +3 -3
  67. package/dist/wirings/queue/queue-runner.js +13 -23
  68. package/dist/wirings/queue/queue.types.d.ts +4 -11
  69. package/dist/wirings/rpc/index.d.ts +1 -1
  70. package/dist/wirings/rpc/index.js +1 -1
  71. package/dist/wirings/rpc/rpc-runner.d.ts +17 -16
  72. package/dist/wirings/rpc/rpc-runner.js +98 -61
  73. package/dist/wirings/rpc/rpc-types.d.ts +7 -0
  74. package/dist/wirings/scheduler/log-schedulers.js +1 -1
  75. package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -3
  76. package/dist/wirings/scheduler/scheduler-runner.js +18 -29
  77. package/dist/wirings/scheduler/scheduler.types.d.ts +3 -8
  78. package/dist/wirings/trigger/index.d.ts +2 -0
  79. package/dist/wirings/trigger/index.js +2 -0
  80. package/dist/wirings/trigger/trigger-runner.d.ts +29 -0
  81. package/dist/wirings/trigger/trigger-runner.js +57 -0
  82. package/dist/wirings/trigger/trigger.types.d.ts +42 -0
  83. package/dist/wirings/trigger/trigger.types.js +1 -0
  84. package/dist/wirings/workflow/dsl/index.d.ts +5 -0
  85. package/dist/wirings/workflow/dsl/index.js +4 -0
  86. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +286 -0
  87. package/dist/wirings/workflow/dsl/workflow-dsl.types.js +5 -0
  88. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +5 -0
  89. package/dist/wirings/workflow/dsl/workflow-runner.js +22 -0
  90. package/dist/wirings/workflow/graph/graph-node.d.ts +122 -0
  91. package/dist/wirings/workflow/graph/graph-node.js +58 -0
  92. package/dist/wirings/workflow/graph/graph-runner.d.ts +35 -0
  93. package/dist/wirings/workflow/graph/graph-runner.js +452 -0
  94. package/dist/wirings/workflow/graph/index.d.ts +3 -0
  95. package/dist/wirings/workflow/graph/index.js +3 -0
  96. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +95 -0
  97. package/dist/wirings/workflow/graph/workflow-graph.types.js +15 -0
  98. package/dist/wirings/workflow/index.d.ts +7 -3
  99. package/dist/wirings/workflow/index.js +6 -3
  100. package/dist/wirings/workflow/pikku-workflow-service.d.ts +108 -10
  101. package/dist/wirings/workflow/pikku-workflow-service.js +274 -165
  102. package/dist/wirings/workflow/wire-workflow.d.ts +42 -0
  103. package/dist/wirings/workflow/wire-workflow.js +53 -0
  104. package/dist/wirings/workflow/workflow-utils.d.ts +23 -0
  105. package/dist/wirings/workflow/workflow-utils.js +66 -0
  106. package/dist/wirings/workflow/workflow.types.d.ts +135 -128
  107. package/package.json +11 -2
  108. package/src/errors/error-handler.ts +3 -3
  109. package/src/errors/errors.ts +3 -3
  110. package/src/factory-functions.test.ts +9 -36
  111. package/src/function/function-runner.test.ts +58 -69
  112. package/src/function/function-runner.ts +130 -37
  113. package/src/function/functions.types.ts +193 -54
  114. package/src/handle-error.ts +1 -1
  115. package/src/index.ts +10 -5
  116. package/src/middleware/auth-apikey.test.ts +360 -0
  117. package/src/middleware/auth-apikey.ts +3 -7
  118. package/src/middleware/auth-bearer.test.ts +447 -0
  119. package/src/middleware/auth-bearer.ts +27 -33
  120. package/src/middleware/auth-cookie.test.ts +525 -0
  121. package/src/middleware/auth-cookie.ts +6 -6
  122. package/src/middleware/timeout.ts +4 -2
  123. package/src/middleware-runner.test.ts +58 -127
  124. package/src/middleware-runner.ts +29 -25
  125. package/src/permissions.test.ts +68 -130
  126. package/src/permissions.ts +41 -100
  127. package/src/pikku-state.ts +156 -201
  128. package/src/schema.ts +42 -13
  129. package/src/services/user-session-service.ts +14 -4
  130. package/src/services/workflow-service.ts +74 -0
  131. package/src/types/core.types.ts +79 -58
  132. package/src/types/state.types.ts +195 -0
  133. package/src/utils.ts +59 -4
  134. package/src/wirings/channel/channel-common.ts +4 -7
  135. package/src/wirings/channel/channel-handler.ts +17 -23
  136. package/src/wirings/channel/channel-runner.ts +7 -7
  137. package/src/wirings/channel/channel.types.ts +14 -11
  138. package/src/wirings/channel/local/local-channel-runner.test.ts +8 -4
  139. package/src/wirings/channel/local/local-channel-runner.ts +23 -38
  140. package/src/wirings/channel/log-channels.ts +1 -1
  141. package/src/wirings/channel/serverless/serverless-channel-runner.ts +53 -79
  142. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -3
  143. package/src/wirings/cli/cli-runner.test.ts +26 -26
  144. package/src/wirings/cli/cli-runner.ts +34 -71
  145. package/src/wirings/cli/cli.types.ts +23 -16
  146. package/src/wirings/forge-node/forge-node.types.ts +135 -0
  147. package/src/wirings/forge-node/index.ts +1 -0
  148. package/src/wirings/http/http-runner.test.ts +10 -10
  149. package/src/wirings/http/http-runner.ts +56 -66
  150. package/src/wirings/http/http.types.ts +19 -14
  151. package/src/wirings/http/log-http-routes.ts +1 -1
  152. package/src/wirings/http/routers/path-to-regex.test.ts +30 -19
  153. package/src/wirings/http/routers/path-to-regex.ts +2 -2
  154. package/src/wirings/mcp/mcp-runner.ts +44 -69
  155. package/src/wirings/mcp/mcp.types.ts +6 -0
  156. package/src/wirings/queue/queue-runner.test.ts +641 -0
  157. package/src/wirings/queue/queue-runner.ts +16 -38
  158. package/src/wirings/queue/queue.types.ts +4 -11
  159. package/src/wirings/rpc/index.ts +1 -1
  160. package/src/wirings/rpc/rpc-runner.ts +129 -77
  161. package/src/wirings/rpc/rpc-types.ts +8 -0
  162. package/src/wirings/scheduler/log-schedulers.ts +1 -1
  163. package/src/wirings/scheduler/scheduler-runner.test.ts +627 -0
  164. package/src/wirings/scheduler/scheduler-runner.ts +29 -55
  165. package/src/wirings/scheduler/scheduler.types.ts +3 -9
  166. package/src/wirings/trigger/index.ts +2 -0
  167. package/src/wirings/trigger/trigger-runner.ts +96 -0
  168. package/src/wirings/trigger/trigger.types.ts +56 -0
  169. package/src/wirings/workflow/dsl/index.ts +30 -0
  170. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +312 -0
  171. package/src/wirings/workflow/dsl/workflow-runner.ts +27 -0
  172. package/src/wirings/workflow/graph/graph-node.ts +227 -0
  173. package/src/wirings/workflow/graph/graph-runner.ts +694 -0
  174. package/src/wirings/workflow/graph/index.ts +3 -0
  175. package/src/wirings/workflow/graph/workflow-graph.types.ts +126 -0
  176. package/src/wirings/workflow/index.ts +60 -12
  177. package/src/wirings/workflow/pikku-workflow-service.ts +401 -195
  178. package/src/wirings/workflow/wire-workflow.ts +94 -0
  179. package/src/wirings/workflow/workflow-utils.ts +120 -0
  180. package/src/wirings/workflow/workflow.types.ts +167 -188
  181. package/tsconfig.tsbuildinfo +1 -1
  182. package/dist/wirings/workflow/workflow-runner.d.ts +0 -35
  183. package/dist/wirings/workflow/workflow-runner.js +0 -68
  184. package/src/wirings/workflow/workflow-runner.ts +0 -85
@@ -1,9 +1,10 @@
1
1
  import type { Logger, LogLevel } from '../services/logger.js'
2
2
  import { VariablesService } from '../services/variables-service.js'
3
+ import { SecretService } from '../services/secret-service.js'
3
4
  import { SchemaService } from '../services/schema-service.js'
4
5
  import { JWTService } from '../services/jwt-service.js'
5
6
  import { PikkuHTTP } from '../wirings/http/http.types.js'
6
- import { UserSessionService } from '../services/user-session-service.js'
7
+ import { SessionService } from '../services/user-session-service.js'
7
8
  import { PikkuChannel } from '../wirings/channel/channel.types.js'
8
9
  import { PikkuRPC } from '../wirings/rpc/rpc-types.js'
9
10
  import { PikkuMCP } from '../wirings/mcp/mcp.types.js'
@@ -11,23 +12,24 @@ import { PikkuScheduledTask } from '../wirings/scheduler/scheduler.types.js'
11
12
  import { PikkuQueue, QueueService } from '../wirings/queue/queue.types.js'
12
13
  import { PikkuCLI } from '../wirings/cli/cli.types.js'
13
14
  import {
14
- PikkuWorkflowInteraction,
15
+ PikkuWorkflowWire,
15
16
  WorkflowService,
16
17
  WorkflowServiceConfig,
17
- WorkflowStepInteraction,
18
+ WorkflowStepWire,
18
19
  } from '../wirings/workflow/workflow.types.js'
20
+ import type { PikkuGraphWire } from '../wirings/workflow/graph/workflow-graph.types.js'
21
+ import { PikkuTrigger } from '../wirings/trigger/trigger.types.js'
19
22
  import { SchedulerService } from '../services/scheduler-service.js'
20
23
 
21
- export enum PikkuWiringTypes {
22
- http = 'http',
23
- scheduler = 'scheduler',
24
- channel = 'channel',
25
- rpc = 'rpc',
26
- queue = 'queue',
27
- mcp = 'mcp',
28
- cli = 'cli',
29
- workflow = 'workflow',
30
- }
24
+ export type PikkuWiringTypes =
25
+ | 'http'
26
+ | 'scheduler'
27
+ | 'channel'
28
+ | 'rpc'
29
+ | 'queue'
30
+ | 'mcp'
31
+ | 'cli'
32
+ | 'workflow'
31
33
 
32
34
  export interface FunctionServicesMeta {
33
35
  optimized: boolean
@@ -85,17 +87,18 @@ export type FunctionRuntimeMeta = {
85
87
  }
86
88
 
87
89
  export type FunctionMeta = FunctionRuntimeMeta &
88
- Partial<{
89
- name: string
90
- services: FunctionServicesMeta
91
- inputs: string[] | null
92
- outputs: string[] | null
93
- tags: string[]
94
- docs: PikkuDocs
95
- isDirectFunction: boolean // true if it's pikkuFunc(fn), false if it's pikkuFunc({ func: fn })
96
- middleware: MiddlewareMetadata[] // Function-level middleware
97
- permissions: PermissionMetadata[] // Function-level permissions
98
- }>
90
+ Partial<
91
+ {
92
+ name: string
93
+ services: FunctionServicesMeta
94
+ usedWires: string[]
95
+ inputs: string[] | null
96
+ outputs: string[] | null
97
+ middleware: MiddlewareMetadata[]
98
+ permissions: PermissionMetadata[]
99
+ isDirectFunction: boolean
100
+ } & CommonWireMeta
101
+ >
99
102
 
100
103
  export type FunctionsRuntimeMeta = Record<string, FunctionRuntimeMeta>
101
104
  export type FunctionsMeta = Record<string, FunctionMeta>
@@ -169,6 +172,8 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
169
172
  logger: Logger
170
173
  /** The variable service to be used */
171
174
  variables: VariablesService
175
+ /** The secrets service to retrieve secrets */
176
+ secrets: SecretService
172
177
  /** The workflow orchestrator service */
173
178
  workflowService?: WorkflowService
174
179
  /** The queue service */
@@ -178,31 +183,47 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
178
183
  }
179
184
 
180
185
  /**
181
- * Represents different forms of interaction within Pikku and the outside world.
186
+ * Represents different forms of wire within Pikku and the outside world.
182
187
  */
183
- export type PikkuInteraction<In = unknown, Out = unknown> = Partial<{
188
+ export type PikkuWire<
189
+ In = unknown,
190
+ Out = unknown,
191
+ HasInitialSession extends boolean = false,
192
+ UserSession extends CoreUserSession = CoreUserSession,
193
+ TypedRPC extends PikkuRPC = PikkuRPC,
194
+ IsChannel extends true | null = null,
195
+ MCPTools extends string | never = never,
196
+ TypedWorkflow extends PikkuWorkflowWire | never = PikkuWorkflowWire,
197
+ TriggerOutput = unknown,
198
+ > = Partial<{
184
199
  http: PikkuHTTP<In>
185
- mcp: PikkuMCP
186
- rpc: PikkuRPC
187
- channel: PikkuChannel<unknown, Out>
200
+ mcp: PikkuMCP<MCPTools>
201
+ rpc: TypedRPC
202
+ channel: [IsChannel] extends [null]
203
+ ? PikkuChannel<unknown, Out>
204
+ : PikkuChannel<unknown, Out> | undefined
188
205
  scheduledTask: PikkuScheduledTask
189
206
  queue: PikkuQueue
190
207
  cli: PikkuCLI
191
- workflow: PikkuWorkflowInteraction
192
- workflowStep: WorkflowStepInteraction
208
+ workflow: TypedWorkflow
209
+ workflowStep: WorkflowStepWire
210
+ graph: PikkuGraphWire
211
+ trigger: PikkuTrigger<TriggerOutput>
212
+ initialSession: HasInitialSession extends true
213
+ ? UserSession
214
+ : UserSession | undefined
215
+ session: SessionService<UserSession>
193
216
  }>
194
217
 
195
218
  /**
196
- * A function that can wrap an interaction and be called before or after
219
+ * A function that can wrap an wire and be called before or after
197
220
  */
198
221
  export type CorePikkuMiddleware<
199
222
  SingletonServices extends CoreSingletonServices = CoreSingletonServices,
200
223
  UserSession extends CoreUserSession = CoreUserSession,
201
224
  > = (
202
- services: SingletonServices & {
203
- userSession: UserSessionService<UserSession>
204
- },
205
- interactions: PikkuInteraction,
225
+ services: SingletonServices,
226
+ wires: PikkuWire<unknown, unknown, false, UserSession>,
206
227
  next: () => Promise<void>
207
228
  ) => Promise<void>
208
229
 
@@ -218,8 +239,8 @@ export type CorePikkuMiddlewareConfig<
218
239
  > = {
219
240
  /** The middleware function */
220
241
  func: CorePikkuMiddleware<SingletonServices, UserSession>
221
- /** Optional human-readable name for the middleware */
222
- name?: string
242
+ /** Optional human-readable title for the middleware */
243
+ title?: string
223
244
  /** Optional description of what the middleware does */
224
245
  description?: string
225
246
  }
@@ -254,7 +275,7 @@ export type CorePikkuMiddlewareGroup<
254
275
  * ```typescript
255
276
  * // Direct function syntax
256
277
  * export const logMiddleware = pikkuMiddleware(
257
- * async ({ logger }, _interaction, next) => {
278
+ * async ({ logger }, next) => {
258
279
  * logger.info('Request started')
259
280
  * await next()
260
281
  * }
@@ -262,9 +283,9 @@ export type CorePikkuMiddlewareGroup<
262
283
  *
263
284
  * // Configuration object syntax with metadata
264
285
  * export const logMiddleware = pikkuMiddleware({
265
- * name: 'Request Logger',
286
+ * title: 'Request Logger',
266
287
  * description: 'Logs request information',
267
- * func: async ({ logger }, _interaction, next) => {
288
+ * func: async ({ logger }, next) => {
268
289
  * logger.info('Request started')
269
290
  * await next()
270
291
  * }
@@ -292,7 +313,7 @@ export const pikkuMiddleware = <
292
313
  * message,
293
314
  * level = 'info'
294
315
  * }) => {
295
- * return pikkuMiddleware(async ({ logger }, _interaction, next) => {
316
+ * return pikkuMiddleware(async ({ logger }, next) => {
296
317
  * logger[level](message)
297
318
  * await next()
298
319
  * })
@@ -306,20 +327,15 @@ export const pikkuMiddlewareFactory = <In = any>(
306
327
  }
307
328
 
308
329
  /**
309
- * Represents the core services used by Pikku, including singleton services and the request/response interaction.
330
+ * Represents the core services used by Pikku, including singleton services.
310
331
  */
311
- export type CoreServices<
312
- SingletonServices = CoreSingletonServices,
313
- UserSession extends CoreUserSession = CoreUserSession,
314
- > = SingletonServices &
315
- PikkuInteraction & {
316
- userSession?: UserSessionService<UserSession>
317
- }
332
+ export type CoreServices<SingletonServices = CoreSingletonServices> =
333
+ SingletonServices
318
334
 
319
- export type SessionServices<
335
+ export type WireServices<
320
336
  SingletonServices extends CoreSingletonServices = CoreSingletonServices,
321
337
  Services = CoreServices<SingletonServices>,
322
- > = Omit<Services, keyof SingletonServices | keyof PikkuInteraction | 'session'>
338
+ > = Omit<Services, keyof SingletonServices | 'session'>
323
339
 
324
340
  /**
325
341
  * Defines a function type for creating singleton services from the given configuration.
@@ -335,16 +351,15 @@ export type CreateSingletonServices<
335
351
  /**
336
352
  * Defines a function type for creating session-specific services.
337
353
  */
338
- export type CreateSessionServices<
354
+ export type CreateWireServices<
339
355
  SingletonServices extends CoreSingletonServices = CoreSingletonServices,
340
356
  Services extends
341
357
  CoreServices<SingletonServices> = CoreServices<SingletonServices>,
342
358
  UserSession extends CoreUserSession = CoreUserSession,
343
359
  > = (
344
360
  services: SingletonServices,
345
- interaction: PikkuInteraction,
346
- session: UserSession | undefined
347
- ) => Promise<SessionServices<Services, SingletonServices>>
361
+ wire: PikkuWire<unknown, unknown, false, UserSession>
362
+ ) => Promise<WireServices<Services, SingletonServices>>
348
363
 
349
364
  /**
350
365
  * Defines a function type for creating config.
@@ -357,11 +372,17 @@ export type CreateConfig<
357
372
  /**
358
373
  * Represents the documentation for a route, including summary, description, tags, and errors.
359
374
  */
360
- export type PikkuDocs = {
375
+ export type CommonWireMeta = {
376
+ pikkuFuncName: string
377
+
378
+ title?: string
379
+ tags?: string[]
361
380
  summary?: string
362
381
  description?: string
363
- tags?: string[]
364
382
  errors?: string[]
383
+
384
+ middleware?: MiddlewareMetadata[]
385
+ permissions?: PermissionMetadata[]
365
386
  }
366
387
 
367
388
  /**
@@ -0,0 +1,195 @@
1
+ import { PikkuError, ErrorDetails } from '../errors/error-handler.js'
2
+ import {
3
+ CorePikkuFunctionConfig,
4
+ CorePermissionGroup,
5
+ CorePikkuPermission,
6
+ } from '../function/functions.types.js'
7
+ import { CoreChannel, ChannelsMeta } from '../wirings/channel/channel.types.js'
8
+ import { CLIMeta, CLIProgramState } from '../wirings/cli/cli.types.js'
9
+ import {
10
+ HTTPMethod,
11
+ CoreHTTPFunctionWiring,
12
+ HTTPWiringsMeta,
13
+ } from '../wirings/http/http.types.js'
14
+ import {
15
+ CoreMCPResource,
16
+ MCPResourceMeta,
17
+ CoreMCPTool,
18
+ MCPToolMeta,
19
+ CoreMCPPrompt,
20
+ MCPPromptMeta,
21
+ } from '../wirings/mcp/mcp.types.js'
22
+ import {
23
+ CoreQueueWorker,
24
+ QueueWorkersMeta,
25
+ } from '../wirings/queue/queue.types.js'
26
+ import {
27
+ CoreScheduledTask,
28
+ ScheduledTasksMeta,
29
+ } from '../wirings/scheduler/scheduler.types.js'
30
+ import {
31
+ CoreWorkflow,
32
+ WorkflowsRuntimeMeta,
33
+ WorkflowWires,
34
+ } from '../wirings/workflow/workflow.types.js'
35
+ import type {
36
+ WorkflowGraphDefinition,
37
+ GraphNodeConfig,
38
+ } from '../wirings/workflow/graph/workflow-graph.types.js'
39
+ import { CoreTrigger, TriggerMeta } from '../wirings/trigger/trigger.types.js'
40
+ import {
41
+ FunctionsMeta,
42
+ CorePikkuMiddleware,
43
+ CorePikkuMiddlewareGroup,
44
+ FunctionServicesMeta,
45
+ CreateConfig,
46
+ CreateSingletonServices,
47
+ CreateWireServices,
48
+ CoreConfig,
49
+ CoreSingletonServices,
50
+ CoreServices,
51
+ CoreUserSession,
52
+ } from './core.types.js'
53
+
54
+ /**
55
+ * State structure for an individual package
56
+ */
57
+ export interface PikkuPackageState {
58
+ function: {
59
+ meta: FunctionsMeta
60
+ functions: Map<string, CorePikkuFunctionConfig<any, any>>
61
+ }
62
+ rpc: {
63
+ meta: Record<string, string>
64
+ files: Map<
65
+ string,
66
+ {
67
+ exportedName: string
68
+ path: string
69
+ }
70
+ >
71
+ /** Maps namespace aliases to package names (e.g., 'ext' -> '@pikku/templates-function-external') */
72
+ externalPackages: Map<string, string>
73
+ }
74
+ http: {
75
+ middleware: Map<string, CorePikkuMiddleware<any, any>[]>
76
+ permissions: Map<string, CorePermissionGroup | CorePikkuPermission[]>
77
+ routes: Map<HTTPMethod, Map<string, CoreHTTPFunctionWiring<any, any, any>>>
78
+ meta: HTTPWiringsMeta
79
+ }
80
+ channel: {
81
+ channels: Map<string, CoreChannel<any, any>>
82
+ meta: ChannelsMeta
83
+ }
84
+ scheduler: {
85
+ tasks: Map<string, CoreScheduledTask>
86
+ meta: ScheduledTasksMeta
87
+ }
88
+ queue: {
89
+ registrations: Map<string, CoreQueueWorker>
90
+ meta: QueueWorkersMeta
91
+ }
92
+ workflows: {
93
+ registrations: Map<string, CoreWorkflow>
94
+ graphRegistrations: Map<string, WorkflowGraphDefinition<any>>
95
+ /** DSL workflow wirings (from wireWorkflow({ func: ... })) */
96
+ wirings: Map<any, { wires: WorkflowWires; func: any }>
97
+ /** Graph workflow wirings (from wireWorkflow({ graph: ... })) */
98
+ graphWirings: Map<
99
+ any,
100
+ { wires: WorkflowWires; graph: Record<string, GraphNodeConfig<string>> }
101
+ >
102
+ meta: WorkflowsRuntimeMeta
103
+ }
104
+ trigger: {
105
+ triggers: Map<string, CoreTrigger>
106
+ meta: TriggerMeta
107
+ }
108
+ mcp: {
109
+ resources: Map<string, CoreMCPResource>
110
+ resourcesMeta: MCPResourceMeta
111
+ tools: Map<string, CoreMCPTool>
112
+ toolsMeta: MCPToolMeta
113
+ prompts: Map<string, CoreMCPPrompt>
114
+ promptsMeta: MCPPromptMeta
115
+ }
116
+ cli: {
117
+ meta: CLIMeta | Record<string, any> // Backward compatible with old published CLI format
118
+ programs: Record<string, CLIProgramState>
119
+ }
120
+ middleware: {
121
+ tagGroup: Record<string, CorePikkuMiddlewareGroup>
122
+ httpGroup: Record<string, CorePikkuMiddlewareGroup>
123
+ tagGroupMeta: Record<
124
+ string,
125
+ {
126
+ exportName: string | null
127
+ sourceFile: string
128
+ position: number
129
+ services: FunctionServicesMeta
130
+ middlewareCount: number
131
+ isFactory: boolean
132
+ }
133
+ >
134
+ httpGroupMeta: Record<
135
+ string,
136
+ {
137
+ exportName: string | null
138
+ sourceFile: string
139
+ position: number
140
+ services: FunctionServicesMeta
141
+ middlewareCount: number
142
+ isFactory: boolean
143
+ }
144
+ >
145
+ }
146
+ permissions: {
147
+ tagGroup: Record<string, CorePermissionGroup | CorePikkuPermission[]>
148
+ httpGroup: Record<string, CorePermissionGroup | CorePikkuPermission[]>
149
+ tagGroupMeta: Record<
150
+ string,
151
+ {
152
+ exportName: string | null
153
+ sourceFile: string
154
+ position: number
155
+ services: FunctionServicesMeta
156
+ permissionCount: number
157
+ isFactory: boolean
158
+ }
159
+ >
160
+ httpGroupMeta: Record<
161
+ string,
162
+ {
163
+ exportName: string | null
164
+ sourceFile: string
165
+ position: number
166
+ services: FunctionServicesMeta
167
+ permissionCount: number
168
+ isFactory: boolean
169
+ }
170
+ >
171
+ }
172
+ misc: {
173
+ errors: Map<PikkuError, ErrorDetails>
174
+ schemas: Map<string, any>
175
+ middleware: Record<string, CorePikkuMiddleware[]>
176
+ permissions: Record<string, CorePermissionGroup | CorePikkuPermission[]>
177
+ }
178
+ package: {
179
+ /** Service factory functions for external packages */
180
+ factories: {
181
+ createConfig?: CreateConfig<CoreConfig>
182
+ createSingletonServices?: CreateSingletonServices<
183
+ CoreConfig,
184
+ CoreSingletonServices
185
+ >
186
+ createWireServices?: CreateWireServices<
187
+ CoreSingletonServices,
188
+ CoreServices,
189
+ CoreUserSession
190
+ >
191
+ } | null
192
+ /** Cached singleton services for this package */
193
+ singletonServices: CoreSingletonServices | null
194
+ }
195
+ }
package/src/utils.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import { Logger } from './services/logger.js'
2
+ import { CoreSingletonServices } from './types/core.types.js'
2
3
 
3
- // TODO: SessionServices probably needs it's own type
4
+ // TODO: WireServices probably needs it's own type
4
5
  // but is an issue for the future and will be tackled
5
6
  // with dependency injection
6
- export const closeSessionServices = async (
7
+ export const closeWireServices = async (
7
8
  logger: Logger,
8
- sessionServices: Record<string, any>
9
+ wireServices: Record<string, any>
9
10
  ) => {
10
11
  await Promise.all(
11
- Object.values(sessionServices).map(async (service) => {
12
+ Object.values(wireServices).map(async (service) => {
12
13
  if (service?.close) {
13
14
  try {
14
15
  await service.close()
@@ -57,3 +58,57 @@ export const freezeDedupe = <T>(
57
58
  }
58
59
  return Object.freeze(out)
59
60
  }
61
+
62
+ /**
63
+ * Stop a single service by calling its stop method if it exists
64
+ */
65
+ const stopService = async (
66
+ logger: Logger,
67
+ name: string,
68
+ service: any
69
+ ): Promise<void> => {
70
+ const stop = service?.stop
71
+ if (stop) {
72
+ logger.info(`Stopping singleton service: ${name}`)
73
+ try {
74
+ await stop.call(service)
75
+ } catch (e: any) {
76
+ logger.error(`Error stopping service ${name}:`, e)
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Stop all singleton services, including external package services.
83
+ * External package services are stopped first, then the parent services.
84
+ *
85
+ * @param singletonServices - The parent singleton services to stop
86
+ */
87
+ export const stopSingletonServices = async (
88
+ singletonServices: CoreSingletonServices
89
+ ): Promise<void> => {
90
+ const logger = singletonServices.logger
91
+
92
+ // First, stop all external package singleton services
93
+ if (globalThis.pikkuState) {
94
+ for (const [packageName, packageState] of globalThis.pikkuState) {
95
+ // Skip main package - we handle it separately
96
+ if (packageName === '__main__') continue
97
+
98
+ const packageServices = packageState.package?.singletonServices
99
+ if (packageServices) {
100
+ logger.info(`Stopping singleton services for package: ${packageName}`)
101
+ for (const [name, service] of Object.entries(packageServices)) {
102
+ await stopService(logger, `${packageName}/${name}`, service)
103
+ }
104
+ // Clear the cached services
105
+ packageState.package.singletonServices = null
106
+ }
107
+ }
108
+ }
109
+
110
+ // Then stop the parent singleton services
111
+ for (const [name, service] of Object.entries(singletonServices)) {
112
+ await stopService(logger, name, service)
113
+ }
114
+ }
@@ -1,8 +1,4 @@
1
- import {
2
- CoreServices,
3
- PikkuWiringTypes,
4
- CorePikkuMiddleware,
5
- } from '../../types/core.types.js'
1
+ import { CoreServices, CorePikkuMiddleware } from '../../types/core.types.js'
6
2
  import { CoreChannel, ChannelMessageMeta } from './channel.types.js'
7
3
  import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
8
4
  import { runPikkuFuncDirectly } from '../../function/function-runner.js'
@@ -49,7 +45,7 @@ export const runChannelLifecycleWithMiddleware = async ({
49
45
 
50
46
  // Use combineMiddleware to properly resolve metadata + inline middleware
51
47
  const allMiddleware = combineMiddleware(
52
- PikkuWiringTypes.channel,
48
+ 'channel',
53
49
  `${channelConfig.name}:${lifecycleType}`,
54
50
  {
55
51
  wireInheritedMiddleware: meta.middleware,
@@ -61,7 +57,8 @@ export const runChannelLifecycleWithMiddleware = async ({
61
57
  const runLifecycle = async () => {
62
58
  return await runPikkuFuncDirectly(
63
59
  meta.pikkuFuncName,
64
- { ...services, channel },
60
+ services,
61
+ { channel },
65
62
  data
66
63
  )
67
64
  }
@@ -2,7 +2,6 @@ import {
2
2
  CoreServices,
3
3
  JSONValue,
4
4
  CoreUserSession,
5
- PikkuWiringTypes,
6
5
  } from '../../types/core.types.js'
7
6
  import {
8
7
  ChannelMessageMeta,
@@ -11,13 +10,14 @@ import {
11
10
  } from './channel.types.js'
12
11
  import { pikkuState } from '../../pikku-state.js'
13
12
  import { runPikkuFunc } from '../../function/function-runner.js'
13
+ import { SessionService } from '../../services/user-session-service.js'
14
14
 
15
15
  const getRouteMeta = (
16
16
  channelName: string,
17
17
  routingProperty?: string,
18
18
  routerValue?: string
19
19
  ): ChannelMessageMeta => {
20
- const channelMeta = pikkuState('channel', 'meta')[channelName]
20
+ const channelMeta = pikkuState(null, 'channel', 'meta')[channelName]
21
21
  if (!channelMeta) {
22
22
  throw new Error(`Channel ${channelName} not found`)
23
23
  }
@@ -62,7 +62,8 @@ const validateAuth = (
62
62
  export const processMessageHandlers = (
63
63
  services: CoreServices,
64
64
  channelConfig: CoreChannel<any, any>,
65
- channelHandler: PikkuChannelHandler
65
+ channelHandler: PikkuChannelHandler,
66
+ userSession?: SessionService<CoreUserSession>
66
67
  ) => {
67
68
  const logger = services.logger
68
69
  const requiresSession = channelConfig.auth !== false
@@ -121,26 +122,19 @@ export const processMessageHandlers = (
121
122
  ? `${channelConfig.name}:${routingProperty}:${routerValue}`
122
123
  : `${channelConfig.name}:default`
123
124
 
124
- return await runPikkuFunc(
125
- PikkuWiringTypes.channel,
126
- cacheKey,
127
- pikkuFuncName,
128
- {
129
- singletonServices: services,
130
- getAllServices: () => ({
131
- ...services,
132
- channel: channelHandler.getChannel(),
133
- }),
134
- data: () => data,
135
- userSession: services.userSession,
136
- inheritedMiddleware,
137
- wireMiddleware,
138
- inheritedPermissions,
139
- wirePermissions,
140
- tags: channelConfig.tags,
141
- interaction: { channel: channelHandler.getChannel() },
142
- }
143
- )
125
+ return await runPikkuFunc('channel', cacheKey, pikkuFuncName, {
126
+ singletonServices: services,
127
+ data: () => data,
128
+ inheritedMiddleware,
129
+ wireMiddleware,
130
+ inheritedPermissions,
131
+ wirePermissions,
132
+ tags: channelConfig.tags,
133
+ wire: {
134
+ channel: channelHandler.getChannel(),
135
+ session: userSession,
136
+ },
137
+ })
144
138
  }
145
139
 
146
140
  return async (rawData): Promise<unknown> => {
@@ -3,7 +3,7 @@ import { addFunction } from '../../function/function-runner.js'
3
3
  import { CorePikkuPermission } from '../../function/functions.types.js'
4
4
  import { pikkuState } from '../../pikku-state.js'
5
5
  import { coerceTopLevelDataFromSchema, validateSchema } from '../../schema.js'
6
- import { UserSessionService } from '../../services/user-session-service.js'
6
+ import { SessionService } from '../../services/user-session-service.js'
7
7
  import { CorePikkuMiddleware } from '../../types/core.types.js'
8
8
  import { httpRouter } from '../http/routers/http-router.js'
9
9
  import {
@@ -33,13 +33,13 @@ export const wireChannel = <
33
33
  >
34
34
  ) => {
35
35
  // Get the channel metadata
36
- const channelsMeta = pikkuState('channel', 'meta')
36
+ const channelsMeta = pikkuState(null, 'channel', 'meta')
37
37
  const channelMeta = channelsMeta[channel.name]
38
38
  if (!channelMeta) {
39
39
  throw new Error(`Channel metadata not found for channel: ${channel.name}`)
40
40
  }
41
41
 
42
- pikkuState('channel', 'channels').set(channel.name, channel as any)
42
+ pikkuState(null, 'channel', 'channels').set(channel.name, channel as any)
43
43
 
44
44
  // Register onConnect function if provided
45
45
  if (channel.onConnect && channelMeta.connect) {
@@ -89,7 +89,7 @@ export const wireChannel = <
89
89
  }
90
90
 
91
91
  // Store the channel configuration
92
- pikkuState('channel', 'channels').set(channel.name, channel as any)
92
+ pikkuState(null, 'channel', 'channels').set(channel.name, channel as any)
93
93
  }
94
94
 
95
95
  const getMatchingChannelConfig = (path: string) => {
@@ -98,7 +98,7 @@ const getMatchingChannelConfig = (path: string) => {
98
98
  return null
99
99
  }
100
100
 
101
- const meta = pikkuState('channel', 'meta')
101
+ const meta = pikkuState(null, 'channel', 'meta')
102
102
  const channelMeta = Object.values(meta).find(
103
103
  (channelConfig) => channelConfig.route === matchedPath.route
104
104
  )
@@ -106,7 +106,7 @@ const getMatchingChannelConfig = (path: string) => {
106
106
  return null
107
107
  }
108
108
 
109
- const channels = pikkuState('channel', 'channels')
109
+ const channels = pikkuState(null, 'channel', 'channels')
110
110
  const channelConfig = channels.get(channelMeta.name)
111
111
  if (!channelConfig) {
112
112
  return null
@@ -128,7 +128,7 @@ export const openChannel = async ({
128
128
  request,
129
129
  }: Pick<CoreChannel<unknown, string>, 'route'> &
130
130
  RunChannelParams<unknown> & {
131
- userSession: UserSessionService<any>
131
+ userSession: SessionService<any>
132
132
  } & RunChannelOptions): Promise<{
133
133
  openingData: unknown
134
134
  channelConfig: CoreChannel<unknown, any>