@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,4 +1,4 @@
1
- import type { CoreServices, PikkuInteraction } from '../../types/core.types.js'
1
+ import type { CoreServices, PikkuWire } from '../../types/core.types.js'
2
2
  import type { CoreQueueWorker, QueueJob, PikkuQueue } from './queue.types.js'
3
3
  import type {
4
4
  CorePikkuFunctionConfig,
@@ -7,11 +7,7 @@ import type {
7
7
  import { getErrorResponse, PikkuError } from '../../errors/error-handler.js'
8
8
  import { pikkuState } from '../../pikku-state.js'
9
9
  import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
10
- import {
11
- CreateSessionServices,
12
- PikkuWiringTypes,
13
- } from '../../types/core.types.js'
14
- import { rpcService } from '../rpc/rpc-runner.js'
10
+ import { CreateWireServices } from '../../types/core.types.js'
15
11
 
16
12
  /**
17
13
  * Error class for queue processor not found
@@ -56,7 +52,7 @@ export const wireQueueWorker = <
56
52
  queueWorker: CoreQueueWorker<PikkuFunctionConfig>
57
53
  ) => {
58
54
  // Get processor metadata
59
- const meta = pikkuState('queue', 'meta')
55
+ const meta = pikkuState(null, 'queue', 'meta')
60
56
  const processorMeta = meta[queueWorker.queueName]
61
57
  if (!processorMeta) {
62
58
  throw new Error(
@@ -71,11 +67,10 @@ export const wireQueueWorker = <
71
67
  permissions: queueWorker.func.permissions,
72
68
  middleware: queueWorker.func.middleware as any,
73
69
  tags: queueWorker.func.tags,
74
- docs: queueWorker.func.docs as any,
75
70
  })
76
71
 
77
72
  // Store processor definition in state - runtime adapters will pick this up
78
- const registrations = pikkuState('queue', 'registrations')
73
+ const registrations = pikkuState(null, 'queue', 'registrations')
79
74
  registrations.set(queueWorker.queueName, queueWorker)
80
75
  }
81
76
 
@@ -83,14 +78,14 @@ export const wireQueueWorker = <
83
78
  * Get all registered queue processors
84
79
  */
85
80
  export function getQueueWorkers(): Map<string, CoreQueueWorker> {
86
- return pikkuState('queue', 'registrations')
81
+ return pikkuState(null, 'queue', 'registrations')
87
82
  }
88
83
 
89
84
  /**
90
85
  * Stop and remove a queue processor
91
86
  */
92
87
  export async function removeQueueWorker(name: string): Promise<void> {
93
- const registrations = pikkuState('queue', 'registrations')
88
+ const registrations = pikkuState(null, 'queue', 'registrations')
94
89
  const registration = registrations.get(name)
95
90
 
96
91
  if (!registration) {
@@ -105,31 +100,31 @@ export async function removeQueueWorker(name: string): Promise<void> {
105
100
  */
106
101
  export async function runQueueJob({
107
102
  singletonServices,
108
- createSessionServices,
103
+ createWireServices,
109
104
  job,
110
105
  updateProgress,
111
106
  }: {
112
107
  singletonServices: CoreServices
113
- createSessionServices?: CreateSessionServices
108
+ createWireServices?: CreateWireServices
114
109
  job: QueueJob
115
110
  updateProgress?: (progress: number | string | object) => Promise<void>
116
111
  }): Promise<void> {
117
112
  const logger = singletonServices.logger
118
113
 
119
- const meta = pikkuState('queue', 'meta')
114
+ const meta = pikkuState(null, 'queue', 'meta')
120
115
  const processorMeta = meta[job.queueName]
121
116
  if (!processorMeta) {
122
117
  throw new Error(`Processor metadata not found for: ${job.queueName}`)
123
118
  }
124
119
 
125
120
  // Get the queue worker registration to access middleware
126
- const registrations = pikkuState('queue', 'registrations')
121
+ const registrations = pikkuState(null, 'queue', 'registrations')
127
122
  const queueWorker = registrations.get(job.queueName)
128
123
  if (!queueWorker) {
129
124
  throw new Error(`Queue worker registration not found for: ${job.queueName}`)
130
125
  }
131
126
 
132
- // Create the queue interaction object
127
+ // Create the queue wire object
133
128
  const queue: PikkuQueue = {
134
129
  queueName: job.queueName,
135
130
  jobId: job.id,
@@ -150,41 +145,24 @@ export async function runQueueJob({
150
145
  try {
151
146
  logger.info(`Processing job ${job.id} in queue ${job.queueName}`)
152
147
 
153
- const interaction: PikkuInteraction = { queue }
154
- // Use provided singleton services
155
- const getAllServices = async () => {
156
- const sessionServices = await createSessionServices?.(
157
- singletonServices,
158
- { queue },
159
- undefined
160
- )
161
-
162
- const services = rpcService.injectRPCService(
163
- {
164
- ...singletonServices,
165
- ...sessionServices,
166
- },
167
- interaction,
168
- false
169
- )
170
-
171
- return services
148
+ const wire: PikkuWire = {
149
+ queue,
172
150
  }
173
151
 
174
152
  // Execute the pikku function with the job data
175
153
  const result = await runPikkuFunc(
176
- PikkuWiringTypes.queue,
154
+ 'queue',
177
155
  job.queueName,
178
156
  processorMeta.pikkuFuncName,
179
157
  {
180
158
  singletonServices,
181
- getAllServices,
159
+ createWireServices,
182
160
  auth: false,
183
161
  data: () => job.data,
184
162
  inheritedMiddleware: processorMeta.middleware,
185
163
  wireMiddleware: queueWorker.middleware,
186
164
  tags: queueWorker.tags,
187
- interaction,
165
+ wire,
188
166
  }
189
167
  )
190
168
 
@@ -1,4 +1,4 @@
1
- import { PikkuDocs, MiddlewareMetadata } from '../../types/core.types.js'
1
+ import { CommonWireMeta } from '../../types/core.types.js'
2
2
  import { CorePikkuFunctionConfig } from '../../function/functions.types.js'
3
3
  import { QueueConfigMapping } from './validate-worker-config.js'
4
4
 
@@ -147,15 +147,9 @@ export interface QueueWorkers {
147
147
  */
148
148
  export type QueueWorkersMeta = Record<
149
149
  string,
150
- {
151
- pikkuFuncName: string
152
- schemaName?: string
150
+ CommonWireMeta & {
153
151
  queueName: string
154
- session?: undefined
155
- docs?: PikkuDocs
156
- tags?: string[]
157
152
  config?: PikkuWorkerConfig
158
- middleware?: MiddlewareMetadata[] // Pre-resolved middleware chain (tag + explicit)
159
153
  }
160
154
  >
161
155
 
@@ -172,14 +166,13 @@ export type CoreQueueWorker<
172
166
  queueName: string
173
167
  func: PikkuFunctionConfig
174
168
  config?: PikkuWorkerConfig
175
- docs?: PikkuDocs
176
- session?: undefined
169
+ errors?: string[]
177
170
  tags?: string[]
178
171
  middleware?: PikkuFunctionConfig['middleware']
179
172
  }
180
173
 
181
174
  /**
182
- * Represents a queue interaction object for middleware
175
+ * Represents a queue wire object for middleware
183
176
  * Provides information and actions for the current queue job execution
184
177
  */
185
178
  export interface PikkuQueue {
@@ -1,2 +1,2 @@
1
- export { initialize, PikkuRPCService, rpcService } from './rpc-runner.js'
1
+ export { PikkuRPCService, rpcService } from './rpc-runner.js'
2
2
  export type { PikkuRPC, RPCMeta } from './rpc-types.js'
@@ -1,20 +1,38 @@
1
- import {
2
- CoreServices,
3
- PikkuInteraction,
4
- PikkuWiringTypes,
5
- } from '../../types/core.types.js'
1
+ import { CoreServices, PikkuWire } from '../../types/core.types.js'
6
2
  import { runPikkuFunc } from '../../function/function-runner.js'
7
3
  import { pikkuState } from '../../pikku-state.js'
8
4
  import { ForbiddenError } from '../../errors/errors.js'
9
- import { PikkuRPC } from './rpc-types.js'
5
+ import { PikkuRPC, ResolvedFunction } from './rpc-types.js'
10
6
 
11
- // Type for the RPC service configuration
12
- type RPCServiceConfig = {
13
- coerceDataFromSchema: boolean
7
+ /**
8
+ * Resolve a namespaced function reference to package and function names
9
+ * Uses pikkuState to look up the namespace -> package mapping
10
+ */
11
+ const resolveNamespace = (
12
+ namespacedFunction: string
13
+ ): ResolvedFunction | null => {
14
+ const colonIndex = namespacedFunction.indexOf(':')
15
+ if (colonIndex === -1) {
16
+ return null
17
+ }
18
+
19
+ const namespace = namespacedFunction.substring(0, colonIndex)
20
+ const functionName = namespacedFunction.substring(colonIndex + 1)
21
+
22
+ const externalPackages = pikkuState(null, 'rpc', 'externalPackages')
23
+ const packageName = externalPackages.get(namespace)
24
+ if (!packageName) {
25
+ return null
26
+ }
27
+
28
+ return {
29
+ package: packageName,
30
+ function: functionName,
31
+ }
14
32
  }
15
33
 
16
34
  const getPikkuFunctionName = (rpcName: string): string => {
17
- const rpc = pikkuState('rpc', 'meta')
35
+ const rpc = pikkuState(null, 'rpc', 'meta')
18
36
  const rpcMeta = rpc[rpcName]
19
37
  if (!rpcMeta) {
20
38
  throw new Error(`RPC function not found: ${rpcName}`)
@@ -26,15 +44,14 @@ const getPikkuFunctionName = (rpcName: string): string => {
26
44
  export class ContextAwareRPCService {
27
45
  constructor(
28
46
  private services: CoreServices,
29
- private interaction: PikkuInteraction,
47
+ private wire: PikkuWire,
30
48
  private options: {
31
- coerceDataFromSchema?: boolean
32
49
  requiresAuth?: boolean
33
50
  }
34
51
  ) {}
35
52
 
36
53
  public async rpcExposed(funcName: string, data: any): Promise<any> {
37
- const functionMeta = pikkuState('function', 'meta')[funcName]
54
+ const functionMeta = pikkuState(null, 'function', 'meta')[funcName]
38
55
  if (!functionMeta) {
39
56
  throw new Error(`Function not found: ${funcName}`)
40
57
  }
@@ -48,66 +65,118 @@ export class ContextAwareRPCService {
48
65
  funcName: string,
49
66
  data: In
50
67
  ): Promise<Out> {
51
- const rpcDepth = this.services.rpc?.depth || 0
68
+ const rpcDepth = this.wire.rpc?.depth || 0
69
+ const updatedWire: PikkuWire = {
70
+ ...this.wire,
71
+ rpc: this.wire.rpc
72
+ ? {
73
+ ...this.wire.rpc,
74
+ depth: rpcDepth + 1,
75
+ global: false,
76
+ }
77
+ : undefined,
78
+ }
79
+
80
+ // Check if it's a namespaced function call (e.g., 'stripe:createCharge')
81
+ if (funcName.includes(':')) {
82
+ return this.invokeExternalPackageFunction<In, Out>(
83
+ funcName,
84
+ data,
85
+ updatedWire
86
+ )
87
+ }
88
+
89
+ // Main package function
52
90
  return runPikkuFunc<In, Out>(
53
- PikkuWiringTypes.rpc,
91
+ 'rpc',
54
92
  funcName,
55
93
  getPikkuFunctionName(funcName),
56
94
  {
57
95
  auth: this.options.requiresAuth,
96
+ // TODO: this is a hack since services have already been created
97
+ // but is valid since we don't want to keep creating new wire services
58
98
  singletonServices: this.services,
59
- getAllServices: () => {
60
- this.services.rpc = this.services.rpc
61
- ? ({
62
- ...this.services.rpc,
63
- depth: rpcDepth + 1,
64
- global: false,
65
- } as any)
66
- : undefined
67
- return this.services
68
- },
69
99
  data: () => data,
70
- userSession: this.services.userSession,
71
- coerceDataFromSchema: this.options.coerceDataFromSchema,
72
- interaction: this.interaction,
100
+ wire: updatedWire,
73
101
  }
74
102
  )
75
103
  }
76
104
 
77
- public async rpcWithInteraction<In = any, Out = any>(
78
- funcName: string,
105
+ /**
106
+ * Invoke a function from an external package
107
+ * External packages register their functions in pikkuState under their package name.
108
+ * The function is executed using the parent services (shared singleton services).
109
+ * @private
110
+ */
111
+ private async invokeExternalPackageFunction<In = any, Out = any>(
112
+ namespacedFunction: string,
113
+ data: In,
114
+ wire: PikkuWire
115
+ ): Promise<Out> {
116
+ // Resolve namespace to package name
117
+ const resolved = resolveNamespace(namespacedFunction)
118
+ if (!resolved) {
119
+ throw new Error(
120
+ `Unknown namespace in function reference: ${namespacedFunction}. ` +
121
+ `Make sure the package is registered in externalPackages config.`
122
+ )
123
+ }
124
+
125
+ // Get the function meta from the external package
126
+ // External packages use function meta, not RPC meta
127
+ const externalFunctionMeta = pikkuState(
128
+ resolved.package,
129
+ 'function',
130
+ 'meta'
131
+ )
132
+ const funcMeta = externalFunctionMeta[resolved.function]
133
+ if (!funcMeta) {
134
+ throw new Error(
135
+ `Function '${resolved.function}' not found in package '${resolved.package}'. ` +
136
+ `Available functions: ${Object.keys(externalFunctionMeta).join(', ') || '(none)'}`
137
+ )
138
+ }
139
+ const funcName = funcMeta.pikkuFuncName || resolved.function
140
+
141
+ // Execute the function using runPikkuFunc with the external package's state
142
+ // We use the parent services (this.services) since external packages share services
143
+ // Pass the function's tags so tag-based middleware/permissions are applied
144
+ return runPikkuFunc<In, Out>('rpc', namespacedFunction, funcName, {
145
+ auth: this.options.requiresAuth,
146
+ singletonServices: this.services,
147
+ data: () => data,
148
+ wire,
149
+ packageName: resolved.package,
150
+ tags: funcMeta.tags,
151
+ })
152
+ }
153
+
154
+ public async rpcWithWire<In = any, Out = any>(
155
+ rpcName: string,
79
156
  data: In,
80
- interaction: PikkuInteraction
157
+ wire: PikkuWire
81
158
  ): Promise<Out> {
82
- const rpcDepth = this.services.rpc?.depth || 0
83
- const mergedInteraction = {
84
- ...this.interaction,
85
- ...interaction,
159
+ const rpcDepth = this.wire.rpc?.depth || 0
160
+ const mergedWire: PikkuWire = {
161
+ ...this.wire,
162
+ ...wire,
163
+ rpc: this.wire.rpc
164
+ ? {
165
+ ...this.wire.rpc,
166
+ depth: rpcDepth + 1,
167
+ global: false,
168
+ }
169
+ : undefined,
86
170
  }
87
171
  return runPikkuFunc<In, Out>(
88
- PikkuWiringTypes.rpc,
89
- funcName,
90
- getPikkuFunctionName(funcName),
172
+ 'rpc',
173
+ rpcName,
174
+ getPikkuFunctionName(rpcName),
91
175
  {
92
176
  auth: this.options.requiresAuth,
93
177
  singletonServices: this.services,
94
- getAllServices: () => {
95
- this.services.rpc = this.services.rpc
96
- ? ({
97
- ...this.services.rpc,
98
- depth: rpcDepth + 1,
99
- global: false,
100
- } as any)
101
- : undefined
102
- return {
103
- ...this.services,
104
- ...mergedInteraction,
105
- }
106
- },
107
178
  data: () => data,
108
- userSession: this.services.userSession,
109
- coerceDataFromSchema: this.options.coerceDataFromSchema,
110
- interaction: mergedInteraction,
179
+ wire: mergedWire,
111
180
  }
112
181
  )
113
182
  }
@@ -132,43 +201,26 @@ export class PikkuRPCService<
132
201
  Services extends CoreServices,
133
202
  TypedRPC = PikkuRPC,
134
203
  > {
135
- private config?: RPCServiceConfig
136
-
137
- // Initialize the RPC service with configuration
138
- initialize(config: RPCServiceConfig) {
139
- this.config = config
140
- }
141
-
142
204
  // Convenience function for initializing
143
- injectRPCService(
205
+ getContextRPCService(
144
206
  services: Services,
145
- interaction: PikkuInteraction,
207
+ wire: PikkuWire,
146
208
  requiresAuth?: boolean | undefined,
147
209
  depth: number = 0
148
- ): Services & { rpc: TypedRPC } {
149
- const serviceCopy = {
150
- ...services,
151
- }
152
- const serviceRPC = new ContextAwareRPCService(serviceCopy, interaction, {
153
- coerceDataFromSchema: this.config?.coerceDataFromSchema,
210
+ ): TypedRPC {
211
+ const serviceRPC = new ContextAwareRPCService(services, wire, {
154
212
  requiresAuth,
155
213
  })
156
- serviceCopy.rpc = {
214
+ return {
157
215
  depth,
158
216
  global: false,
159
217
  invoke: serviceRPC.rpc.bind(serviceRPC),
160
218
  invokeExposed: serviceRPC.rpc.bind(serviceRPC),
161
219
  startWorkflow: serviceRPC.startWorkflow.bind(serviceRPC),
162
- rpcWithInteraction: serviceRPC.rpcWithInteraction.bind(serviceRPC),
220
+ rpcWithWire: serviceRPC.rpcWithWire.bind(serviceRPC),
163
221
  } as any
164
- return serviceCopy as Services & { rpc: TypedRPC }
165
222
  }
166
223
  }
167
224
 
168
225
  // Create a singleton instance
169
226
  export const rpcService = new PikkuRPCService()
170
-
171
- // Convenience function for initializing
172
- export const initialize = (config: RPCServiceConfig) => {
173
- rpcService.initialize(config)
174
- }
@@ -17,3 +17,11 @@ export interface RPCHandler<Input, Output> {
17
17
  input: Input
18
18
  output: Output
19
19
  }
20
+
21
+ /**
22
+ * Resolved function reference from namespace
23
+ */
24
+ export interface ResolvedFunction {
25
+ package: string
26
+ function: string
27
+ }
@@ -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 logSchedulers = (logger: Logger) => {
9
- const scheduledTasks = pikkuState('scheduler', 'tasks')
9
+ const scheduledTasks = pikkuState(null, 'scheduler', 'tasks')
10
10
  if (scheduledTasks.size === 0) {
11
11
  logger.info('No scheduled tasks added')
12
12
  return