@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,120 @@
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
+ * The type of forge node.
8
+ * - trigger: Starts workflows (webhooks, schedules, events)
9
+ * - action: Operations that do something (API calls, send email, database ops)
10
+ * - end: Terminal nodes with no outputs (logging, notifications)
11
+ */
12
+ export type ForgeNodeType = 'trigger' | 'action' | 'end';
13
+ /**
14
+ * Configuration for wireForgeNode.
15
+ * This is the input type that developers use when defining nodes.
16
+ */
17
+ export type CoreForgeNode = {
18
+ /** Unique identifier for this node */
19
+ name: string;
20
+ /** Human-readable name for UI display */
21
+ displayName: string;
22
+ /** Grouping category (validated against forge.node.categories in config) */
23
+ category: string;
24
+ /** Node type determining behavior and outputs */
25
+ type: ForgeNodeType;
26
+ /** RPC name to call when node executes (local name, Forge handles package aliasing) */
27
+ rpc: string;
28
+ /** Optional description for UI */
29
+ description?: string;
30
+ /** Whether to add an error output port alongside the default output */
31
+ errorOutput?: boolean;
32
+ /** Optional tags for filtering/categorization */
33
+ tags?: string[];
34
+ };
35
+ /**
36
+ * Metadata generated for each forge node.
37
+ * This is the output type that the CLI generates.
38
+ */
39
+ export type ForgeNodeMeta = {
40
+ name: string;
41
+ displayName: string;
42
+ category: string;
43
+ type: ForgeNodeType;
44
+ /** RPC name (local, remapped by Forge for external packages) */
45
+ rpc: string;
46
+ description?: string;
47
+ /** Whether node has error output port */
48
+ errorOutput: boolean;
49
+ /** Input schema name extracted from RPC */
50
+ inputSchemaName: string | null;
51
+ /** Output schema name extracted from RPC */
52
+ outputSchemaName: string | null;
53
+ tags?: string[];
54
+ };
55
+ /**
56
+ * Record of all forge node metadata, keyed by node name.
57
+ */
58
+ export type ForgeNodesMeta = Record<string, ForgeNodeMeta>;
59
+ /**
60
+ * No-op function for wireForgeNode.
61
+ * This exists purely for TypeScript type checking and will be tree-shaken.
62
+ * The CLI extracts metadata via AST parsing.
63
+ */
64
+ export declare const wireForgeNode: (_config: CoreForgeNode) => void;
65
+ /**
66
+ * Configuration for wireForgeCredential.
67
+ * Declares credentials/secrets required by a Forge package.
68
+ * Uses Zod for schema definition - converted to JSON Schema at build time.
69
+ */
70
+ export type CoreForgeCredential<T = unknown> = {
71
+ /** Unique identifier for this credential */
72
+ name: string;
73
+ /** Human-readable name for UI display */
74
+ displayName: string;
75
+ /** Optional description for UI */
76
+ description?: string;
77
+ /** Key used with SecretService.getSecret() to retrieve the credential */
78
+ secretId: string;
79
+ /** Zod schema defining the structure of the credential */
80
+ schema: T;
81
+ };
82
+ /**
83
+ * Metadata generated for each forge credential.
84
+ * Schema is converted from Zod to JSON Schema at build time.
85
+ */
86
+ export type ForgeCredentialMeta = {
87
+ name: string;
88
+ displayName: string;
89
+ description?: string;
90
+ secretId: string;
91
+ /** JSON Schema (converted from Zod at build time) or zodLookup reference name */
92
+ schema: Record<string, unknown> | string;
93
+ };
94
+ /**
95
+ * Record of all forge credential metadata, keyed by credential name.
96
+ */
97
+ export type ForgeCredentialsMeta = Record<string, ForgeCredentialMeta>;
98
+ /**
99
+ * No-op function for wireForgeCredential.
100
+ * This exists purely for TypeScript type checking and will be tree-shaken.
101
+ * The CLI extracts metadata via AST parsing.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * import { z } from 'zod'
106
+ *
107
+ * const slackCredentials = z.object({
108
+ * botToken: z.string().describe('Bot OAuth token'),
109
+ * signingSecret: z.string().describe('Request signing secret')
110
+ * })
111
+ *
112
+ * wireForgeCredential({
113
+ * name: 'slack',
114
+ * displayName: 'Slack Credentials',
115
+ * secretId: 'SLACK_CREDENTIALS',
116
+ * schema: slackCredentials
117
+ * })
118
+ * ```
119
+ */
120
+ export declare const wireForgeCredential: <T>(_config: CoreForgeCredential<T>) => void;
@@ -0,0 +1,38 @@
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
+ * No-op function for wireForgeNode.
8
+ * This exists purely for TypeScript type checking and will be tree-shaken.
9
+ * The CLI extracts metadata via AST parsing.
10
+ */
11
+ export const wireForgeNode = (_config) => {
12
+ // No-op - metadata only, extracted by CLI via AST
13
+ };
14
+ /**
15
+ * No-op function for wireForgeCredential.
16
+ * This exists purely for TypeScript type checking and will be tree-shaken.
17
+ * The CLI extracts metadata via AST parsing.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { z } from 'zod'
22
+ *
23
+ * const slackCredentials = z.object({
24
+ * botToken: z.string().describe('Bot OAuth token'),
25
+ * signingSecret: z.string().describe('Request signing secret')
26
+ * })
27
+ *
28
+ * wireForgeCredential({
29
+ * name: 'slack',
30
+ * displayName: 'Slack Credentials',
31
+ * secretId: 'SLACK_CREDENTIALS',
32
+ * schema: slackCredentials
33
+ * })
34
+ * ```
35
+ */
36
+ export const wireForgeCredential = (_config) => {
37
+ // No-op - metadata only, extracted by CLI via AST
38
+ };
@@ -0,0 +1 @@
1
+ export * from './forge-node.types.js';
@@ -0,0 +1 @@
1
+ export * from './forge-node.types.js';
@@ -31,7 +31,7 @@ import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
31
31
  * ])
32
32
  * ```
33
33
  */
34
- export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(pattern: string, middleware: CorePikkuMiddlewareGroup) => CorePikkuMiddlewareGroup;
34
+ export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(pattern: string, middleware: CorePikkuMiddlewareGroup, packageName?: string | null) => CorePikkuMiddlewareGroup;
35
35
  /**
36
36
  * Registers HTTP permissions for a specific route pattern.
37
37
  *
@@ -61,7 +61,7 @@ export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddle
61
61
  * ])
62
62
  * ```
63
63
  */
64
- export declare const addHTTPPermission: <PikkuPermission extends CorePikkuPermission>(pattern: string, permissions: CorePermissionGroup | CorePikkuPermission[]) => CorePermissionGroup | CorePikkuPermission[];
64
+ export declare const addHTTPPermission: <PikkuPermission extends CorePikkuPermission>(pattern: string, permissions: CorePermissionGroup | CorePikkuPermission[], packageName?: string | null) => CorePermissionGroup | CorePikkuPermission[];
65
65
  /**
66
66
  * Adds a new route to the global HTTP route registry.
67
67
  *
@@ -79,16 +79,16 @@ export declare const addHTTPPermission: <PikkuPermission extends CorePikkuPermis
79
79
  */
80
80
  export declare const wireHTTP: <In, Out, Route extends string, PikkuFunction extends CorePikkuFunction<In, Out> = CorePikkuFunction<In, Out>, PikkuFunctionSessionless extends CorePikkuFunctionSessionless<In, Out> = CorePikkuFunctionSessionless<In, Out>, PikkuPermissionGroup extends CorePikkuPermission<In> = CorePikkuPermission<In>, PikkuMiddleware extends CorePikkuMiddleware = CorePikkuMiddleware>(httpWiring: CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction, PikkuFunctionSessionless, PikkuPermissionGroup, PikkuMiddleware>) => void;
81
81
  /**
82
- * Combines the request and response objects into a single HTTP interaction object.
82
+ * Combines the request and response objects into a single HTTP wire object.
83
83
  *
84
84
  * This utility function creates an object that holds both the HTTP request and response,
85
85
  * which simplifies passing these around through middleware and route execution.
86
86
  *
87
87
  * @param {PikkuHTTPRequest | undefined} request - The HTTP request object.
88
88
  * @param {PikkuHTTPResponse | undefined} response - The HTTP response object.
89
- * @returns {PikkuHTTP | undefined} The combined HTTP interaction object or undefined if none provided.
89
+ * @returns {PikkuHTTP | undefined} The combined HTTP wire object or undefined if none provided.
90
90
  */
91
- export declare const createHTTPInteraction: (request: PikkuHTTPRequest | undefined, response: PikkuHTTPResponse | undefined) => PikkuHTTP | undefined;
91
+ export declare const createHTTPWire: (request: PikkuHTTPRequest | undefined, response: PikkuHTTPResponse | undefined) => PikkuHTTP | undefined;
92
92
  /**
93
93
  * Executes an HTTP route for a given Fetch API request.
94
94
  *
@@ -123,11 +123,11 @@ export declare const pikkuFetch: <In, Out>(request: Request | PikkuHTTPRequest,
123
123
  * middleware execution, error handling, and session service cleanup.
124
124
  *
125
125
  * This function does the following:
126
- * - Wraps the incoming request and response into an HTTP interaction object.
126
+ * - Wraps the incoming request and response into an HTTP wire object.
127
127
  * - Determines the correct route based on HTTP method and path.
128
128
  * - Executes middleware and the route handler.
129
129
  * - Catches and handles errors, optionally bubbling them if configured.
130
- * - Cleans up any session services created during processing.
130
+ * - Cleans up any wire services created during processing.
131
131
  *
132
132
  * @template In Expected input data type.
133
133
  * @template Out Expected output data type.
@@ -136,4 +136,4 @@ export declare const pikkuFetch: <In, Out>(request: Request | PikkuHTTPRequest,
136
136
  * @param {RunHTTPWiringOptions & RunHTTPWiringParams} options - Options such as singleton services, session handling, and error configuration.
137
137
  * @returns {Promise<Out | void>} The output from the route handler or void if an error occurred.
138
138
  */
139
- export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { singletonServices, createSessionServices, skipUserSession, respondWith404, logWarningsForStatusCodes, coerceDataFromSchema, bubbleErrors, generateRequestId, }: RunHTTPWiringOptions & RunHTTPWiringParams) => Promise<Out | void>;
139
+ export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { singletonServices, createWireServices, skipUserSession, respondWith404, logWarningsForStatusCodes, coerceDataFromSchema, bubbleErrors, generateRequestId, }: RunHTTPWiringOptions & RunHTTPWiringParams) => Promise<Out | void>;
@@ -1,14 +1,13 @@
1
- import { PikkuWiringTypes, } from '../../types/core.types.js';
2
1
  import { NotFoundError } from '../../errors/errors.js';
3
- import { closeSessionServices, createWeakUID, isSerializable, } from '../../utils.js';
4
- import { PikkuUserSessionService } from '../../services/user-session-service.js';
2
+ import { closeWireServices, createWeakUID, isSerializable, } from '../../utils.js';
3
+ import { PikkuSessionService } from '../../services/user-session-service.js';
5
4
  import { handleHTTPError } from '../../handle-error.js';
6
5
  import { pikkuState } from '../../pikku-state.js';
7
6
  import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
8
7
  import { PikkuFetchHTTPRequest } from './pikku-fetch-http-request.js';
9
8
  import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
10
- import { rpcService } from '../rpc/rpc-runner.js';
11
9
  import { httpRouter } from './routers/http-router.js';
10
+ import { startWorkflowByHttpWire } from '../workflow/workflow-utils.js';
12
11
  /**
13
12
  * Registers HTTP middleware for a specific route pattern.
14
13
  *
@@ -38,8 +37,8 @@ import { httpRouter } from './routers/http-router.js';
38
37
  * ])
39
38
  * ```
40
39
  */
41
- export const addHTTPMiddleware = (pattern, middleware) => {
42
- const httpGroups = pikkuState('middleware', 'httpGroup');
40
+ export const addHTTPMiddleware = (pattern, middleware, packageName = null) => {
41
+ const httpGroups = pikkuState(packageName, 'middleware', 'httpGroup');
43
42
  httpGroups[pattern] = middleware;
44
43
  return middleware;
45
44
  };
@@ -72,8 +71,8 @@ export const addHTTPMiddleware = (pattern, middleware) => {
72
71
  * ])
73
72
  * ```
74
73
  */
75
- export const addHTTPPermission = (pattern, permissions) => {
76
- const httpGroups = pikkuState('permissions', 'httpGroup');
74
+ export const addHTTPPermission = (pattern, permissions, packageName = null) => {
75
+ const httpGroups = pikkuState(packageName, 'permissions', 'httpGroup');
77
76
  httpGroups[pattern] = permissions;
78
77
  return permissions;
79
78
  };
@@ -93,17 +92,19 @@ export const addHTTPPermission = (pattern, permissions) => {
93
92
  * @param {CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction, PikkuFunctionSessionless, PikkuPermission, PikkuMiddleware>} httpWiring - The HTTP wiring configuration object.
94
93
  */
95
94
  export const wireHTTP = (httpWiring) => {
96
- const httpMeta = pikkuState('http', 'meta');
95
+ const httpMeta = pikkuState(null, 'http', 'meta');
97
96
  const routeMeta = httpMeta[httpWiring.method][httpWiring.route];
98
97
  if (!routeMeta) {
99
98
  throw new Error('Route metadata not found');
100
99
  }
101
- addFunction(routeMeta.pikkuFuncName, httpWiring.func);
102
- const routes = pikkuState('http', 'routes');
100
+ if (httpWiring.func) {
101
+ addFunction(routeMeta.pikkuFuncName, httpWiring.func);
102
+ }
103
+ const routes = pikkuState(null, 'http', 'routes');
103
104
  if (!routes.has(httpWiring.method)) {
104
105
  routes.set(httpWiring.method, new Map());
105
106
  }
106
- pikkuState('http', 'routes')
107
+ pikkuState(null, 'http', 'routes')
107
108
  .get(httpWiring.method)
108
109
  ?.set(httpWiring.route, httpWiring);
109
110
  };
@@ -121,10 +122,10 @@ export const wireHTTP = (httpWiring) => {
121
122
  const getMatchingRoute = (requestType, requestPath) => {
122
123
  const matchedPath = httpRouter.match(requestType.toLowerCase(), requestPath);
123
124
  if (matchedPath) {
124
- const route = pikkuState('http', 'routes')
125
+ const route = pikkuState(null, 'http', 'routes')
125
126
  .get(requestType.toLowerCase())
126
127
  .get(matchedPath.route);
127
- const meta = pikkuState('http', 'meta')[requestType.toLowerCase()][route.route];
128
+ const meta = pikkuState(null, 'http', 'meta')[requestType.toLowerCase()][route.route];
128
129
  return {
129
130
  matchedPath,
130
131
  params: matchedPath.params,
@@ -135,16 +136,16 @@ const getMatchingRoute = (requestType, requestPath) => {
135
136
  }
136
137
  };
137
138
  /**
138
- * Combines the request and response objects into a single HTTP interaction object.
139
+ * Combines the request and response objects into a single HTTP wire object.
139
140
  *
140
141
  * This utility function creates an object that holds both the HTTP request and response,
141
142
  * which simplifies passing these around through middleware and route execution.
142
143
  *
143
144
  * @param {PikkuHTTPRequest | undefined} request - The HTTP request object.
144
145
  * @param {PikkuHTTPResponse | undefined} response - The HTTP response object.
145
- * @returns {PikkuHTTP | undefined} The combined HTTP interaction object or undefined if none provided.
146
+ * @returns {PikkuHTTP | undefined} The combined HTTP wire object or undefined if none provided.
146
147
  */
147
- export const createHTTPInteraction = (request, response) => {
148
+ export const createHTTPWire = (request, response) => {
148
149
  let http = undefined;
149
150
  if (request || response) {
150
151
  http = {};
@@ -172,20 +173,20 @@ export const createHTTPInteraction = (request, response) => {
172
173
  *
173
174
  * @param {Object} services - A collection of shared services and utilities.
174
175
  * @param {Object} matchedRoute - Contains route details, URL parameters, and optional schema.
175
- * @param {PikkuHTTP | undefined} http - The HTTP interaction object.
176
+ * @param {PikkuHTTP | undefined} http - The HTTP wire object.
176
177
  * @param {Object} options - Options for route execution (e.g., whether to coerce query strings to arrays).
177
- * @returns {Promise<any>} An object containing the route handler result and session services (if any).
178
+ * @returns {Promise<any>} An object containing the route handler result and wire services (if any).
178
179
  * @throws Throws errors like MissingSessionError or ForbiddenError on validation failures.
179
180
  */
180
181
  const executeRoute = async (services, matchedRoute, http, options) => {
181
- const userSession = new PikkuUserSessionService();
182
+ const userSession = new PikkuSessionService();
182
183
  const { params, route, meta } = matchedRoute;
183
- const { singletonServices, createSessionServices, skipUserSession, requestId, } = services;
184
- const requiresSession = route.auth !== false;
185
- let sessionServices;
186
- let result;
184
+ const { singletonServices, createWireServices, skipUserSession, requestId } = services;
187
185
  // Attach URL parameters to the request object
188
186
  http?.request?.setParams(params);
187
+ const requiresSession = route.auth !== false;
188
+ let wireServices;
189
+ let result;
189
190
  singletonServices.logger.info(`Matched route: ${route.route} | method: ${route.method.toUpperCase()} | auth: ${requiresSession.toString()}`);
190
191
  // Ensure session is available when required
191
192
  if (skipUserSession && requiresSession) {
@@ -219,23 +220,17 @@ const executeRoute = async (services, matchedRoute, http, options) => {
219
220
  state: 'open',
220
221
  };
221
222
  }
222
- const interaction = { http, channel };
223
- const getAllServices = async (session) => {
224
- // Create session-specific services for handling the request
225
- sessionServices = await createSessionServices({ ...singletonServices, userSession, channel }, { http }, session);
226
- return rpcService.injectRPCService({
227
- ...singletonServices,
228
- ...sessionServices,
229
- http,
230
- userSession,
231
- channel,
232
- }, interaction, route.auth);
233
- };
234
- result = await runPikkuFunc(PikkuWiringTypes.http, `${meta.method}:${meta.route}`, meta.pikkuFuncName, {
223
+ const wire = { http, channel, session: userSession };
224
+ if (matchedRoute.meta.workflow === true) {
225
+ await startWorkflowByHttpWire(singletonServices, createWireServices, matchedRoute, wire);
226
+ return wireServices
227
+ ? { wireServices, result: http.response }
228
+ : { result: http.response };
229
+ }
230
+ result = await runPikkuFunc('http', `${meta.method}:${meta.route}`, meta.pikkuFuncName, {
235
231
  singletonServices,
236
- getAllServices,
232
+ createWireServices,
237
233
  auth: route.auth !== false,
238
- userSession,
239
234
  data,
240
235
  inheritedMiddleware: meta.middleware,
241
236
  wireMiddleware: route.middleware,
@@ -243,7 +238,7 @@ const executeRoute = async (services, matchedRoute, http, options) => {
243
238
  wirePermissions: route.permissions,
244
239
  coerceDataFromSchema: options.coerceDataFromSchema,
245
240
  tags: route.tags,
246
- interaction,
241
+ wire,
247
242
  });
248
243
  // Respond with either a binary or JSON response based on configuration
249
244
  if (route.returnsJSON === false) {
@@ -255,7 +250,7 @@ const executeRoute = async (services, matchedRoute, http, options) => {
255
250
  http?.response?.status(200);
256
251
  // TODO: Evaluate if the response stream should be explicitly ended.
257
252
  // http?.response?.end()
258
- return sessionServices ? { result, sessionServices } : { result };
253
+ return wireServices ? { result, wireServices } : { result };
259
254
  };
260
255
  /**
261
256
  * Executes an HTTP route for a given Fetch API request.
@@ -299,11 +294,11 @@ export const pikkuFetch = async (request, params) => {
299
294
  * middleware execution, error handling, and session service cleanup.
300
295
  *
301
296
  * This function does the following:
302
- * - Wraps the incoming request and response into an HTTP interaction object.
297
+ * - Wraps the incoming request and response into an HTTP wire object.
303
298
  * - Determines the correct route based on HTTP method and path.
304
299
  * - Executes middleware and the route handler.
305
300
  * - Catches and handles errors, optionally bubbling them if configured.
306
- * - Cleans up any session services created during processing.
301
+ * - Cleans up any wire services created during processing.
307
302
  *
308
303
  * @template In Expected input data type.
309
304
  * @template Out Expected output data type.
@@ -312,14 +307,14 @@ export const pikkuFetch = async (request, params) => {
312
307
  * @param {RunHTTPWiringOptions & RunHTTPWiringParams} options - Options such as singleton services, session handling, and error configuration.
313
308
  * @returns {Promise<Out | void>} The output from the route handler or void if an error occurred.
314
309
  */
315
- export const fetchData = async (request, response, { singletonServices, createSessionServices, skipUserSession = false, respondWith404 = true, logWarningsForStatusCodes = [], coerceDataFromSchema = true, bubbleErrors = false, generateRequestId, }) => {
310
+ export const fetchData = async (request, response, { singletonServices, createWireServices, skipUserSession = false, respondWith404 = true, logWarningsForStatusCodes = [], coerceDataFromSchema = true, bubbleErrors = false, generateRequestId, }) => {
316
311
  const requestId = request.getHeader?.('x-request-id') ||
317
312
  generateRequestId?.() ||
318
313
  createWeakUID();
319
- let sessionServices;
314
+ let wireServices;
320
315
  let result;
321
- // Combine the request and response into one interaction object
322
- const http = createHTTPInteraction(request instanceof Request ? new PikkuFetchHTTPRequest(request) : request, response);
316
+ // Combine the request and response into one wire object
317
+ const http = createHTTPWire(request instanceof Request ? new PikkuFetchHTTPRequest(request) : request, response);
323
318
  const apiType = http.request.method();
324
319
  const apiRoute = http.request.path();
325
320
  // Locate the matching route based on the HTTP method and path
@@ -336,9 +331,9 @@ export const fetchData = async (request, response, { singletonServices, createSe
336
331
  }
337
332
  // Execute the matched route along with its middleware and session management
338
333
  ;
339
- ({ result, sessionServices } = await executeRoute({
334
+ ({ result, wireServices } = await executeRoute({
340
335
  singletonServices,
341
- createSessionServices,
336
+ createWireServices,
342
337
  skipUserSession,
343
338
  requestId,
344
339
  }, matchedRoute, http, { coerceDataFromSchema }));
@@ -350,8 +345,8 @@ export const fetchData = async (request, response, { singletonServices, createSe
350
345
  }
351
346
  finally {
352
347
  // Clean up any session-specific services created during processing
353
- if (sessionServices) {
354
- await closeSessionServices(singletonServices.logger, sessionServices);
348
+ if (wireServices) {
349
+ await closeWireServices(singletonServices.logger, wireServices);
355
350
  }
356
351
  }
357
352
  };
@@ -1,6 +1,6 @@
1
1
  import type { SerializeOptions } from 'cookie';
2
2
  import type { PikkuError } from '../../errors/error-handler.js';
3
- import type { PikkuDocs, CoreServices, CoreSingletonServices, CoreUserSession, CreateSessionServices, CorePikkuMiddleware, MiddlewareMetadata, PermissionMetadata } from '../../types/core.types.js';
3
+ import type { CoreServices, CoreSingletonServices, CoreUserSession, CreateWireServices, CorePikkuMiddleware, CommonWireMeta } from '../../types/core.types.js';
4
4
  import type { CorePikkuFunction, CorePikkuFunctionSessionless, CorePikkuPermission, CorePermissionGroup, CorePikkuFunctionConfig } from '../../function/functions.types.js';
5
5
  type ExtractHTTPWiringParams<S extends string> = S extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractHTTPWiringParams<`/${Rest}`> : S extends `${string}:${infer Param}` ? Param : never;
6
6
  export type AssertHTTPWiringParams<In, HTTPWiring extends string> = ExtractHTTPWiringParams<HTTPWiring> extends keyof In ? unknown : [
@@ -19,7 +19,7 @@ export type RunHTTPWiringOptions = Partial<{
19
19
  }>;
20
20
  export type RunHTTPWiringParams = {
21
21
  singletonServices: CoreSingletonServices;
22
- createSessionServices: CreateSessionServices<CoreSingletonServices, CoreServices<CoreSingletonServices>, CoreUserSession>;
22
+ createWireServices: CreateWireServices<CoreSingletonServices, CoreServices<CoreSingletonServices>, CoreUserSession>;
23
23
  };
24
24
  /**
25
25
  * Represents the HTTP methods supported for API HTTP wirings.
@@ -43,7 +43,7 @@ export type CoreHTTPFunction = {
43
43
  }>;
44
44
  };
45
45
  /**
46
- * Represents a http interaction within Pikku, including a request and response.
46
+ * Represents a http wire within Pikku, including a request and response.
47
47
  */
48
48
  export interface PikkuHTTP<In = unknown> {
49
49
  request?: PikkuHTTPRequest<In>;
@@ -67,7 +67,7 @@ export type PikkuQuery<T = Record<string, string | undefined>> = Record<string,
67
67
  * @template PikkuFunctionSessionless - The sessionless API function type, defaults to `CorePikkuFunctionSessionless`.
68
68
  * @template PikkuPermission - The permission function type, defaults to `CorePikkuPermission`.
69
69
  */
70
- export type CoreHTTPFunctionWiring<In, Out, R extends string, PikkuFunction extends CorePikkuFunction<In, Out, any, any, any> = CorePikkuFunction<In, Out>, PikkuFunctionSessionless extends CorePikkuFunctionSessionless<In, Out, any, any, any> = CorePikkuFunctionSessionless<In, Out>, PikkuPermission extends CorePikkuPermission<In, any, any> = CorePikkuPermission<In, any, any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any>> = (CoreHTTPFunction & {
70
+ export type CoreHTTPFunctionWiring<In, Out, R extends string, PikkuFunction extends CorePikkuFunction<In, Out, any, any> = CorePikkuFunction<In, Out>, PikkuFunctionSessionless extends CorePikkuFunctionSessionless<In, Out, any, any> = CorePikkuFunctionSessionless<In, Out>, PikkuPermission extends CorePikkuPermission<In, any, any> = CorePikkuPermission<In, any, any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any>> = (CoreHTTPFunction & {
71
71
  route: R;
72
72
  method: HTTPMethod;
73
73
  func: CorePikkuFunctionConfig<PikkuFunction, PikkuPermission, PikkuMiddleware>;
@@ -123,7 +123,19 @@ export type CoreHTTPFunctionWiring<In, Out, R extends string, PikkuFunction exte
123
123
  tags?: string[];
124
124
  middleware?: PikkuMiddleware[];
125
125
  sse?: undefined;
126
- });
126
+ }) | {
127
+ /** Route triggers a workflow matched by route/method from workflow wires.http */
128
+ route: R;
129
+ method: HTTPMethod;
130
+ workflow: true;
131
+ func?: undefined;
132
+ permissions?: undefined;
133
+ auth?: undefined;
134
+ tags?: undefined;
135
+ middleware?: undefined;
136
+ returnsJSON?: undefined;
137
+ sse?: boolean;
138
+ };
127
139
  /**
128
140
  * Represents the input types for HTTP wiring metadata, including parameters, query, and body types.
129
141
  */
@@ -135,18 +147,14 @@ export type HTTPFunctionMetaInputTypes = {
135
147
  /**
136
148
  * Represents metadata for a set of HTTP wirings, including HTTP wiring details, methods, input/output types, and documentation.
137
149
  */
138
- export type HTTPWiringMeta = {
139
- pikkuFuncName: string;
150
+ export type HTTPWiringMeta = CommonWireMeta & {
140
151
  route: string;
141
152
  method: HTTPMethod;
142
153
  params?: string[];
143
154
  query?: string[];
144
155
  inputTypes?: HTTPFunctionMetaInputTypes;
145
- docs?: PikkuDocs;
146
- tags?: string[];
147
156
  sse?: true;
148
- middleware?: MiddlewareMetadata[];
149
- permissions?: PermissionMetadata[];
157
+ workflow?: true;
150
158
  };
151
159
  export type HTTPWiringsMeta = Record<HTTPMethod, Record<string, HTTPWiringMeta>>;
152
160
  export type HTTPFunctionsMeta = Array<{
@@ -4,7 +4,7 @@ import { pikkuState } from '../../pikku-state.js';
4
4
  * @param logger - A logger for logging information.
5
5
  */
6
6
  export const logRoutes = (logger) => {
7
- const routesByType = pikkuState('http', 'routes');
7
+ const routesByType = pikkuState(null, 'http', 'routes');
8
8
  if (routesByType.size === 0) {
9
9
  logger.info('No routes added');
10
10
  return;
@@ -10,8 +10,8 @@ export class PathToRegexRouter {
10
10
  this.isInitialized = false;
11
11
  }
12
12
  initialize() {
13
- const routes = pikkuState('http', 'routes');
14
- const channelRoutes = pikkuState('channel', 'channels');
13
+ const routes = pikkuState(null, 'http', 'routes');
14
+ const channelRoutes = pikkuState(null, 'channel', 'channels');
15
15
  // Helper function to compile routes for a given method
16
16
  const compileRoutesForMethod = (method, routeEntries) => {
17
17
  const methodCompiledRoutes = this.compiledRoutes.get(method) || new Map();
@@ -1,4 +1,4 @@
1
- import { type CoreServices, type CoreSingletonServices, type CoreUserSession, type CreateSessionServices } from '../../types/core.types.js';
1
+ import { type CoreServices, type CoreSingletonServices, type CoreUserSession, type CreateWireServices } from '../../types/core.types.js';
2
2
  import type { CoreMCPResource, CoreMCPTool, CoreMCPPrompt, JsonRpcRequest, JsonRpcResponse, JsonRpcErrorResponse, PikkuMCP } from './mcp.types.js';
3
3
  import type { CorePikkuFunctionConfig, CorePikkuFunctionSessionless } from '../../function/functions.types.js';
4
4
  export declare class MCPError extends Error {
@@ -8,7 +8,7 @@ export declare class MCPError extends Error {
8
8
  export type RunMCPEndpointParams<Tools extends string = any> = {
9
9
  singletonServices: CoreSingletonServices;
10
10
  mcp?: PikkuMCP<Tools>;
11
- createSessionServices?: CreateSessionServices<CoreSingletonServices, CoreServices<CoreSingletonServices>, CoreUserSession>;
11
+ createWireServices?: CreateWireServices<CoreSingletonServices, CoreServices<CoreSingletonServices>, CoreUserSession>;
12
12
  };
13
13
  export type JsonRpcError = {
14
14
  code: number;