@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
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Forge node types for workflow builder visualization.
3
+ * wireForgeNode is metadata-only - no runtime behavior.
4
+ * The CLI extracts this via AST and generates JSON metadata.
5
+ */
6
+
7
+ /**
8
+ * The type of forge node.
9
+ * - trigger: Starts workflows (webhooks, schedules, events)
10
+ * - action: Operations that do something (API calls, send email, database ops)
11
+ * - end: Terminal nodes with no outputs (logging, notifications)
12
+ */
13
+ export type ForgeNodeType = 'trigger' | 'action' | 'end'
14
+
15
+ /**
16
+ * Configuration for wireForgeNode.
17
+ * This is the input type that developers use when defining nodes.
18
+ */
19
+ export type CoreForgeNode = {
20
+ /** Unique identifier for this node */
21
+ name: string
22
+ /** Human-readable name for UI display */
23
+ displayName: string
24
+ /** Grouping category (validated against forge.node.categories in config) */
25
+ category: string
26
+ /** Node type determining behavior and outputs */
27
+ type: ForgeNodeType
28
+ /** RPC name to call when node executes (local name, Forge handles package aliasing) */
29
+ rpc: string
30
+ /** Optional description for UI */
31
+ description?: string
32
+ /** Whether to add an error output port alongside the default output */
33
+ errorOutput?: boolean
34
+ /** Optional tags for filtering/categorization */
35
+ tags?: string[]
36
+ }
37
+
38
+ /**
39
+ * Metadata generated for each forge node.
40
+ * This is the output type that the CLI generates.
41
+ */
42
+ export type ForgeNodeMeta = {
43
+ name: string
44
+ displayName: string
45
+ category: string
46
+ type: ForgeNodeType
47
+ /** RPC name (local, remapped by Forge for external packages) */
48
+ rpc: string
49
+ description?: string
50
+ /** Whether node has error output port */
51
+ errorOutput: boolean
52
+ /** Input schema name extracted from RPC */
53
+ inputSchemaName: string | null
54
+ /** Output schema name extracted from RPC */
55
+ outputSchemaName: string | null
56
+ tags?: string[]
57
+ }
58
+
59
+ /**
60
+ * Record of all forge node metadata, keyed by node name.
61
+ */
62
+ export type ForgeNodesMeta = Record<string, ForgeNodeMeta>
63
+
64
+ /**
65
+ * No-op function for wireForgeNode.
66
+ * This exists purely for TypeScript type checking and will be tree-shaken.
67
+ * The CLI extracts metadata via AST parsing.
68
+ */
69
+ export const wireForgeNode = (_config: CoreForgeNode): void => {
70
+ // No-op - metadata only, extracted by CLI via AST
71
+ }
72
+
73
+ /**
74
+ * Configuration for wireForgeCredential.
75
+ * Declares credentials/secrets required by a Forge package.
76
+ * Uses Zod for schema definition - converted to JSON Schema at build time.
77
+ */
78
+ export type CoreForgeCredential<T = unknown> = {
79
+ /** Unique identifier for this credential */
80
+ name: string
81
+ /** Human-readable name for UI display */
82
+ displayName: string
83
+ /** Optional description for UI */
84
+ description?: string
85
+ /** Key used with SecretService.getSecret() to retrieve the credential */
86
+ secretId: string
87
+ /** Zod schema defining the structure of the credential */
88
+ schema: T
89
+ }
90
+
91
+ /**
92
+ * Metadata generated for each forge credential.
93
+ * Schema is converted from Zod to JSON Schema at build time.
94
+ */
95
+ export type ForgeCredentialMeta = {
96
+ name: string
97
+ displayName: string
98
+ description?: string
99
+ secretId: string
100
+ /** JSON Schema (converted from Zod at build time) or zodLookup reference name */
101
+ schema: Record<string, unknown> | string
102
+ }
103
+
104
+ /**
105
+ * Record of all forge credential metadata, keyed by credential name.
106
+ */
107
+ export type ForgeCredentialsMeta = Record<string, ForgeCredentialMeta>
108
+
109
+ /**
110
+ * No-op function for wireForgeCredential.
111
+ * This exists purely for TypeScript type checking and will be tree-shaken.
112
+ * The CLI extracts metadata via AST parsing.
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * import { z } from 'zod'
117
+ *
118
+ * const slackCredentials = z.object({
119
+ * botToken: z.string().describe('Bot OAuth token'),
120
+ * signingSecret: z.string().describe('Request signing secret')
121
+ * })
122
+ *
123
+ * wireForgeCredential({
124
+ * name: 'slack',
125
+ * displayName: 'Slack Credentials',
126
+ * secretId: 'SLACK_CREDENTIALS',
127
+ * schema: slackCredentials
128
+ * })
129
+ * ```
130
+ */
131
+ export const wireForgeCredential = <T>(
132
+ _config: CoreForgeCredential<T>
133
+ ): void => {
134
+ // No-op - metadata only, extracted by CLI via AST
135
+ }
@@ -0,0 +1 @@
1
+ export * from './forge-node.types.js'
@@ -11,19 +11,19 @@ import {
11
11
  import { addFunction } from '../../function/function-runner.js'
12
12
  import { httpRouter } from './routers/http-router.js'
13
13
 
14
- const sessionMiddleware: CorePikkuMiddleware = async (services, _, next) => {
15
- services.userSession.set({ userId: 'test' } as any)
14
+ const sessionMiddleware: CorePikkuMiddleware = async (services, wire, next) => {
15
+ wire.session?.set({ userId: 'test' } as any)
16
16
  await next()
17
17
  }
18
18
 
19
19
  const setHTTPFunctionMap = (func: any) => {
20
- pikkuState('function', 'meta', {
20
+ pikkuState(null, 'function', 'meta', {
21
21
  pikku_func_name: {
22
22
  pikkuFuncName: 'pikku_func_name',
23
23
  services: ['userSession'],
24
24
  },
25
25
  } as any)
26
- pikkuState('http', 'meta', {
26
+ pikkuState(null, 'http', 'meta', {
27
27
  get: {
28
28
  test: {
29
29
  pikkuFuncName: 'pikku_func_name',
@@ -43,7 +43,7 @@ const setHTTPFunctionMap = (func: any) => {
43
43
 
44
44
  describe('fetch', () => {
45
45
  let singletonServices: any
46
- let createSessionServices: any
46
+ let createWireServices: any
47
47
  let request: any
48
48
  let response: any
49
49
 
@@ -59,7 +59,7 @@ describe('fetch', () => {
59
59
  },
60
60
  }
61
61
 
62
- createSessionServices = async () => ({})
62
+ createWireServices = async () => ({})
63
63
  request = new PikkuMockRequest('/test', 'get')
64
64
  response = new PikkuMockResponse()
65
65
 
@@ -77,7 +77,7 @@ describe('fetch', () => {
77
77
  async () =>
78
78
  fetch(request, {
79
79
  singletonServices,
80
- createSessionServices,
80
+ createWireServices,
81
81
  bubbleErrors: true,
82
82
  }),
83
83
  NotFoundError
@@ -99,7 +99,7 @@ describe('fetch', () => {
99
99
 
100
100
  const result = await fetch(request, {
101
101
  singletonServices,
102
- createSessionServices,
102
+ createWireServices,
103
103
  })
104
104
 
105
105
  assert.deepStrictEqual(await result.json(), { success: true })
@@ -122,7 +122,7 @@ describe('fetch', () => {
122
122
 
123
123
  await fetch(request, {
124
124
  singletonServices,
125
- createSessionServices,
125
+ createWireServices,
126
126
  })
127
127
 
128
128
  assert.strictEqual(await permissions.test(), true)
@@ -143,7 +143,7 @@ describe('fetch', () => {
143
143
  async () =>
144
144
  fetch(request, {
145
145
  singletonServices,
146
- createSessionServices,
146
+ createWireServices,
147
147
  bubbleErrors: true,
148
148
  }),
149
149
  error
@@ -18,25 +18,25 @@ import {
18
18
  CoreUserSession,
19
19
  CorePikkuMiddleware,
20
20
  CorePikkuMiddlewareGroup,
21
- SessionServices,
21
+ WireServices,
22
+ PikkuWire,
22
23
  PikkuWiringTypes,
23
- PikkuInteraction,
24
24
  } from '../../types/core.types.js'
25
25
  import { NotFoundError } from '../../errors/errors.js'
26
26
  import {
27
- closeSessionServices,
27
+ closeWireServices,
28
28
  createWeakUID,
29
29
  isSerializable,
30
30
  } from '../../utils.js'
31
- import { PikkuUserSessionService } from '../../services/user-session-service.js'
31
+ import { PikkuSessionService } from '../../services/user-session-service.js'
32
32
  import { handleHTTPError } from '../../handle-error.js'
33
33
  import { pikkuState } from '../../pikku-state.js'
34
34
  import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js'
35
35
  import { PikkuFetchHTTPRequest } from './pikku-fetch-http-request.js'
36
36
  import { PikkuChannel } from '../channel/channel.types.js'
37
37
  import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
38
- import { rpcService } from '../rpc/rpc-runner.js'
39
38
  import { httpRouter } from './routers/http-router.js'
39
+ import { startWorkflowByHttpWire } from '../workflow/workflow-utils.js'
40
40
 
41
41
  /**
42
42
  * Registers HTTP middleware for a specific route pattern.
@@ -69,9 +69,10 @@ import { httpRouter } from './routers/http-router.js'
69
69
  */
70
70
  export const addHTTPMiddleware = <PikkuMiddleware extends CorePikkuMiddleware>(
71
71
  pattern: string,
72
- middleware: CorePikkuMiddlewareGroup
72
+ middleware: CorePikkuMiddlewareGroup,
73
+ packageName: string | null = null
73
74
  ): CorePikkuMiddlewareGroup => {
74
- const httpGroups = pikkuState('middleware', 'httpGroup')
75
+ const httpGroups = pikkuState(packageName, 'middleware', 'httpGroup')
75
76
  httpGroups[pattern] = middleware
76
77
  return middleware
77
78
  }
@@ -107,9 +108,10 @@ export const addHTTPMiddleware = <PikkuMiddleware extends CorePikkuMiddleware>(
107
108
  */
108
109
  export const addHTTPPermission = <PikkuPermission extends CorePikkuPermission>(
109
110
  pattern: string,
110
- permissions: CorePermissionGroup | CorePikkuPermission[]
111
+ permissions: CorePermissionGroup | CorePikkuPermission[],
112
+ packageName: string | null = null
111
113
  ): CorePermissionGroup | CorePikkuPermission[] => {
112
- const httpGroups = pikkuState('permissions', 'httpGroup')
114
+ const httpGroups = pikkuState(packageName, 'permissions', 'httpGroup')
113
115
  httpGroups[pattern] = permissions
114
116
  return permissions
115
117
  }
@@ -152,17 +154,19 @@ export const wireHTTP = <
152
154
  PikkuMiddleware
153
155
  >
154
156
  ) => {
155
- const httpMeta = pikkuState('http', 'meta')
157
+ const httpMeta = pikkuState(null, 'http', 'meta')
156
158
  const routeMeta = httpMeta[httpWiring.method][httpWiring.route]
157
159
  if (!routeMeta) {
158
160
  throw new Error('Route metadata not found')
159
161
  }
160
- addFunction(routeMeta.pikkuFuncName, httpWiring.func)
161
- const routes = pikkuState('http', 'routes')
162
+ if (httpWiring.func) {
163
+ addFunction(routeMeta.pikkuFuncName, httpWiring.func)
164
+ }
165
+ const routes = pikkuState(null, 'http', 'routes')
162
166
  if (!routes.has(httpWiring.method)) {
163
167
  routes.set(httpWiring.method, new Map())
164
168
  }
165
- pikkuState('http', 'routes')
169
+ pikkuState(null, 'http', 'routes')
166
170
  .get(httpWiring.method)
167
171
  ?.set(httpWiring.route, httpWiring as any)
168
172
  }
@@ -185,10 +189,10 @@ const getMatchingRoute = (requestType: string, requestPath: string) => {
185
189
  )
186
190
 
187
191
  if (matchedPath) {
188
- const route = pikkuState('http', 'routes')
192
+ const route = pikkuState(null, 'http', 'routes')
189
193
  .get(requestType.toLowerCase() as HTTPMethod)!
190
194
  .get(matchedPath.route)!
191
- const meta = pikkuState('http', 'meta')[
195
+ const meta = pikkuState(null, 'http', 'meta')[
192
196
  requestType.toLowerCase() as PikkuWiringTypes
193
197
  ][route.route]
194
198
 
@@ -203,16 +207,16 @@ const getMatchingRoute = (requestType: string, requestPath: string) => {
203
207
  }
204
208
 
205
209
  /**
206
- * Combines the request and response objects into a single HTTP interaction object.
210
+ * Combines the request and response objects into a single HTTP wire object.
207
211
  *
208
212
  * This utility function creates an object that holds both the HTTP request and response,
209
213
  * which simplifies passing these around through middleware and route execution.
210
214
  *
211
215
  * @param {PikkuHTTPRequest | undefined} request - The HTTP request object.
212
216
  * @param {PikkuHTTPResponse | undefined} response - The HTTP response object.
213
- * @returns {PikkuHTTP | undefined} The combined HTTP interaction object or undefined if none provided.
217
+ * @returns {PikkuHTTP | undefined} The combined HTTP wire object or undefined if none provided.
214
218
  */
215
- export const createHTTPInteraction = (
219
+ export const createHTTPWire = (
216
220
  request: PikkuHTTPRequest | undefined,
217
221
  response: PikkuHTTPResponse | undefined
218
222
  ): PikkuHTTP | undefined => {
@@ -246,15 +250,15 @@ export const createHTTPInteraction = (
246
250
  *
247
251
  * @param {Object} services - A collection of shared services and utilities.
248
252
  * @param {Object} matchedRoute - Contains route details, URL parameters, and optional schema.
249
- * @param {PikkuHTTP | undefined} http - The HTTP interaction object.
253
+ * @param {PikkuHTTP | undefined} http - The HTTP wire object.
250
254
  * @param {Object} options - Options for route execution (e.g., whether to coerce query strings to arrays).
251
- * @returns {Promise<any>} An object containing the route handler result and session services (if any).
255
+ * @returns {Promise<any>} An object containing the route handler result and wire services (if any).
252
256
  * @throws Throws errors like MissingSessionError or ForbiddenError on validation failures.
253
257
  */
254
258
  const executeRoute = async (
255
259
  services: {
256
260
  singletonServices: any
257
- createSessionServices: Function
261
+ createWireServices?: any
258
262
  skipUserSession: boolean
259
263
  requestId: string
260
264
  },
@@ -269,22 +273,18 @@ const executeRoute = async (
269
273
  coerceDataFromSchema: boolean
270
274
  }
271
275
  ) => {
272
- const userSession = new PikkuUserSessionService<CoreUserSession>()
276
+ const userSession = new PikkuSessionService<CoreUserSession>()
273
277
  const { params, route, meta } = matchedRoute
274
- const {
275
- singletonServices,
276
- createSessionServices,
277
- skipUserSession,
278
- requestId,
279
- } = services
280
-
281
- const requiresSession = route.auth !== false
282
- let sessionServices: any
283
- let result: any
278
+ const { singletonServices, createWireServices, skipUserSession, requestId } =
279
+ services
284
280
 
285
281
  // Attach URL parameters to the request object
286
282
  http?.request?.setParams(params)
287
283
 
284
+ const requiresSession = route.auth !== false
285
+ let wireServices: any
286
+ let result: any
287
+
288
288
  singletonServices.logger.info(
289
289
  `Matched route: ${route.route} | method: ${route.method.toUpperCase()} | auth: ${requiresSession.toString()}`
290
290
  )
@@ -324,38 +324,28 @@ const executeRoute = async (
324
324
  }
325
325
  }
326
326
 
327
- const interaction: PikkuInteraction = { http, channel }
328
-
329
- const getAllServices = async (session?: CoreUserSession) => {
330
- // Create session-specific services for handling the request
331
- sessionServices = await createSessionServices(
332
- { ...singletonServices, userSession, channel },
333
- { http },
334
- session
335
- )
327
+ const wire: PikkuWire = { http, channel, session: userSession }
336
328
 
337
- return rpcService.injectRPCService(
338
- {
339
- ...singletonServices,
340
- ...sessionServices,
341
- http,
342
- userSession,
343
- channel,
344
- },
345
- interaction,
346
- route.auth
329
+ if (matchedRoute.meta.workflow === true) {
330
+ await startWorkflowByHttpWire(
331
+ singletonServices,
332
+ createWireServices,
333
+ matchedRoute,
334
+ wire
347
335
  )
336
+ return wireServices
337
+ ? { wireServices, result: http.response }
338
+ : { result: http.response }
348
339
  }
349
340
 
350
341
  result = await runPikkuFunc(
351
- PikkuWiringTypes.http,
342
+ 'http',
352
343
  `${meta.method}:${meta.route}`,
353
344
  meta.pikkuFuncName,
354
345
  {
355
346
  singletonServices,
356
- getAllServices,
347
+ createWireServices,
357
348
  auth: route.auth !== false,
358
- userSession,
359
349
  data,
360
350
  inheritedMiddleware: meta.middleware,
361
351
  wireMiddleware: route.middleware,
@@ -363,7 +353,7 @@ const executeRoute = async (
363
353
  wirePermissions: route.permissions,
364
354
  coerceDataFromSchema: options.coerceDataFromSchema,
365
355
  tags: route.tags,
366
- interaction,
356
+ wire,
367
357
  }
368
358
  )
369
359
 
@@ -378,7 +368,7 @@ const executeRoute = async (
378
368
  // TODO: Evaluate if the response stream should be explicitly ended.
379
369
  // http?.response?.end()
380
370
 
381
- return sessionServices ? { result, sessionServices } : { result }
371
+ return wireServices ? { result, wireServices } : { result }
382
372
  }
383
373
 
384
374
  /**
@@ -431,11 +421,11 @@ export const pikkuFetch = async <In, Out>(
431
421
  * middleware execution, error handling, and session service cleanup.
432
422
  *
433
423
  * This function does the following:
434
- * - Wraps the incoming request and response into an HTTP interaction object.
424
+ * - Wraps the incoming request and response into an HTTP wire object.
435
425
  * - Determines the correct route based on HTTP method and path.
436
426
  * - Executes middleware and the route handler.
437
427
  * - Catches and handles errors, optionally bubbling them if configured.
438
- * - Cleans up any session services created during processing.
428
+ * - Cleans up any wire services created during processing.
439
429
  *
440
430
  * @template In Expected input data type.
441
431
  * @template Out Expected output data type.
@@ -449,7 +439,7 @@ export const fetchData = async <In, Out>(
449
439
  response: PikkuHTTPResponse,
450
440
  {
451
441
  singletonServices,
452
- createSessionServices,
442
+ createWireServices,
453
443
  skipUserSession = false,
454
444
  respondWith404 = true,
455
445
  logWarningsForStatusCodes = [],
@@ -462,11 +452,11 @@ export const fetchData = async <In, Out>(
462
452
  (request as any).getHeader?.('x-request-id') ||
463
453
  generateRequestId?.() ||
464
454
  createWeakUID()
465
- let sessionServices: SessionServices<typeof singletonServices> | undefined
455
+ let wireServices: WireServices<typeof singletonServices> | undefined
466
456
  let result: Out
467
457
 
468
- // Combine the request and response into one interaction object
469
- const http = createHTTPInteraction(
458
+ // Combine the request and response into one wire object
459
+ const http = createHTTPWire(
470
460
  request instanceof Request ? new PikkuFetchHTTPRequest(request) : request,
471
461
  response
472
462
  )
@@ -487,10 +477,10 @@ export const fetchData = async <In, Out>(
487
477
  }
488
478
 
489
479
  // Execute the matched route along with its middleware and session management
490
- ;({ result, sessionServices } = await executeRoute(
480
+ ;({ result, wireServices } = await executeRoute(
491
481
  {
492
482
  singletonServices,
493
- createSessionServices,
483
+ createWireServices,
494
484
  skipUserSession,
495
485
  requestId,
496
486
  },
@@ -513,8 +503,8 @@ export const fetchData = async <In, Out>(
513
503
  )
514
504
  } finally {
515
505
  // Clean up any session-specific services created during processing
516
- if (sessionServices) {
517
- await closeSessionServices(singletonServices.logger, sessionServices)
506
+ if (wireServices) {
507
+ await closeWireServices(singletonServices.logger, wireServices)
518
508
  }
519
509
  }
520
510
  }
@@ -1,14 +1,12 @@
1
1
  import type { SerializeOptions } from 'cookie'
2
2
  import type { PikkuError } from '../../errors/error-handler.js'
3
3
  import type {
4
- PikkuDocs,
5
4
  CoreServices,
6
5
  CoreSingletonServices,
7
6
  CoreUserSession,
8
- CreateSessionServices,
7
+ CreateWireServices,
9
8
  CorePikkuMiddleware,
10
- MiddlewareMetadata,
11
- PermissionMetadata,
9
+ CommonWireMeta,
12
10
  } from '../../types/core.types.js'
13
11
  import type {
14
12
  CorePikkuFunction,
@@ -46,7 +44,7 @@ export type RunHTTPWiringOptions = Partial<{
46
44
 
47
45
  export type RunHTTPWiringParams = {
48
46
  singletonServices: CoreSingletonServices
49
- createSessionServices: CreateSessionServices<
47
+ createWireServices: CreateWireServices<
50
48
  CoreSingletonServices,
51
49
  CoreServices<CoreSingletonServices>,
52
50
  CoreUserSession
@@ -83,7 +81,7 @@ export type CoreHTTPFunction = {
83
81
  }>
84
82
  }
85
83
  /**
86
- * Represents a http interaction within Pikku, including a request and response.
84
+ * Represents a http wire within Pikku, including a request and response.
87
85
  */
88
86
  export interface PikkuHTTP<In = unknown> {
89
87
  request?: PikkuHTTPRequest<In>
@@ -123,14 +121,12 @@ export type CoreHTTPFunctionWiring<
123
121
  In,
124
122
  Out,
125
123
  any,
126
- any,
127
124
  any
128
125
  > = CorePikkuFunction<In, Out>,
129
126
  PikkuFunctionSessionless extends CorePikkuFunctionSessionless<
130
127
  In,
131
128
  Out,
132
129
  any,
133
- any,
134
130
  any
135
131
  > = CorePikkuFunctionSessionless<In, Out>,
136
132
  PikkuPermission extends CorePikkuPermission<
@@ -229,6 +225,19 @@ export type CoreHTTPFunctionWiring<
229
225
  middleware?: PikkuMiddleware[]
230
226
  sse?: undefined
231
227
  })
228
+ | {
229
+ /** Route triggers a workflow matched by route/method from workflow wires.http */
230
+ route: R
231
+ method: HTTPMethod
232
+ workflow: true
233
+ func?: undefined
234
+ permissions?: undefined
235
+ auth?: undefined
236
+ tags?: undefined
237
+ middleware?: undefined
238
+ returnsJSON?: undefined
239
+ sse?: boolean
240
+ }
232
241
 
233
242
  /**
234
243
  * Represents the input types for HTTP wiring metadata, including parameters, query, and body types.
@@ -242,18 +251,14 @@ export type HTTPFunctionMetaInputTypes = {
242
251
  /**
243
252
  * Represents metadata for a set of HTTP wirings, including HTTP wiring details, methods, input/output types, and documentation.
244
253
  */
245
- export type HTTPWiringMeta = {
246
- pikkuFuncName: string
254
+ export type HTTPWiringMeta = CommonWireMeta & {
247
255
  route: string
248
256
  method: HTTPMethod
249
257
  params?: string[]
250
258
  query?: string[]
251
259
  inputTypes?: HTTPFunctionMetaInputTypes
252
- docs?: PikkuDocs
253
- tags?: string[]
254
260
  sse?: true
255
- middleware?: MiddlewareMetadata[] // Pre-resolved middleware chain (global + route + tag + explicit)
256
- permissions?: PermissionMetadata[] // Pre-resolved permission chain (global + route + tag + explicit)
261
+ workflow?: true
257
262
  }
258
263
  export type HTTPWiringsMeta = Record<HTTPMethod, Record<string, HTTPWiringMeta>>
259
264
 
@@ -6,7 +6,7 @@ import { Logger } from '../../services/index.js'
6
6
  * @param logger - A logger for logging information.
7
7
  */
8
8
  export const logRoutes = (logger: Logger) => {
9
- const routesByType = pikkuState('http', 'routes')
9
+ const routesByType = pikkuState(null, 'http', 'routes')
10
10
  if (routesByType.size === 0) {
11
11
  logger.info('No routes added')
12
12
  return