@pikku/core 0.11.2 → 0.12.0

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 (344) hide show
  1. package/CHANGELOG.md +33 -2
  2. package/dist/crypto-utils.d.ts +2 -0
  3. package/dist/crypto-utils.js +78 -0
  4. package/dist/errors/errors.d.ts +8 -0
  5. package/dist/errors/errors.js +16 -0
  6. package/dist/errors/index.d.ts +0 -1
  7. package/dist/errors/index.js +0 -1
  8. package/dist/function/function-runner.d.ts +7 -1
  9. package/dist/function/function-runner.js +82 -23
  10. package/dist/function/functions.types.d.ts +31 -87
  11. package/dist/function/functions.types.js +16 -46
  12. package/dist/function/index.d.ts +2 -2
  13. package/dist/function/index.js +1 -2
  14. package/dist/handle-error.js +1 -10
  15. package/dist/index.d.ts +28 -26
  16. package/dist/index.js +18 -29
  17. package/dist/middleware/auth-apikey.d.ts +2 -2
  18. package/dist/middleware/auth-apikey.js +3 -3
  19. package/dist/middleware/auth-bearer.d.ts +2 -2
  20. package/dist/middleware/auth-bearer.js +3 -6
  21. package/dist/middleware/auth-cookie.d.ts +2 -2
  22. package/dist/middleware/auth-cookie.js +6 -8
  23. package/dist/middleware/cors.d.ts +46 -0
  24. package/dist/middleware/cors.js +73 -0
  25. package/dist/middleware/index.d.ts +5 -3
  26. package/dist/middleware/index.js +5 -3
  27. package/dist/middleware/remote-auth.d.ts +5 -0
  28. package/dist/middleware/remote-auth.js +55 -0
  29. package/dist/middleware/timeout.d.ts +2 -2
  30. package/dist/middleware-runner.js +8 -10
  31. package/dist/permissions.js +11 -15
  32. package/dist/pikku-state.d.ts +1 -0
  33. package/dist/pikku-state.js +18 -8
  34. package/dist/schema.js +12 -11
  35. package/dist/services/ai-agent-runner-service.d.ts +24 -0
  36. package/dist/services/ai-agent-runner-service.js +1 -0
  37. package/dist/services/ai-run-state-service.d.ts +13 -0
  38. package/dist/services/ai-run-state-service.js +1 -0
  39. package/dist/services/ai-storage-service.d.ts +18 -0
  40. package/dist/services/ai-storage-service.js +1 -0
  41. package/dist/services/deployment-service.d.ts +19 -0
  42. package/dist/services/deployment-service.js +1 -0
  43. package/dist/services/gopass-secrets.d.ts +47 -0
  44. package/dist/services/gopass-secrets.js +94 -0
  45. package/dist/services/in-memory-trigger-service.d.ts +23 -0
  46. package/dist/services/in-memory-trigger-service.js +50 -0
  47. package/dist/services/in-memory-workflow-service.d.ts +59 -0
  48. package/dist/services/in-memory-workflow-service.js +287 -0
  49. package/dist/services/index.d.ts +25 -11
  50. package/dist/services/index.js +10 -13
  51. package/dist/services/local-secrets.d.ts +23 -0
  52. package/dist/services/local-secrets.js +45 -0
  53. package/dist/services/local-variables.d.ts +5 -0
  54. package/dist/services/local-variables.js +18 -0
  55. package/dist/services/scheduler-service.d.ts +21 -1
  56. package/dist/services/scheduler-service.js +14 -0
  57. package/dist/services/schema-service.d.ts +6 -0
  58. package/dist/services/scoped-secret-service.d.ts +16 -0
  59. package/dist/services/scoped-secret-service.js +35 -0
  60. package/dist/services/secret-service.d.ts +25 -4
  61. package/dist/services/trigger-service.d.ts +23 -0
  62. package/dist/services/trigger-service.js +1 -0
  63. package/dist/services/typed-secret-service.d.ts +30 -0
  64. package/dist/services/typed-secret-service.js +40 -0
  65. package/dist/services/typed-variables-service.d.ts +27 -0
  66. package/dist/services/typed-variables-service.js +46 -0
  67. package/dist/services/user-session-service.d.ts +13 -0
  68. package/dist/services/user-session-service.js +17 -0
  69. package/dist/services/variables-service.d.ts +5 -0
  70. package/dist/services/workflow-service.d.ts +9 -4
  71. package/dist/types/core.types.d.ts +48 -12
  72. package/dist/types/core.types.js +8 -1
  73. package/dist/types/state.types.d.ts +43 -51
  74. package/dist/utils.d.ts +3 -2
  75. package/dist/utils.js +15 -3
  76. package/dist/version.d.ts +6 -0
  77. package/dist/version.js +19 -0
  78. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +29 -0
  79. package/dist/wirings/ai-agent/ai-agent-memory.js +199 -0
  80. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +9 -0
  81. package/dist/wirings/ai-agent/ai-agent-model-config.js +36 -0
  82. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +60 -0
  83. package/dist/wirings/ai-agent/ai-agent-prepare.js +312 -0
  84. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +15 -0
  85. package/dist/wirings/ai-agent/ai-agent-registry.js +47 -0
  86. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +3 -0
  87. package/dist/wirings/ai-agent/ai-agent-runner.js +96 -0
  88. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +11 -0
  89. package/dist/wirings/ai-agent/ai-agent-stream.js +503 -0
  90. package/dist/wirings/ai-agent/ai-agent.types.d.ts +254 -0
  91. package/dist/wirings/ai-agent/ai-agent.types.js +1 -0
  92. package/dist/wirings/ai-agent/index.d.ts +5 -0
  93. package/dist/wirings/ai-agent/index.js +4 -0
  94. package/dist/wirings/channel/channel-common.d.ts +7 -4
  95. package/dist/wirings/channel/channel-common.js +15 -8
  96. package/dist/wirings/channel/channel-handler.js +12 -3
  97. package/dist/wirings/channel/channel-middleware-runner.d.ts +9 -0
  98. package/dist/wirings/channel/channel-middleware-runner.js +73 -0
  99. package/dist/wirings/channel/channel-runner.js +7 -7
  100. package/dist/wirings/channel/channel.types.d.ts +5 -1
  101. package/dist/wirings/channel/define-channel-routes.d.ts +21 -0
  102. package/dist/wirings/channel/define-channel-routes.js +23 -0
  103. package/dist/wirings/channel/index.d.ts +10 -8
  104. package/dist/wirings/channel/index.js +7 -8
  105. package/dist/wirings/channel/local/index.d.ts +3 -3
  106. package/dist/wirings/channel/local/index.js +3 -3
  107. package/dist/wirings/channel/local/local-channel-runner.js +18 -6
  108. package/dist/wirings/channel/serverless/index.d.ts +1 -1
  109. package/dist/wirings/channel/serverless/index.js +1 -1
  110. package/dist/wirings/channel/serverless/serverless-channel-runner.js +15 -4
  111. package/dist/wirings/cli/channel/index.d.ts +1 -1
  112. package/dist/wirings/cli/channel/index.js +1 -1
  113. package/dist/wirings/cli/cli-runner.d.ts +1 -1
  114. package/dist/wirings/cli/cli-runner.js +12 -8
  115. package/dist/wirings/cli/cli.types.d.ts +6 -6
  116. package/dist/wirings/cli/define-cli-commands.d.ts +19 -0
  117. package/dist/wirings/cli/define-cli-commands.js +20 -0
  118. package/dist/wirings/cli/index.d.ts +2 -3
  119. package/dist/wirings/cli/index.js +1 -3
  120. package/dist/wirings/http/http-routes.d.ts +69 -0
  121. package/dist/wirings/http/http-routes.js +139 -0
  122. package/dist/wirings/http/http-runner.js +49 -23
  123. package/dist/wirings/http/http.types.d.ts +78 -38
  124. package/dist/wirings/http/index.d.ts +5 -4
  125. package/dist/wirings/http/index.js +4 -3
  126. package/dist/wirings/mcp/index.d.ts +4 -3
  127. package/dist/wirings/mcp/index.js +3 -3
  128. package/dist/wirings/mcp/mcp-runner.d.ts +1 -3
  129. package/dist/wirings/mcp/mcp-runner.js +25 -39
  130. package/dist/wirings/mcp/mcp.types.d.ts +3 -3
  131. package/dist/wirings/node/index.d.ts +2 -0
  132. package/dist/wirings/node/index.js +1 -0
  133. package/dist/wirings/node/node.types.d.ts +20 -0
  134. package/dist/wirings/node/node.types.js +1 -0
  135. package/dist/wirings/oauth2/index.d.ts +3 -0
  136. package/dist/wirings/oauth2/index.js +2 -0
  137. package/dist/wirings/oauth2/oauth2-client.d.ts +47 -0
  138. package/dist/wirings/oauth2/oauth2-client.js +267 -0
  139. package/dist/wirings/oauth2/oauth2.types.d.ts +65 -0
  140. package/dist/wirings/oauth2/oauth2.types.js +4 -0
  141. package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +20 -0
  142. package/dist/wirings/oauth2/wire-oauth2-credential.js +21 -0
  143. package/dist/wirings/queue/index.d.ts +2 -2
  144. package/dist/wirings/queue/index.js +1 -1
  145. package/dist/wirings/queue/queue-runner.d.ts +7 -0
  146. package/dist/wirings/queue/queue-runner.js +17 -6
  147. package/dist/wirings/queue/queue.types.d.ts +8 -2
  148. package/dist/wirings/rpc/index.d.ts +1 -1
  149. package/dist/wirings/rpc/index.js +1 -1
  150. package/dist/wirings/rpc/rpc-runner.d.ts +33 -5
  151. package/dist/wirings/rpc/rpc-runner.js +134 -16
  152. package/dist/wirings/rpc/rpc-types.d.ts +8 -4
  153. package/dist/wirings/scheduler/index.d.ts +3 -3
  154. package/dist/wirings/scheduler/index.js +2 -3
  155. package/dist/wirings/scheduler/scheduler-runner.d.ts +5 -0
  156. package/dist/wirings/scheduler/scheduler-runner.js +23 -5
  157. package/dist/wirings/secret/index.d.ts +3 -0
  158. package/dist/wirings/secret/index.js +2 -0
  159. package/dist/wirings/secret/secret.types.d.ts +27 -0
  160. package/dist/wirings/secret/secret.types.js +1 -0
  161. package/dist/wirings/secret/validate-secret-definitions.d.ts +6 -0
  162. package/dist/wirings/secret/validate-secret-definitions.js +55 -0
  163. package/dist/wirings/trigger/index.d.ts +3 -2
  164. package/dist/wirings/trigger/index.js +2 -2
  165. package/dist/wirings/trigger/pikku-trigger-service.d.ts +26 -0
  166. package/dist/wirings/trigger/pikku-trigger-service.js +75 -0
  167. package/dist/wirings/trigger/trigger-runner.d.ts +21 -8
  168. package/dist/wirings/trigger/trigger-runner.js +46 -18
  169. package/dist/wirings/trigger/trigger.types.d.ts +99 -11
  170. package/dist/wirings/trigger/trigger.types.js +40 -1
  171. package/dist/wirings/variable/index.d.ts +3 -0
  172. package/dist/wirings/variable/index.js +2 -0
  173. package/dist/wirings/variable/validate-variable-definitions.d.ts +6 -0
  174. package/dist/wirings/variable/validate-variable-definitions.js +45 -0
  175. package/dist/wirings/variable/variable.types.d.ts +18 -0
  176. package/dist/wirings/variable/variable.types.js +1 -0
  177. package/dist/wirings/workflow/dsl/index.d.ts +1 -1
  178. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +7 -1
  179. package/dist/wirings/workflow/dsl/workflow-runner.js +3 -2
  180. package/dist/wirings/workflow/graph/graph-node.d.ts +1 -6
  181. package/dist/wirings/workflow/graph/graph-runner.d.ts +5 -31
  182. package/dist/wirings/workflow/graph/graph-runner.js +384 -296
  183. package/dist/wirings/workflow/graph/index.d.ts +4 -3
  184. package/dist/wirings/workflow/graph/index.js +3 -3
  185. package/dist/wirings/workflow/graph/template.d.ts +15 -0
  186. package/dist/wirings/workflow/graph/template.js +27 -0
  187. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +15 -0
  188. package/dist/wirings/workflow/graph/wire-workflow-graph.js +8 -0
  189. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -13
  190. package/dist/wirings/workflow/index.d.ts +6 -6
  191. package/dist/wirings/workflow/index.js +6 -4
  192. package/dist/wirings/workflow/pikku-workflow-service.d.ts +28 -14
  193. package/dist/wirings/workflow/pikku-workflow-service.js +200 -56
  194. package/dist/wirings/workflow/workflow-helpers.d.ts +36 -0
  195. package/dist/wirings/workflow/workflow-helpers.js +38 -0
  196. package/dist/wirings/workflow/workflow-utils.d.ts +1 -23
  197. package/dist/wirings/workflow/workflow-utils.js +1 -66
  198. package/dist/wirings/workflow/workflow.types.d.ts +40 -93
  199. package/package.json +13 -15
  200. package/run-tests.sh +4 -1
  201. package/src/crypto-utils.ts +99 -0
  202. package/src/errors/errors.ts +17 -0
  203. package/src/errors/index.ts +0 -1
  204. package/src/factory-functions.test.ts +42 -2
  205. package/src/function/function-runner.test.ts +4 -11
  206. package/src/function/function-runner.ts +114 -29
  207. package/src/function/functions.types.ts +62 -132
  208. package/src/function/index.ts +5 -2
  209. package/src/handle-error.ts +2 -10
  210. package/src/index.ts +99 -25
  211. package/src/middleware/auth-apikey.test.ts +15 -12
  212. package/src/middleware/auth-apikey.ts +3 -3
  213. package/src/middleware/auth-bearer.test.ts +17 -14
  214. package/src/middleware/auth-bearer.ts +25 -27
  215. package/src/middleware/auth-cookie.test.ts +16 -13
  216. package/src/middleware/auth-cookie.ts +6 -8
  217. package/src/middleware/cors.ts +96 -0
  218. package/src/middleware/index.ts +5 -3
  219. package/src/middleware/remote-auth.ts +68 -0
  220. package/src/middleware-runner.test.ts +122 -0
  221. package/src/middleware-runner.ts +12 -12
  222. package/src/permissions.test.ts +81 -7
  223. package/src/permissions.ts +15 -17
  224. package/src/pikku-state.ts +20 -8
  225. package/src/run-tests-script.test.ts +49 -0
  226. package/src/schema.ts +18 -15
  227. package/src/services/ai-agent-runner-service.ts +29 -0
  228. package/src/services/ai-run-state-service.ts +20 -0
  229. package/src/services/ai-storage-service.ts +39 -0
  230. package/src/services/deployment-service.ts +22 -0
  231. package/src/services/gopass-secrets.ts +95 -0
  232. package/src/services/in-memory-trigger-service.ts +68 -0
  233. package/src/services/in-memory-workflow-service.ts +395 -0
  234. package/src/services/index.ts +49 -14
  235. package/src/services/local-secrets.ts +51 -0
  236. package/src/services/local-variables.ts +22 -0
  237. package/src/services/scheduler-service.ts +29 -1
  238. package/src/services/schema-service.ts +7 -0
  239. package/src/services/scoped-secret-service.ts +41 -0
  240. package/src/services/secret-service.ts +25 -4
  241. package/src/services/trigger-service.ts +38 -0
  242. package/src/services/typed-secret-service.ts +70 -0
  243. package/src/services/typed-variables-service.ts +81 -0
  244. package/src/services/user-session-service.ts +23 -0
  245. package/src/services/variables-service.ts +5 -0
  246. package/src/services/workflow-service.ts +22 -2
  247. package/src/types/core.types.ts +76 -11
  248. package/src/types/state.types.ts +37 -63
  249. package/src/utils.ts +20 -6
  250. package/src/version.test.ts +80 -0
  251. package/src/version.ts +25 -0
  252. package/src/wirings/ai-agent/ai-agent-memory.ts +300 -0
  253. package/src/wirings/ai-agent/ai-agent-model-config.ts +43 -0
  254. package/src/wirings/ai-agent/ai-agent-prepare.ts +470 -0
  255. package/src/wirings/ai-agent/ai-agent-registry.test.ts +37 -0
  256. package/src/wirings/ai-agent/ai-agent-registry.ts +82 -0
  257. package/src/wirings/ai-agent/ai-agent-runner.test.ts +75 -0
  258. package/src/wirings/ai-agent/ai-agent-runner.ts +137 -0
  259. package/src/wirings/ai-agent/ai-agent-stream.test.ts +246 -0
  260. package/src/wirings/ai-agent/ai-agent-stream.ts +774 -0
  261. package/src/wirings/ai-agent/ai-agent.types.ts +273 -0
  262. package/src/wirings/ai-agent/index.ts +28 -0
  263. package/src/wirings/channel/channel-common.ts +32 -19
  264. package/src/wirings/channel/channel-handler.ts +17 -4
  265. package/src/wirings/channel/channel-middleware-runner.ts +119 -0
  266. package/src/wirings/channel/channel-runner.ts +9 -10
  267. package/src/wirings/channel/channel.types.ts +17 -1
  268. package/src/wirings/channel/define-channel-routes.ts +25 -0
  269. package/src/wirings/channel/index.ts +23 -8
  270. package/src/wirings/channel/local/index.ts +3 -3
  271. package/src/wirings/channel/local/local-channel-runner.test.ts +44 -1
  272. package/src/wirings/channel/local/local-channel-runner.ts +22 -6
  273. package/src/wirings/channel/serverless/index.ts +5 -1
  274. package/src/wirings/channel/serverless/serverless-channel-runner.ts +20 -4
  275. package/src/wirings/cli/channel/index.ts +1 -1
  276. package/src/wirings/cli/cli-runner.test.ts +9 -9
  277. package/src/wirings/cli/cli-runner.ts +17 -10
  278. package/src/wirings/cli/cli.types.ts +11 -11
  279. package/src/wirings/cli/command-parser.test.ts +8 -8
  280. package/src/wirings/cli/define-cli-commands.ts +24 -0
  281. package/src/wirings/cli/index.ts +10 -4
  282. package/src/wirings/http/http-routes.test.ts +322 -0
  283. package/src/wirings/http/http-routes.ts +198 -0
  284. package/src/wirings/http/http-runner.test.ts +3 -3
  285. package/src/wirings/http/http-runner.ts +63 -29
  286. package/src/wirings/http/http.types.ts +121 -37
  287. package/src/wirings/http/index.ts +16 -4
  288. package/src/wirings/mcp/index.ts +27 -3
  289. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +3 -3
  290. package/src/wirings/mcp/mcp-runner.ts +39 -50
  291. package/src/wirings/mcp/mcp.types.ts +3 -3
  292. package/src/wirings/node/index.ts +2 -0
  293. package/src/wirings/node/node.types.ts +23 -0
  294. package/src/wirings/oauth2/index.ts +3 -0
  295. package/src/wirings/oauth2/oauth2-client.test.ts +929 -0
  296. package/src/wirings/oauth2/oauth2-client.ts +335 -0
  297. package/src/wirings/oauth2/oauth2.types.ts +69 -0
  298. package/src/wirings/oauth2/wire-oauth2-credential.ts +23 -0
  299. package/src/wirings/queue/index.ts +14 -2
  300. package/src/wirings/queue/queue-runner.test.ts +97 -55
  301. package/src/wirings/queue/queue-runner.ts +33 -7
  302. package/src/wirings/queue/queue.types.ts +12 -2
  303. package/src/wirings/rpc/index.ts +1 -1
  304. package/src/wirings/rpc/rpc-runner.ts +187 -17
  305. package/src/wirings/rpc/rpc-types.ts +13 -4
  306. package/src/wirings/scheduler/index.ts +7 -4
  307. package/src/wirings/scheduler/scheduler-runner.test.ts +70 -26
  308. package/src/wirings/scheduler/scheduler-runner.ts +45 -5
  309. package/src/wirings/secret/index.ts +9 -0
  310. package/src/wirings/secret/secret.types.ts +32 -0
  311. package/src/wirings/secret/validate-secret-definitions.ts +82 -0
  312. package/src/wirings/trigger/index.ts +10 -2
  313. package/src/wirings/trigger/pikku-trigger-service.ts +134 -0
  314. package/src/wirings/trigger/trigger-runner.ts +80 -38
  315. package/src/wirings/trigger/trigger.types.ts +144 -22
  316. package/src/wirings/variable/index.ts +8 -0
  317. package/src/wirings/variable/validate-variable-definitions.ts +69 -0
  318. package/src/wirings/variable/variable.types.ts +22 -0
  319. package/src/wirings/workflow/dsl/index.ts +1 -0
  320. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +9 -1
  321. package/src/wirings/workflow/dsl/workflow-runner.ts +4 -3
  322. package/src/wirings/workflow/graph/graph-node.ts +1 -6
  323. package/src/wirings/workflow/graph/graph-runner.test.ts +495 -0
  324. package/src/wirings/workflow/graph/graph-runner.ts +496 -374
  325. package/src/wirings/workflow/graph/index.ts +14 -3
  326. package/src/wirings/workflow/graph/template.ts +42 -0
  327. package/src/wirings/workflow/graph/wire-workflow-graph.ts +29 -0
  328. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -22
  329. package/src/wirings/workflow/index.ts +21 -10
  330. package/src/wirings/workflow/pikku-workflow-service.test.ts +212 -0
  331. package/src/wirings/workflow/pikku-workflow-service.ts +285 -66
  332. package/src/wirings/workflow/workflow-helpers.ts +79 -0
  333. package/src/wirings/workflow/workflow-utils.ts +0 -120
  334. package/src/wirings/workflow/workflow.types.ts +45 -90
  335. package/tsconfig.tsbuildinfo +1 -1
  336. package/dist/wirings/forge-node/forge-node.types.d.ts +0 -120
  337. package/dist/wirings/forge-node/forge-node.types.js +0 -38
  338. package/dist/wirings/forge-node/index.d.ts +0 -1
  339. package/dist/wirings/forge-node/index.js +0 -1
  340. package/dist/wirings/workflow/wire-workflow.d.ts +0 -42
  341. package/dist/wirings/workflow/wire-workflow.js +0 -53
  342. package/src/wirings/forge-node/forge-node.types.ts +0 -135
  343. package/src/wirings/forge-node/index.ts +0 -1
  344. package/src/wirings/workflow/wire-workflow.ts +0 -94
package/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## 0.12.0
2
+
3
+ ### New Features
4
+
5
+ - AI agents with `pikkuAIAgent()` — define agents with tools, sub-agents, memory, structured output, and streaming via SSE
6
+ - AI middleware hooks (`pikkuAIMiddleware`) for input, stream, and output transformation
7
+ - Tool approval flow — suspend agent execution pending human approval
8
+ - Channel middleware (`pikkuChannelMiddleware`) for intercepting and transforming channel events
9
+ - Remote RPC — call functions across servers with `rpc.remote()` and `DeploymentService`
10
+ - HTTP route groups with `wireHTTPRoutes` for shared basePath, tags, and auth
11
+ - Workflow graph engine with `createGraph()` type-safe builder
12
+ - Workflow HTTP helpers: `workflow()`, `workflowStart()`, `workflowStatus()`, `graphStart()`
13
+ - Workflow DSL with rich step types (branch, parallel, fanout, switch, filter)
14
+ - Trigger system with `wireTrigger()` and `wireTriggerSource()`
15
+ - OAuth2 support with `wireOAuth2Credential` and `OAuth2Client`
16
+ - Secret and variable declarations with `wireSecret()` and `wireVariable()`
17
+ - `TypedSecretService` and `TypedVariablesService` for compile-time validated access
18
+ - `defineCLICommands` and `defineChannelRoutes` for external composition
19
+ - Built-in CORS middleware
20
+ - `disabled: true` support on all wirings and functions
21
+ - `createWireServices` and `createConfig` are now optional
22
+ - `InMemoryWorkflowService` and `InMemoryTriggerService` for testing
23
+
24
+ ### Breaking Changes
25
+
26
+ - `PikkuInteraction` → `PikkuWire`, `CreateSessionServices` → `CreateWireServices`
27
+ - `wireForgeCredential` → `wireCredential`
28
+ - `startWorkflowByWire` → `startWorkflowByHTTPWire`
29
+ - Renamed all `forge` → `node` naming
30
+ - Renamed `credential` → `secret` across core types
31
+ - `WorkflowService.createRun` signature changed (new `inline`, `graphHash` params)
32
+ - Auth enforced by default for `pikkuFunc`
33
+
1
34
  ## 0.11.0
2
35
 
3
36
  ## 0.11.2
@@ -6,8 +39,6 @@
6
39
 
7
40
  - db9c7bf: Add workflow graph system with type-safe builder
8
41
 
9
- ## 0.11.2
10
-
11
42
  ### Features
12
43
 
13
44
  - f35e89da: Add workflow graph system with type-safe builder
@@ -0,0 +1,2 @@
1
+ export declare const encryptJSON: (secret: string, value: unknown) => Promise<string>;
2
+ export declare const decryptJSON: <T>(secret: string, token: string) => Promise<T>;
@@ -0,0 +1,78 @@
1
+ const encoder = new TextEncoder();
2
+ const decoder = new TextDecoder();
3
+ const getSubtle = () => {
4
+ const crypto = globalThis.crypto;
5
+ if (!crypto?.subtle) {
6
+ throw new Error('WebCrypto not available');
7
+ }
8
+ return crypto.subtle;
9
+ };
10
+ const base64Encode = (bytes) => {
11
+ if (typeof Buffer !== 'undefined') {
12
+ return Buffer.from(bytes).toString('base64');
13
+ }
14
+ let binary = '';
15
+ for (let i = 0; i < bytes.length; i++) {
16
+ binary += String.fromCharCode(bytes[i]);
17
+ }
18
+ return btoa(binary);
19
+ };
20
+ const base64Decode = (input) => {
21
+ if (typeof Buffer !== 'undefined') {
22
+ return new Uint8Array(Buffer.from(input, 'base64'));
23
+ }
24
+ const binary = atob(input);
25
+ const bytes = new Uint8Array(binary.length);
26
+ for (let i = 0; i < binary.length; i++) {
27
+ bytes[i] = binary.charCodeAt(i);
28
+ }
29
+ return bytes;
30
+ };
31
+ const toBase64Url = (bytes) => {
32
+ return base64Encode(bytes)
33
+ .replace(/\+/g, '-')
34
+ .replace(/\//g, '_')
35
+ .replace(/=+$/g, '');
36
+ };
37
+ const fromBase64Url = (input) => {
38
+ let base64 = input.replace(/-/g, '+').replace(/_/g, '/');
39
+ while (base64.length % 4 !== 0)
40
+ base64 += '=';
41
+ return base64Decode(base64);
42
+ };
43
+ const deriveKey = async (secret) => {
44
+ const subtle = getSubtle();
45
+ const hash = await subtle.digest('SHA-256', encoder.encode(secret));
46
+ return subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, [
47
+ 'encrypt',
48
+ 'decrypt',
49
+ ]);
50
+ };
51
+ export const encryptJSON = async (secret, value) => {
52
+ const crypto = globalThis.crypto;
53
+ if (!crypto?.getRandomValues) {
54
+ throw new Error('WebCrypto not available');
55
+ }
56
+ const subtle = getSubtle();
57
+ const iv = crypto.getRandomValues(new Uint8Array(12));
58
+ const key = await deriveKey(secret);
59
+ const plaintext = encoder.encode(JSON.stringify(value));
60
+ const encrypted = await subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext);
61
+ const cipherBytes = new Uint8Array(encrypted);
62
+ const out = new Uint8Array(iv.length + cipherBytes.length);
63
+ out.set(iv, 0);
64
+ out.set(cipherBytes, iv.length);
65
+ return toBase64Url(out);
66
+ };
67
+ export const decryptJSON = async (secret, token) => {
68
+ const subtle = getSubtle();
69
+ const data = fromBase64Url(token);
70
+ if (data.length < 13) {
71
+ throw new Error('Invalid encrypted payload');
72
+ }
73
+ const iv = data.slice(0, 12);
74
+ const ciphertext = data.slice(12);
75
+ const key = await deriveKey(secret);
76
+ const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
77
+ return JSON.parse(decoder.decode(new Uint8Array(decrypted)));
78
+ };
@@ -4,6 +4,8 @@
4
4
  import { PikkuError } from './error-handler.js';
5
5
  export declare class InvalidMiddlewareWireError extends PikkuError {
6
6
  }
7
+ export declare class PikkuMissingMetaError extends PikkuError {
8
+ }
7
9
  /**
8
10
  * The server cannot or will not process the request due to client error (e.g., malformed request syntax).
9
11
  * @group Error
@@ -190,3 +192,9 @@ export declare class HTTPVersionNotSupportedError extends PikkuError {
190
192
  */
191
193
  export declare class MaxComputeTimeReachedError extends PikkuError {
192
194
  }
195
+ /**
196
+ * A required schema was not found during validation.
197
+ * @group Error
198
+ */
199
+ export declare class MissingSchemaError extends PikkuError {
200
+ }
@@ -8,6 +8,12 @@ addError(InvalidMiddlewareWireError, {
8
8
  status: 500,
9
9
  message: 'The middleware wire is invalid for the current wiring type.',
10
10
  });
11
+ export class PikkuMissingMetaError extends PikkuError {
12
+ }
13
+ addError(PikkuMissingMetaError, {
14
+ status: 500,
15
+ message: 'Required metadata is missing',
16
+ });
11
17
  /**
12
18
  * The server cannot or will not process the request due to client error (e.g., malformed request syntax).
13
19
  * @group Error
@@ -321,3 +327,13 @@ addError(MaxComputeTimeReachedError, {
321
327
  status: 524,
322
328
  message: 'The server took too long to complete the request, reaching the maximum compute time allowed.',
323
329
  });
330
+ /**
331
+ * A required schema was not found during validation.
332
+ * @group Error
333
+ */
334
+ export class MissingSchemaError extends PikkuError {
335
+ }
336
+ addError(MissingSchemaError, {
337
+ status: 500,
338
+ message: 'A required schema was not found. Ensure schema generation has been run.',
339
+ });
@@ -1,2 +1 @@
1
- export * from './error-handler.js';
2
1
  export * from './errors.js';
@@ -1,2 +1 @@
1
- export * from './error-handler.js';
2
1
  export * from './errors.js';
@@ -1,19 +1,25 @@
1
1
  import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes, PikkuWire, MiddlewareMetadata, PermissionMetadata, CoreSingletonServices, CreateWireServices } from '../types/core.types.js';
2
+ import type { CorePikkuChannelMiddleware } from '../wirings/channel/channel.types.js';
2
3
  import { CorePermissionGroup, CorePikkuFunctionConfig, CorePikkuPermission } from './functions.types.js';
3
4
  import { SessionService } from '../services/user-session-service.js';
4
5
  export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any>, packageName?: string | null) => void;
6
+ export declare const getFunctionNames: (packageName?: string | null) => string[];
7
+ export declare const getAllFunctionNames: () => string[];
5
8
  export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, wire: PikkuWire, data: In, userSession?: SessionService<CoreUserSession>, packageName?: string | null) => Promise<Out>;
6
- export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags, wire, packageName, }: {
9
+ export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedChannelMiddleware, wireChannelMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags, wire, sessionService, packageName, }: {
7
10
  singletonServices: CoreSingletonServices;
8
11
  createWireServices?: CreateWireServices;
9
12
  data: () => Promise<In> | In;
10
13
  auth?: boolean;
11
14
  inheritedMiddleware?: MiddlewareMetadata[];
12
15
  wireMiddleware?: CorePikkuMiddleware[];
16
+ inheritedChannelMiddleware?: MiddlewareMetadata[];
17
+ wireChannelMiddleware?: CorePikkuChannelMiddleware[];
13
18
  inheritedPermissions?: PermissionMetadata[];
14
19
  wirePermissions?: CorePermissionGroup | CorePikkuPermission[];
15
20
  coerceDataFromSchema?: boolean;
16
21
  tags?: string[];
17
22
  wire: PikkuWire;
23
+ sessionService?: SessionService<CoreUserSession>;
18
24
  packageName?: string | null;
19
25
  }) => Promise<Out>;
@@ -1,7 +1,10 @@
1
1
  import { runMiddleware, combineMiddleware } from '../middleware-runner.js';
2
+ import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../wirings/channel/channel-middleware-runner.js';
2
3
  import { runPermissions } from '../permissions.js';
3
4
  import { pikkuState } from '../pikku-state.js';
4
5
  import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js';
6
+ import { parseVersionedId } from '../version.js';
7
+ import { createFunctionSessionWireProps, } from '../services/user-session-service.js';
5
8
  import { ForbiddenError } from '../errors/errors.js';
6
9
  import { rpcService } from '../wirings/rpc/rpc-runner.js';
7
10
  import { closeWireServices } from '../utils.js';
@@ -39,25 +42,57 @@ const getOrCreatePackageSingletonServices = async (packageName, parentServices)
39
42
  export const addFunction = (funcName, funcConfig, packageName = null) => {
40
43
  pikkuState(packageName, 'function', 'functions').set(funcName, funcConfig);
41
44
  };
45
+ export const getFunctionNames = (packageName = null) => {
46
+ const functionsMeta = pikkuState(packageName, 'function', 'meta');
47
+ return Object.keys(functionsMeta);
48
+ };
49
+ export const getAllFunctionNames = () => {
50
+ const functions = [];
51
+ const mainFunctionsMeta = pikkuState(null, 'function', 'meta');
52
+ functions.push(...Object.keys(mainFunctionsMeta));
53
+ const externalPackages = pikkuState(null, 'rpc', 'externalPackages');
54
+ for (const [namespace, config] of externalPackages) {
55
+ const packageFunctionsMeta = pikkuState(config.package, 'function', 'meta');
56
+ for (const funcName of Object.keys(packageFunctionsMeta)) {
57
+ functions.push(`${namespace}:${funcName}`);
58
+ }
59
+ }
60
+ return functions;
61
+ };
42
62
  export const runPikkuFuncDirectly = async (funcName, allServices, wire, data, userSession, packageName = null) => {
43
63
  const funcConfig = pikkuState(packageName, 'function', 'functions').get(funcName);
44
64
  if (!funcConfig) {
45
65
  throw new Error(`Function not found: ${funcName}`);
46
66
  }
47
- // Inject session into wire
48
67
  const wireWithSession = {
49
68
  ...wire,
50
- session: userSession,
69
+ ...(userSession && createFunctionSessionWireProps(userSession)),
51
70
  };
52
71
  return (await funcConfig.func(allServices, data, wireWithSession));
53
72
  };
54
- export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], wire, packageName = null, }) => {
55
- const funcConfig = pikkuState(packageName, 'function', 'functions').get(funcName);
73
+ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedChannelMiddleware, wireChannelMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], wire, sessionService, packageName = null, }) => {
74
+ wire = {
75
+ ...wire,
76
+ wireType: wire.wireType ?? wireType,
77
+ wireId: wire.wireId ?? wireId,
78
+ };
79
+ const funcMap = pikkuState(packageName, 'function', 'functions');
80
+ let funcConfig = funcMap.get(funcName);
81
+ const allMeta = pikkuState(packageName, 'function', 'meta');
82
+ let funcMeta = allMeta[funcName];
83
+ if (!funcConfig || !funcMeta) {
84
+ const { baseName, version } = parseVersionedId(funcName);
85
+ if (version !== null) {
86
+ funcConfig = funcConfig || funcMap.get(baseName);
87
+ funcMeta = funcMeta || allMeta[baseName];
88
+ if (funcConfig && funcMeta) {
89
+ singletonServices.logger.warn(`Version '${funcName}' not registered, resolved to '${baseName}'`);
90
+ }
91
+ }
92
+ }
56
93
  if (!funcConfig) {
57
94
  throw new Error(`Function not found: ${funcName}`);
58
95
  }
59
- const allMeta = pikkuState(packageName, 'function', 'meta');
60
- const funcMeta = allMeta[funcName];
61
96
  if (!funcMeta) {
62
97
  throw new Error(`Function meta not found: ${funcName}`);
63
98
  }
@@ -73,6 +108,14 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
73
108
  resolvedCreateWireServices = factories.createWireServices;
74
109
  }
75
110
  }
111
+ const allChannelMiddleware = combineChannelMiddleware(wireType, wireId, {
112
+ wireInheritedChannelMiddleware: inheritedChannelMiddleware,
113
+ wireChannelMiddleware,
114
+ packageName,
115
+ });
116
+ const resolvedWire = allChannelMiddleware.length > 0 && wire.channel
117
+ ? wrapChannelWithMiddleware(wire, resolvedSingletonServices, allChannelMiddleware)
118
+ : wire;
76
119
  // Convert tags to PermissionMetadata and merge with inheritedPermissions
77
120
  const mergedInheritedPermissions = [
78
121
  ...(inheritedPermissions || []),
@@ -80,22 +123,36 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
80
123
  ];
81
124
  // Helper function to run permissions and execute the function
82
125
  const executeFunction = async () => {
83
- const initialSession = wire.session?.freezeInitial();
84
- const wireWithInitialSession = {
85
- ...wire,
86
- initialSession,
126
+ const functionWireProps = sessionService
127
+ ? createFunctionSessionWireProps(sessionService)
128
+ : undefined;
129
+ const wireWithSession = {
130
+ ...resolvedWire,
131
+ ...functionWireProps,
87
132
  };
88
- if (wiringAuth === true || funcConfig.auth === true) {
89
- // This means it was explicitly enabled in either wiring or function and has to be respected
90
- if (!initialSession) {
133
+ const session = wireWithSession.session;
134
+ if (funcMeta.sessionless) {
135
+ if (wiringAuth === true || funcConfig.auth === true) {
136
+ if (!session) {
137
+ throw new ForbiddenError('Authentication required');
138
+ }
139
+ }
140
+ }
141
+ else if (funcMeta.sessionless === false) {
142
+ if (wiringAuth === false || funcConfig.auth === false) {
143
+ resolvedSingletonServices.logger.warn(`Function '${funcName}' requires a session but auth was explicitly disabled — use pikkuSessionlessFunc instead.`);
144
+ }
145
+ else if (!session) {
91
146
  throw new ForbiddenError('Authentication required');
92
147
  }
93
148
  }
94
- if (wiringAuth === undefined && funcConfig.auth === undefined) {
95
- // We always default to requiring auth unless explicitly disabled
96
- if (!initialSession) {
97
- // TODO: Critical, we need to figure out how to make this work with different wirings
98
- // throw new ForbiddenError('Authentication required')
149
+ else {
150
+ // TODO: Remove after a couple of releases backward compat for
151
+ // generated metadata that doesn't include the `sessionless` field yet.
152
+ if (wiringAuth === true || funcConfig.auth === true) {
153
+ if (!session) {
154
+ throw new ForbiddenError('Authentication required');
155
+ }
99
156
  }
100
157
  }
101
158
  // Evaluate the data from the lazy function
@@ -116,16 +173,18 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
116
173
  funcInheritedPermissions: funcMeta.permissions,
117
174
  funcPermissions: funcConfig.permissions,
118
175
  services: resolvedSingletonServices,
119
- wire: { ...wireWithInitialSession, rpc: undefined },
176
+ wire: { ...wireWithSession, rpc: undefined },
120
177
  data: actualData,
121
178
  packageName,
122
179
  });
123
- const wireServices = await resolvedCreateWireServices?.(resolvedSingletonServices, wireWithInitialSession);
180
+ const wireServices = await resolvedCreateWireServices?.(resolvedSingletonServices, wireWithSession);
124
181
  try {
125
182
  const services = { ...resolvedSingletonServices, ...wireServices };
126
- const rpc = rpcService.getContextRPCService(services, wireWithInitialSession);
183
+ const rpc = rpcService.getContextRPCService(services, wireWithSession, {
184
+ sessionService,
185
+ });
127
186
  return await funcConfig.func(services, actualData, {
128
- ...wireWithInitialSession,
187
+ ...wireWithSession,
129
188
  rpc,
130
189
  });
131
190
  }
@@ -143,7 +202,7 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
143
202
  packageName,
144
203
  });
145
204
  if (allMiddleware.length > 0) {
146
- return (await runMiddleware(resolvedSingletonServices, wire, allMiddleware, executeFunction));
205
+ return (await runMiddleware(resolvedSingletonServices, resolvedWire, allMiddleware, executeFunction));
147
206
  }
148
207
  return (await executeFunction());
149
208
  };
@@ -1,5 +1,11 @@
1
1
  import type { CoreServices, CoreSingletonServices, CoreUserSession, CorePikkuMiddleware, PikkuWire, PickRequired } from '../types/core.types.js';
2
- import { Session } from 'inspector';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+ import type { CoreNodeConfig } from '../wirings/node/node.types.js';
4
+ /**
5
+ * @deprecated Use StandardSchemaV1 from @standard-schema/spec instead.
6
+ * This alias exists only for backward compatibility with generated code.
7
+ */
8
+ export type ZodLike<T = any> = StandardSchemaV1<T, T>;
3
9
  /**
4
10
  * Represents a core API function that performs an operation using core services and a user session.
5
11
  *
@@ -8,7 +14,7 @@ import { Session } from 'inspector';
8
14
  * @template Services - The services type, defaults to `CoreServices`.
9
15
  * @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
10
16
  */
11
- export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out> = PikkuWire<In, Out, true, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
17
+ export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession, Wire extends PikkuWire<In, Out> = PikkuWire<In, Out, true, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
12
18
  /**
13
19
  * Represents a core API function that can be used without a session.
14
20
  *
@@ -17,7 +23,7 @@ export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices =
17
23
  * @template Services - The services type, defaults to `CoreServices`.
18
24
  * @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
19
25
  */
20
- export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out, false, CoreUserSession, any, any, any> = PikkuWire<In, Out, false, CoreUserSession, any, any, any>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
26
+ export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession, Wire extends PikkuWire<In, Out, false, Session, any, any, any> = PikkuWire<In, Out, false, Session, any, any, any>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
21
27
  /**
22
28
  * Represents a function that checks permissions for a given operation.
23
29
  *
@@ -36,8 +42,8 @@ export type CorePikkuPermission<In = any, Services extends CoreSingletonServices
36
42
  export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession> = PikkuWire<In, never, false, CoreUserSession>> = {
37
43
  /** The permission function */
38
44
  func: CorePikkuPermission<In, Services, Wire>;
39
- /** Optional human-readable title for the permission */
40
- title?: string;
45
+ /** Optional human-readable name for the permission */
46
+ name?: string;
41
47
  /** Optional description of what the permission checks */
42
48
  description?: string;
43
49
  };
@@ -49,18 +55,18 @@ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonSe
49
55
  * ```typescript
50
56
  * // Direct function syntax
51
57
  * export const adminPermission = pikkuPermission(
52
- * async ({ logger }, _data, { session }) => {
53
- * const currentSession = await session.get()
58
+ * async ({ logger }, _data, { getSession }) => {
59
+ * const currentSession = await getSession()
54
60
  * return currentSession?.role === 'admin'
55
61
  * }
56
62
  * )
57
63
  *
58
64
  * // Configuration object syntax with metadata
59
65
  * export const adminPermission = pikkuPermission({
60
- * title: 'Admin Permission',
66
+ * name: 'Admin Permission',
61
67
  * description: 'Checks if user has admin role',
62
- * func: async ({ logger }, _data, { session }) => {
63
- * const currentSession = await session.get()
68
+ * func: async ({ logger }, _data, { getSession }) => {
69
+ * const currentSession = await getSession()
64
70
  * return currentSession?.role === 'admin'
65
71
  * }
66
72
  * })
@@ -85,8 +91,8 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
85
91
  * export const requireRole = pikkuPermissionFactory<{ role: string }>(({
86
92
  * role
87
93
  * }) => {
88
- * return pikkuPermission(async ({ logger }, data, { session }) => {
89
- * const currentSession = await session.get()
94
+ * return pikkuPermission(async ({ logger }, data, { getSession }) => {
95
+ * const currentSession = await getSession()
90
96
  * if (!currentSession || currentSession.role !== role) {
91
97
  * logger.warn(`Permission denied: required role '${role}'`)
92
98
  * return false
@@ -97,93 +103,31 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
97
103
  * ```
98
104
  */
99
105
  export declare const pikkuPermissionFactory: <In = any>(factory: CorePikkuPermissionFactory<In>) => CorePikkuPermissionFactory<In>;
100
- export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Record<string, PikkuPermission | PikkuPermission[]> | undefined;
101
- /**
102
- * Zod schema type - matches z.ZodType shape for type inference
103
- * This avoids requiring zod as a dependency while allowing schema inference
104
- */
105
- export type ZodLike<T = any> = {
106
- _input: T;
107
- _output: T;
106
+ export type CorePikkuAuth<Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = (services: Services, session: Session) => Promise<boolean> | boolean;
107
+ export type CorePikkuAuthConfig<Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = {
108
+ func: CorePikkuAuth<Services, Session>;
109
+ name?: string;
110
+ description?: string;
108
111
  };
109
- export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any> | CorePikkuFunctionSessionless<any, any, any, any>, PikkuPermission extends CorePikkuPermission<any, any, any> = CorePikkuPermission<any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, InputSchema extends ZodLike | undefined = undefined, OutputSchema extends ZodLike | undefined = undefined> = {
112
+ export declare const pikkuAuth: <Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession>(auth: CorePikkuAuth<Services, Session> | CorePikkuAuthConfig<Services, Session>) => CorePikkuPermission<any, Services, any>;
113
+ export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Record<string, PikkuPermission | PikkuPermission[]> | undefined;
114
+ export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any, any> | CorePikkuFunctionSessionless<any, any, any, any, any>, PikkuPermission extends CorePikkuPermission<any, any, any> = CorePikkuPermission<any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, InputSchema extends StandardSchemaV1 | undefined = undefined, OutputSchema extends StandardSchemaV1 | undefined = undefined> = {
110
115
  /** Optional human-readable title for the function */
111
116
  title?: string;
112
117
  /** Optional description of what the function does */
113
118
  description?: string;
114
119
  override?: string;
120
+ version?: number;
115
121
  tags?: string[];
116
122
  expose?: boolean;
117
- internal?: boolean;
123
+ remote?: boolean;
124
+ mcp?: boolean;
125
+ requiresApproval?: boolean;
118
126
  func: PikkuFunction;
119
127
  auth?: boolean;
120
128
  permissions?: CorePermissionGroup<PikkuPermission>;
121
129
  middleware?: PikkuMiddleware[];
122
130
  input?: InputSchema;
123
131
  output?: OutputSchema;
132
+ node?: CoreNodeConfig;
124
133
  };
125
- /**
126
- * A trigger function that sets up a subscription and returns a teardown function.
127
- * The trigger is fired via wire.trigger.trigger(data).
128
- *
129
- * @template TConfig - Configuration type (hardcoded when wired)
130
- * @template TOutput - Output type produced when trigger fires
131
- * @template Services - Services available to the trigger
132
- */
133
- export type CorePikkuTriggerFunction<TConfig = unknown, TOutput = unknown, Services extends CoreSingletonServices = CoreSingletonServices> = (services: Services, config: TConfig, wire: {
134
- trigger: {
135
- trigger: (data: TOutput) => void;
136
- };
137
- }) => Promise<() => void | Promise<void>>;
138
- /**
139
- * Configuration object for creating a trigger function with metadata
140
- */
141
- export type CorePikkuTriggerFunctionConfig<TConfig = unknown, TOutput = unknown, Services extends CoreSingletonServices = CoreSingletonServices, ConfigSchema extends ZodLike | undefined = undefined, OutputSchema extends ZodLike | undefined = undefined> = {
142
- /** Optional human-readable title for the trigger */
143
- title?: string;
144
- /** Optional description of what the trigger does */
145
- description?: string;
146
- /** Optional tags for categorization */
147
- tags?: string[];
148
- /** The trigger function */
149
- func: CorePikkuTriggerFunction<TConfig, TOutput, Services>;
150
- /** Optional Zod schema for config validation */
151
- config?: ConfigSchema;
152
- /** Optional Zod schema for output validation */
153
- output?: OutputSchema;
154
- };
155
- /**
156
- * Factory function for creating trigger functions
157
- * Supports both direct function and configuration object syntax
158
- *
159
- * @example
160
- * ```typescript
161
- * // Direct function syntax
162
- * export const redisSubscribeTrigger = pikkuTriggerFunc<
163
- * { channel: string },
164
- * { message: string }
165
- * >(async ({ redis }, { channel }, { trigger }) => {
166
- * const subscriber = redis.duplicate()
167
- * await subscriber.subscribe(channel, (msg) => {
168
- * trigger.trigger({ message: msg })
169
- * })
170
- * return () => subscriber.unsubscribe()
171
- * })
172
- *
173
- * // Configuration object syntax with metadata
174
- * export const redisSubscribeTrigger = pikkuTriggerFunc({
175
- * title: 'Redis Subscribe Trigger',
176
- * description: 'Listens to Redis pub/sub channel',
177
- * config: z.object({ channel: z.string() }),
178
- * output: z.object({ message: z.string() }),
179
- * func: async ({ redis }, { channel }, { trigger }) => {
180
- * const subscriber = redis.duplicate()
181
- * await subscriber.subscribe(channel, (msg) => {
182
- * trigger.trigger({ message: msg })
183
- * })
184
- * return () => subscriber.unsubscribe()
185
- * }
186
- * })
187
- * ```
188
- */
189
- export declare const pikkuTriggerFunc: <TConfig = unknown, TOutput = unknown, Services extends CoreSingletonServices = CoreSingletonServices, ConfigSchema extends ZodLike | undefined = undefined, OutputSchema extends ZodLike | undefined = undefined>(triggerOrConfig: CorePikkuTriggerFunction<TConfig, TOutput, Services> | CorePikkuTriggerFunctionConfig<TConfig, TOutput, Services, ConfigSchema, OutputSchema>) => CorePikkuTriggerFunctionConfig<TConfig, TOutput, Services, ConfigSchema, OutputSchema>;
@@ -6,18 +6,18 @@
6
6
  * ```typescript
7
7
  * // Direct function syntax
8
8
  * export const adminPermission = pikkuPermission(
9
- * async ({ logger }, _data, { session }) => {
10
- * const currentSession = await session.get()
9
+ * async ({ logger }, _data, { getSession }) => {
10
+ * const currentSession = await getSession()
11
11
  * return currentSession?.role === 'admin'
12
12
  * }
13
13
  * )
14
14
  *
15
15
  * // Configuration object syntax with metadata
16
16
  * export const adminPermission = pikkuPermission({
17
- * title: 'Admin Permission',
17
+ * name: 'Admin Permission',
18
18
  * description: 'Checks if user has admin role',
19
- * func: async ({ logger }, _data, { session }) => {
20
- * const currentSession = await session.get()
19
+ * func: async ({ logger }, _data, { getSession }) => {
20
+ * const currentSession = await getSession()
21
21
  * return currentSession?.role === 'admin'
22
22
  * }
23
23
  * })
@@ -35,8 +35,8 @@ export const pikkuPermission = (permission) => {
35
35
  * export const requireRole = pikkuPermissionFactory<{ role: string }>(({
36
36
  * role
37
37
  * }) => {
38
- * return pikkuPermission(async ({ logger }, data, { session }) => {
39
- * const currentSession = await session.get()
38
+ * return pikkuPermission(async ({ logger }, data, { getSession }) => {
39
+ * const currentSession = await getSession()
40
40
  * if (!currentSession || currentSession.role !== role) {
41
41
  * logger.warn(`Permission denied: required role '${role}'`)
42
42
  * return false
@@ -49,43 +49,13 @@ export const pikkuPermission = (permission) => {
49
49
  export const pikkuPermissionFactory = (factory) => {
50
50
  return factory;
51
51
  };
52
- /**
53
- * Factory function for creating trigger functions
54
- * Supports both direct function and configuration object syntax
55
- *
56
- * @example
57
- * ```typescript
58
- * // Direct function syntax
59
- * export const redisSubscribeTrigger = pikkuTriggerFunc<
60
- * { channel: string },
61
- * { message: string }
62
- * >(async ({ redis }, { channel }, { trigger }) => {
63
- * const subscriber = redis.duplicate()
64
- * await subscriber.subscribe(channel, (msg) => {
65
- * trigger.trigger({ message: msg })
66
- * })
67
- * return () => subscriber.unsubscribe()
68
- * })
69
- *
70
- * // Configuration object syntax with metadata
71
- * export const redisSubscribeTrigger = pikkuTriggerFunc({
72
- * title: 'Redis Subscribe Trigger',
73
- * description: 'Listens to Redis pub/sub channel',
74
- * config: z.object({ channel: z.string() }),
75
- * output: z.object({ message: z.string() }),
76
- * func: async ({ redis }, { channel }, { trigger }) => {
77
- * const subscriber = redis.duplicate()
78
- * await subscriber.subscribe(channel, (msg) => {
79
- * trigger.trigger({ message: msg })
80
- * })
81
- * return () => subscriber.unsubscribe()
82
- * }
83
- * })
84
- * ```
85
- */
86
- export const pikkuTriggerFunc = (triggerOrConfig) => {
87
- if (typeof triggerOrConfig === 'function') {
88
- return { func: triggerOrConfig };
89
- }
90
- return triggerOrConfig;
52
+ export const pikkuAuth = (auth) => {
53
+ const fn = typeof auth === 'function' ? auth : auth.func;
54
+ const wrapper = async (services, _data, wire) => {
55
+ const session = wire.session;
56
+ if (!session)
57
+ return false;
58
+ return fn(services, session);
59
+ };
60
+ return wrapper;
91
61
  };