@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,230 +1,185 @@
1
- import { ChannelsMeta, CoreChannel } from './wirings/channel/channel.types.js'
1
+ import { PikkuPackageState } from './index.js'
2
+ import { HTTPWiringsMeta } from './wirings/http/http.types.js'
2
3
  import {
3
- CoreHTTPFunctionWiring,
4
- HTTPMethod,
5
- HTTPWiringsMeta,
6
- } from './wirings/http/http.types.js'
7
- import {
8
- FunctionsMeta,
9
- CorePikkuMiddleware,
10
- CorePikkuMiddlewareGroup,
11
- FunctionServicesMeta,
12
- } from './types/core.types.js'
13
- import {
14
- CoreScheduledTask,
15
- ScheduledTasksMeta,
16
- } from './wirings/scheduler/scheduler.types.js'
17
- import { ErrorDetails, PikkuError } from './errors/error-handler.js'
18
- import {
19
- CorePermissionGroup,
20
- CorePikkuFunctionConfig,
21
- CorePikkuPermission,
22
- } from './function/functions.types.js'
23
- import {
24
- QueueWorkersMeta,
25
- CoreQueueWorker,
26
- } from './wirings/queue/queue.types.js'
27
- import {
28
- CoreMCPResource,
29
- CoreMCPTool,
30
- CoreMCPPrompt,
31
4
  MCPResourceMeta,
32
5
  MCPToolMeta,
33
6
  MCPPromptMeta,
34
7
  } from './wirings/mcp/mcp.types.js'
35
- import { CLIMeta, CLIProgramState } from './wirings/cli/cli.types.js'
36
- import {
37
- CoreWorkflow,
38
- WorkflowsMeta,
39
- } from './wirings/workflow/workflow.types.js'
8
+ import { ScheduledTasksMeta } from './wirings/scheduler/scheduler.types.js'
9
+ import { TriggerMeta } from './wirings/trigger/trigger.types.js'
40
10
 
41
- interface PikkuState {
42
- function: {
43
- meta: FunctionsMeta
44
- functions: Map<string, CorePikkuFunctionConfig<any, any>>
11
+ declare global {
12
+ // eslint-disable-next-line no-var
13
+ var pikkuState: Map<string, PikkuPackageState> | undefined
14
+ }
15
+
16
+ /**
17
+ * Get or set package-scoped pikku state
18
+ *
19
+ * @param packageName - Package name (null for main package, '@scope/package' for external packages)
20
+ * @param type - State category (function, rpc, http, etc.)
21
+ * @param content - Content key within the category
22
+ * @param value - Optional value to set
23
+ * @returns The current value of the state
24
+ *
25
+ * @example
26
+ * // Main package
27
+ * pikkuState(null, 'function', 'functions').get(funcName)
28
+ *
29
+ * // External package
30
+ * pikkuState('@acme/stripe-functions', 'rpc', 'meta')
31
+ */
32
+ export const pikkuState = <
33
+ Type extends keyof PikkuPackageState,
34
+ Content extends keyof PikkuPackageState[Type],
35
+ >(
36
+ packageName: string | null,
37
+ type: Type,
38
+ content: Content,
39
+ value?: PikkuPackageState[Type][Content]
40
+ ): PikkuPackageState[Type][Content] => {
41
+ const resolvedPackageName = packageName ?? '__main__'
42
+
43
+ // Initialize package state if it doesn't exist
44
+ if (
45
+ !globalThis.pikkuState ||
46
+ !globalThis.pikkuState.has(resolvedPackageName)
47
+ ) {
48
+ initializePikkuState(resolvedPackageName)
45
49
  }
46
- rpc: {
47
- meta: Record<string, string>
48
- files: Map<
49
- string,
50
- {
51
- exportedName: string
52
- path: string
53
- }
54
- >
50
+
51
+ const packageState = globalThis.pikkuState!.get(resolvedPackageName)!
52
+
53
+ if (value !== undefined) {
54
+ packageState[type][content] = value
55
55
  }
56
+
57
+ return packageState[type][content]
58
+ }
59
+
60
+ const createEmptyPackageState = (): PikkuPackageState => ({
61
+ function: {
62
+ meta: {},
63
+ functions: new Map(),
64
+ },
65
+ rpc: {
66
+ meta: {},
67
+ files: new Map(),
68
+ externalPackages: new Map(),
69
+ },
56
70
  http: {
57
- middleware: Map<string, CorePikkuMiddleware<any, any>[]>
58
- permissions: Map<string, CorePermissionGroup | CorePikkuPermission[]>
59
- routes: Map<HTTPMethod, Map<string, CoreHTTPFunctionWiring<any, any, any>>>
60
- meta: HTTPWiringsMeta
61
- }
71
+ middleware: new Map(),
72
+ permissions: new Map(),
73
+ routes: new Map(),
74
+ meta: {
75
+ post: {},
76
+ get: {},
77
+ delete: {},
78
+ patch: {},
79
+ head: {},
80
+ put: {},
81
+ options: {},
82
+ } as HTTPWiringsMeta,
83
+ },
62
84
  channel: {
63
- channels: Map<string, CoreChannel<any, any>>
64
- meta: ChannelsMeta
65
- }
85
+ channels: new Map(),
86
+ meta: {},
87
+ },
66
88
  scheduler: {
67
- tasks: Map<string, CoreScheduledTask>
68
- meta: ScheduledTasksMeta
69
- }
89
+ tasks: new Map(),
90
+ meta: [] as unknown as ScheduledTasksMeta,
91
+ },
70
92
  queue: {
71
- registrations: Map<string, CoreQueueWorker>
72
- meta: QueueWorkersMeta
73
- }
93
+ registrations: new Map(),
94
+ meta: {},
95
+ },
74
96
  workflows: {
75
- registrations: Map<string, CoreWorkflow>
76
- meta: WorkflowsMeta
77
- }
97
+ registrations: new Map(),
98
+ graphRegistrations: new Map(),
99
+ wirings: new Map(),
100
+ graphWirings: new Map(),
101
+ meta: {},
102
+ },
103
+ trigger: {
104
+ triggers: new Map(),
105
+ meta: {} as TriggerMeta,
106
+ },
78
107
  mcp: {
79
- resources: Map<string, CoreMCPResource>
80
- resourcesMeta: MCPResourceMeta
81
- tools: Map<string, CoreMCPTool>
82
- toolsMeta: MCPToolMeta
83
- prompts: Map<string, CoreMCPPrompt>
84
- promptsMeta: MCPPromptMeta
85
- }
108
+ resources: new Map(),
109
+ resourcesMeta: {} as MCPResourceMeta,
110
+ tools: new Map(),
111
+ toolsMeta: {} as MCPToolMeta,
112
+ prompts: new Map(),
113
+ promptsMeta: {} as MCPPromptMeta,
114
+ },
86
115
  cli: {
87
- meta: CLIMeta | Record<string, any> // Backward compatible with old published CLI format
88
- programs: Record<string, CLIProgramState>
89
- }
116
+ meta: { programs: {}, renderers: {} },
117
+ programs: {},
118
+ },
90
119
  middleware: {
91
- tagGroup: Record<string, CorePikkuMiddlewareGroup>
92
- httpGroup: Record<string, CorePikkuMiddlewareGroup>
93
- tagGroupMeta: Record<
94
- string,
95
- {
96
- exportName: string | null
97
- sourceFile: string
98
- position: number
99
- services: FunctionServicesMeta
100
- middlewareCount: number
101
- isFactory: boolean
102
- }
103
- >
104
- httpGroupMeta: Record<
105
- string,
106
- {
107
- exportName: string | null
108
- sourceFile: string
109
- position: number
110
- services: FunctionServicesMeta
111
- middlewareCount: number
112
- isFactory: boolean
113
- }
114
- >
115
- }
120
+ tagGroup: {},
121
+ httpGroup: {},
122
+ tagGroupMeta: {},
123
+ httpGroupMeta: {},
124
+ },
116
125
  permissions: {
117
- tagGroup: Record<string, CorePermissionGroup | CorePikkuPermission[]>
118
- httpGroup: Record<string, CorePermissionGroup | CorePikkuPermission[]>
119
- tagGroupMeta: Record<
120
- string,
121
- {
122
- exportName: string | null
123
- sourceFile: string
124
- position: number
125
- services: FunctionServicesMeta
126
- permissionCount: number
127
- isFactory: boolean
128
- }
129
- >
130
- httpGroupMeta: Record<
131
- string,
132
- {
133
- exportName: string | null
134
- sourceFile: string
135
- position: number
136
- services: FunctionServicesMeta
137
- permissionCount: number
138
- isFactory: boolean
139
- }
140
- >
141
- }
126
+ tagGroup: {},
127
+ httpGroup: {},
128
+ tagGroupMeta: {},
129
+ httpGroupMeta: {},
130
+ },
142
131
  misc: {
143
- errors: Map<PikkuError, ErrorDetails>
144
- schemas: Map<string, any>
145
- middleware: Record<string, CorePikkuMiddleware[]>
146
- permissions: Record<string, CorePermissionGroup | CorePikkuPermission[]>
132
+ errors: new Map(),
133
+ schemas: new Map(),
134
+ middleware: {},
135
+ permissions: {},
136
+ },
137
+ package: {
138
+ factories: null,
139
+ singletonServices: null,
140
+ },
141
+ })
142
+
143
+ /**
144
+ * Initialize state for a new package
145
+ */
146
+ export const initializePikkuState = (packageName: string): void => {
147
+ if (!globalThis.pikkuState) {
148
+ globalThis.pikkuState = new Map()
149
+ }
150
+ if (!globalThis.pikkuState.has(packageName)) {
151
+ globalThis.pikkuState.set(packageName, createEmptyPackageState())
147
152
  }
148
153
  }
149
154
 
150
155
  export const resetPikkuState = () => {
151
- globalThis.pikkuState = {
152
- function: {
153
- meta: {},
154
- functions: new Map(),
155
- },
156
- rpc: {
157
- meta: {},
158
- files: new Map(),
159
- },
160
- http: {
161
- permissions: new Map(),
162
- routes: new Map(),
163
- meta: {},
164
- },
165
- channel: {
166
- channels: new Map(),
167
- meta: {},
168
- },
169
- scheduler: {
170
- tasks: new Map(),
171
- meta: [] as unknown as ScheduledTasksMeta,
172
- },
173
- queue: {
174
- registrations: new Map(),
175
- meta: {},
176
- },
177
- workflows: {
178
- registrations: new Map(),
179
- meta: {},
180
- },
181
- mcp: {
182
- resources: new Map(),
183
- resourcesMeta: {} as MCPResourceMeta,
184
- tools: new Map(),
185
- toolsMeta: {} as MCPToolMeta,
186
- prompts: new Map(),
187
- promptsMeta: {} as MCPPromptMeta,
188
- },
189
- cli: {
190
- meta: { programs: {}, renderers: {} },
191
- programs: {},
192
- },
193
- middleware: {
194
- tagGroup: {},
195
- httpGroup: {},
196
- tagGroupMeta: {},
197
- httpGroupMeta: {},
198
- },
199
- permissions: {
200
- tagGroup: {},
201
- httpGroup: {},
202
- tagGroupMeta: {},
203
- httpGroupMeta: {},
204
- },
205
- misc: {
206
- errors: globalThis.pikkuState?.misc?.errors || new Map(),
207
- schemas: new Map(),
208
- middleware: {},
209
- permissions: {},
210
- },
211
- } as PikkuState
156
+ // Preserve the errors map before resetting
157
+ const existingErrors = globalThis.pikkuState?.get('__main__')?.misc.errors
158
+
159
+ globalThis.pikkuState = new Map()
160
+ initializePikkuState('__main__')
161
+
162
+ // Restore the errors map if it existed
163
+ if (existingErrors) {
164
+ const mainState = globalThis.pikkuState.get('__main__')!
165
+ mainState.misc.errors = existingErrors
166
+ }
212
167
  }
213
168
 
214
169
  if (!globalThis.pikkuState) {
215
170
  resetPikkuState()
216
171
  }
217
172
 
218
- export const pikkuState = <
219
- Type extends keyof PikkuState,
220
- Content extends keyof PikkuState[Type],
221
- >(
222
- type: Type,
223
- content: Content,
224
- value?: PikkuState[Type][Content]
225
- ): PikkuState[Type][Content] => {
226
- if (value) {
227
- globalThis.pikkuState[type][content] = value
228
- }
229
- return globalThis.pikkuState[type][content]
173
+ /**
174
+ * Register service factories for an external package.
175
+ * These factories are used to create services when the package's functions are invoked.
176
+ *
177
+ * @param packageName - The package name (e.g., '@pikku/templates-function-external')
178
+ * @param factories - The service factory functions
179
+ */
180
+ export const addPackageServiceFactories = (
181
+ packageName: string,
182
+ factories: NonNullable<PikkuPackageState['package']['factories']>
183
+ ): void => {
184
+ pikkuState(packageName, 'package', 'factories', factories)
230
185
  }
package/src/schema.ts CHANGED
@@ -4,25 +4,32 @@ import { UnprocessableContentError } from './errors/errors.js'
4
4
  import { pikkuState } from './pikku-state.js'
5
5
 
6
6
  /**
7
- * Adds a schema to the global schemas map.
7
+ * Adds a schema to the schemas map for a specific package.
8
8
  * @param name - The name of the schema.
9
9
  * @param value - The schema value.
10
+ * @param packageName - The package name (null for main package, '@scope/package' for external packages).
10
11
  * @ignore
11
12
  */
12
- export const addSchema = (name: string, value: any) => {
13
- pikkuState('misc', 'schemas').set(name, value)
13
+ export const addSchema = (
14
+ name: string,
15
+ value: any,
16
+ packageName: string | null = null
17
+ ) => {
18
+ pikkuState(packageName, 'misc', 'schemas').set(name, value)
14
19
  }
15
20
 
16
21
  /**
17
- * Retrieves a schema from the global schemas map.
22
+ * Retrieves a schema from the schemas map for a specific package.
18
23
  * @param name - The name of the schema.
24
+ * @param packageName - The package name (null for main package, '@scope/package' for external packages).
19
25
  * @returns The schema value or undefined if not found.
20
26
  * @ignore
21
27
  */
22
28
  export const getSchema = (
23
- name: string
29
+ name: string,
30
+ packageName: string | null = null
24
31
  ): Record<string, unknown> | undefined => {
25
- return pikkuState('misc', 'schemas').get(name)
32
+ return pikkuState(packageName, 'misc', 'schemas').get(name)
26
33
  }
27
34
 
28
35
  /**
@@ -36,7 +43,7 @@ export const compileAllSchemas = (
36
43
  if (!schemaService) {
37
44
  throw new Error('SchemaService needs to be defined to load schemas')
38
45
  }
39
- const schemas = pikkuState('misc', 'schemas')
46
+ const schemas = pikkuState(null, 'misc', 'schemas')
40
47
  for (const [name, schema] of schemas) {
41
48
  schemaService.compileSchema(name, schema)
42
49
  }
@@ -47,14 +54,15 @@ const validateAllSchemasLoaded = (
47
54
  logger: Logger,
48
55
  schemaService: SchemaService
49
56
  ) => {
50
- const routesMeta = pikkuState('http', 'meta')
57
+ const routesMeta = pikkuState(null, 'http', 'meta')
51
58
  const validators = schemaService.getSchemaNames()
52
59
 
53
60
  const missingSchemas: string[] = []
54
61
 
55
62
  for (const routePaths of Object.values(routesMeta)) {
56
63
  for (const meta of Object.values(routePaths)) {
57
- const inputs = pikkuState('function', 'meta')[meta.pikkuFuncName]?.inputs
64
+ const inputs = pikkuState(null, 'function', 'meta')[meta.pikkuFuncName]
65
+ ?.inputs
58
66
  const input = inputs?.[0]
59
67
  if (!input || validators.has(input)) {
60
68
  continue
@@ -74,8 +82,12 @@ const validateAllSchemasLoaded = (
74
82
  }
75
83
  }
76
84
 
77
- export const coerceTopLevelDataFromSchema = (schemaName: string, data: any) => {
78
- const schema = pikkuState('misc', 'schemas').get(schemaName)
85
+ export const coerceTopLevelDataFromSchema = (
86
+ schemaName: string,
87
+ data: any,
88
+ packageName: string | null = null
89
+ ) => {
90
+ const schema = pikkuState(packageName, 'misc', 'schemas').get(schemaName)
79
91
  for (const key in schema.properties) {
80
92
  const property = schema.properties[key]
81
93
  if (typeof property === 'boolean') {
@@ -97,7 +109,8 @@ export const validateSchema = async (
97
109
  logger: Logger,
98
110
  schemaService: SchemaService | undefined,
99
111
  schemaName: string | undefined | null,
100
- data: any
112
+ data: any,
113
+ packageName: string | null = null
101
114
  ) => {
102
115
  if (schemaService) {
103
116
  if (!schemaName) {
@@ -108,7 +121,23 @@ export const validateSchema = async (
108
121
  return
109
122
  }
110
123
  }
111
- const schema = pikkuState('misc', 'schemas').get(schemaName)
124
+ logger.debug(
125
+ `[validateSchema] Validating schema '${schemaName}' for package '${packageName ?? 'main'}' with data:`,
126
+ JSON.stringify(data)
127
+ )
128
+ const schemas = pikkuState(packageName, 'misc', 'schemas')
129
+ const schema = schemas.get(schemaName)
130
+ if (schema === undefined) {
131
+ const availableSchemas = Array.from(schemas.keys())
132
+ logger.error(
133
+ `Schema '${schemaName}' not found for package '${packageName ?? 'main'}'. Available schemas: ${availableSchemas.join(', ') || '(none)'}`
134
+ )
135
+ } else {
136
+ logger.debug(
137
+ `[validateSchema] Found schema '${schemaName}':`,
138
+ JSON.stringify(schema)
139
+ )
140
+ }
112
141
  await schemaService.compileSchema(schemaName, schema)
113
142
  await schemaService.validateSchema(schemaName, data)
114
143
  }
@@ -1,18 +1,21 @@
1
1
  import { ChannelStore } from '../wirings/channel/channel-store.js'
2
2
  import { CoreUserSession } from '../types/core.types.js'
3
3
 
4
- export interface UserSessionService<UserSession extends CoreUserSession> {
4
+ export interface SessionService<UserSession extends CoreUserSession> {
5
5
  sessionChanged: boolean
6
+ initial: UserSession | undefined
6
7
  setInitial(session: UserSession): void
8
+ freezeInitial(): UserSession | undefined
7
9
  set(session: UserSession): Promise<void> | void
8
10
  clear(): Promise<void> | void
9
- get(): Promise<UserSession | undefined> | UserSession | undefined
11
+ get(): Promise<UserSession> | UserSession | undefined
10
12
  }
11
13
 
12
- export class PikkuUserSessionService<UserSession extends CoreUserSession>
13
- implements UserSessionService<UserSession>
14
+ export class PikkuSessionService<UserSession extends CoreUserSession>
15
+ implements SessionService<UserSession>
14
16
  {
15
17
  public sessionChanged = false
18
+ public initial: UserSession | undefined
16
19
  private session: UserSession | undefined
17
20
  constructor(
18
21
  private channelStore?: ChannelStore<unknown, unknown, UserSession>,
@@ -27,6 +30,13 @@ export class PikkuUserSessionService<UserSession extends CoreUserSession>
27
30
  this.session = session
28
31
  }
29
32
 
33
+ public freezeInitial() {
34
+ if (this.initial === undefined) {
35
+ this.initial = this.session
36
+ }
37
+ return this.initial
38
+ }
39
+
30
40
  public set(session: UserSession) {
31
41
  this.sessionChanged = true
32
42
  this.session = session
@@ -0,0 +1,74 @@
1
+ import {
2
+ SerializedError,
3
+ CoreSingletonServices,
4
+ CreateWireServices,
5
+ CoreConfig,
6
+ } from '../types/core.types.js'
7
+ import {
8
+ WorkflowRun,
9
+ StepState,
10
+ WorkflowStatus,
11
+ } from '../wirings/workflow/workflow.types.js'
12
+
13
+ /**
14
+ * Interface for workflow orchestration
15
+ * Handles workflow execution, replay, orchestration logic, and run-level state
16
+ */
17
+ export interface WorkflowService {
18
+ // Run-level state operations
19
+ createRun(workflowName: string, input: any, inline?: boolean): Promise<string>
20
+ getRun(id: string): Promise<WorkflowRun | null>
21
+ getRunHistory(runId: string): Promise<Array<StepState & { stepName: string }>>
22
+ updateRunStatus(
23
+ id: string,
24
+ status: WorkflowStatus,
25
+ output?: any,
26
+ error?: SerializedError
27
+ ): Promise<void>
28
+ withRunLock<T>(id: string, fn: () => Promise<T>): Promise<T>
29
+ close(): Promise<void>
30
+
31
+ // Orchestration operations
32
+ resumeWorkflow(runId: string): Promise<void>
33
+ setServices(
34
+ singletonServices: CoreSingletonServices,
35
+ createWireServices: CreateWireServices,
36
+ config: CoreConfig
37
+ ): void
38
+ startWorkflow<I>(
39
+ name: string,
40
+ input: I,
41
+ rpcService: any,
42
+ options?: { inline?: boolean; startNode?: string }
43
+ ): Promise<{ runId: string }>
44
+ runWorkflowJob(runId: string, rpcService: any): Promise<void>
45
+ orchestrateWorkflow(runId: string, rpcService: any): Promise<void>
46
+ executeWorkflowSleepCompleted(runId: string, stepId: string): Promise<void>
47
+
48
+ // Step-level state operations
49
+ insertStepState(
50
+ runId: string,
51
+ stepName: string,
52
+ rpcName: string,
53
+ data: any,
54
+ stepOptions?: { retries?: number; retryDelay?: string | number }
55
+ ): Promise<StepState>
56
+ getStepState(runId: string, stepName: string): Promise<StepState>
57
+ setStepRunning(stepId: string): Promise<void>
58
+ setStepScheduled(stepId: string): Promise<void>
59
+ setStepResult(stepId: string, result: any): Promise<void>
60
+ setStepError(stepId: string, error: Error): Promise<void>
61
+ createRetryAttempt(
62
+ stepId: string,
63
+ status: 'pending' | 'running'
64
+ ): Promise<StepState>
65
+
66
+ // Step execution
67
+ executeWorkflowStep(
68
+ runId: string,
69
+ stepName: string,
70
+ rpcName: string | null,
71
+ data: any,
72
+ rpcService: any
73
+ ): Promise<void>
74
+ }