@pikku/cli 0.12.54 → 0.12.56

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 (267) hide show
  1. package/cli.schema.json +1 -1
  2. package/console-app/assets/{index-DYnbceYg.js → index-xN8LW0II.js} +155 -155
  3. package/console-app/index.html +1 -1
  4. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +3 -3
  6. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-channel.d.ts +6 -6
  8. package/dist/.pikku/cli/pikku-cli-channel.js +11 -1
  9. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  10. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  11. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  12. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  13. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +14 -0
  14. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  15. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  16. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  17. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +29 -0
  18. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  19. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  20. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  21. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  22. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  23. package/dist/.pikku/function/pikku-function-types.gen.d.ts +8 -31
  24. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  25. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  26. package/dist/.pikku/function/pikku-functions-meta.gen.json +1420 -1384
  27. package/dist/.pikku/function/pikku-functions.gen.js +3 -1
  28. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  29. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  30. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  31. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  32. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  33. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  34. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  35. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  36. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  37. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  38. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  39. package/dist/.pikku/pikku-services.gen.d.ts +4 -2
  40. package/dist/.pikku/pikku-services.gen.js +2 -0
  41. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  42. package/dist/.pikku/pikku-types.gen.js +1 -1
  43. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  44. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  45. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  46. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.json +0 -248
  47. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  48. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  49. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  50. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +69 -67
  51. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  52. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  53. package/dist/.pikku/schemas/register.gen.js +191 -185
  54. package/dist/.pikku/schemas/schemas/FabricAddonVerifyInput.schema.json +1 -0
  55. package/dist/.pikku/schemas/schemas/FabricAddonVerifyOutput.schema.json +1 -0
  56. package/dist/.pikku/schemas/schemas/PikkuAuthInput.schema.json +1 -0
  57. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  58. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  59. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  60. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  61. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  62. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  63. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  64. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  65. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  66. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  67. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  68. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +9 -3
  69. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  70. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  71. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  72. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  73. package/dist/bin/pikku-bin.mjs +2 -2
  74. package/dist/src/cli.wiring.js +15 -1
  75. package/dist/src/deploy/analyzer/analyzer.d.ts +6 -0
  76. package/dist/src/deploy/analyzer/analyzer.js +5 -4
  77. package/dist/src/deploy/build-pipeline.d.ts +5 -1
  78. package/dist/src/deploy/build-pipeline.js +5 -5
  79. package/dist/src/deploy/bundler/bun-bundler.d.ts +14 -0
  80. package/dist/src/deploy/bundler/bun-bundler.js +121 -0
  81. package/dist/src/deploy/bundler/bundler.d.ts +25 -30
  82. package/dist/src/deploy/bundler/bundler.interface.d.ts +54 -0
  83. package/dist/src/deploy/bundler/bundler.interface.js +11 -0
  84. package/dist/src/deploy/bundler/bundler.js +120 -190
  85. package/dist/src/deploy/bundler/dep-extractor.d.ts +11 -3
  86. package/dist/src/deploy/bundler/dep-extractor.js +12 -6
  87. package/dist/src/deploy/bundler/index.d.ts +5 -2
  88. package/dist/src/deploy/bundler/index.js +4 -2
  89. package/dist/src/deploy/bundler/node-bundler.d.ts +13 -0
  90. package/dist/src/deploy/bundler/node-bundler.js +80 -0
  91. package/dist/src/deploy/provider-adapter.d.ts +11 -0
  92. package/dist/src/deploy/server-entry.js +3 -1
  93. package/dist/src/fabric/fabric-commands.d.ts +109 -72
  94. package/dist/src/fabric/fabric-commands.js +8 -0
  95. package/dist/src/fabric/functions/add.function.d.ts +3 -3
  96. package/dist/src/fabric/functions/addon-verify.function.d.ts +54 -0
  97. package/dist/src/fabric/functions/addon-verify.function.js +153 -0
  98. package/dist/src/fabric/functions/db-schema.function.d.ts +3 -3
  99. package/dist/src/fabric/functions/deploy-list.function.d.ts +3 -3
  100. package/dist/src/fabric/functions/deploy-units.function.d.ts +3 -3
  101. package/dist/src/fabric/functions/deploy.function.d.ts +6 -6
  102. package/dist/src/fabric/functions/domains-add.function.d.ts +3 -3
  103. package/dist/src/fabric/functions/domains-list.function.d.ts +3 -3
  104. package/dist/src/fabric/functions/domains-remove.function.d.ts +3 -3
  105. package/dist/src/fabric/functions/errors.function.d.ts +3 -3
  106. package/dist/src/fabric/functions/init.function.d.ts +3 -3
  107. package/dist/src/fabric/functions/link.function.d.ts +3 -3
  108. package/dist/src/fabric/functions/llm-key.function.d.ts +3 -3
  109. package/dist/src/fabric/functions/llm-key.function.js +1 -1
  110. package/dist/src/fabric/functions/login.function.d.ts +3 -3
  111. package/dist/src/fabric/functions/logs.function.d.ts +3 -3
  112. package/dist/src/fabric/functions/metrics.function.d.ts +3 -3
  113. package/dist/src/fabric/functions/publish.function.d.ts +3 -3
  114. package/dist/src/fabric/functions/publish.function.js +8 -3
  115. package/dist/src/fabric/functions/rollback.function.d.ts +3 -3
  116. package/dist/src/fabric/functions/secrets-list.function.d.ts +3 -3
  117. package/dist/src/fabric/functions/secrets-set.function.d.ts +3 -3
  118. package/dist/src/fabric/functions/smoke.function.d.ts +3 -3
  119. package/dist/src/fabric/functions/status.function.d.ts +3 -3
  120. package/dist/src/fabric/functions/trace.function.d.ts +3 -3
  121. package/dist/src/fabric/functions/validate.function.d.ts +3 -3
  122. package/dist/src/functions/commands/all.d.ts +1 -1
  123. package/dist/src/functions/commands/all.js +19 -2
  124. package/dist/src/functions/commands/binary.d.ts +3 -3
  125. package/dist/src/functions/commands/bootstrap.d.ts +1 -1
  126. package/dist/src/functions/commands/bootstrap.js +3 -0
  127. package/dist/src/functions/commands/console.d.ts +3 -3
  128. package/dist/src/functions/commands/db-audit.d.ts +1 -1
  129. package/dist/src/functions/commands/db-generate.d.ts +1 -1
  130. package/dist/src/functions/commands/db-migrate.d.ts +1 -1
  131. package/dist/src/functions/commands/db-reset.d.ts +1 -1
  132. package/dist/src/functions/commands/db-seed.d.ts +1 -1
  133. package/dist/src/functions/commands/deploy-apply.d.ts +3 -3
  134. package/dist/src/functions/commands/deploy-apply.js +32 -1
  135. package/dist/src/functions/commands/deploy-info.d.ts +1 -1
  136. package/dist/src/functions/commands/deploy-plan.d.ts +3 -3
  137. package/dist/src/functions/commands/deploy-plan.js +3 -1
  138. package/dist/src/functions/commands/dev.d.ts +3 -3
  139. package/dist/src/functions/commands/dev.js +17 -45
  140. package/dist/src/functions/commands/emails-init.d.ts +1 -1
  141. package/dist/src/functions/commands/enable.d.ts +6 -5
  142. package/dist/src/functions/commands/enable.js +4 -0
  143. package/dist/src/functions/commands/info.d.ts +4 -4
  144. package/dist/src/functions/commands/login.d.ts +7 -7
  145. package/dist/src/functions/commands/meta.d.ts +31 -31
  146. package/dist/src/functions/commands/new-addon.d.ts +3 -3
  147. package/dist/src/functions/commands/new-function.d.ts +3 -3
  148. package/dist/src/functions/commands/new-middleware.d.ts +3 -3
  149. package/dist/src/functions/commands/new-permission.d.ts +3 -3
  150. package/dist/src/functions/commands/new-wiring.d.ts +3 -3
  151. package/dist/src/functions/commands/pikku-command-bootstrap.d.ts +1 -1
  152. package/dist/src/functions/commands/pikku-command-summary.d.ts +1 -1
  153. package/dist/src/functions/commands/pikku-command-summary.js +6 -1
  154. package/dist/src/functions/commands/skills.d.ts +6 -6
  155. package/dist/src/functions/commands/tests-coverage.d.ts +3 -3
  156. package/dist/src/functions/commands/tests-init.d.ts +3 -3
  157. package/dist/src/functions/commands/versions-check.d.ts +1 -1
  158. package/dist/src/functions/commands/versions-init.d.ts +3 -3
  159. package/dist/src/functions/commands/versions-update.d.ts +1 -1
  160. package/dist/src/functions/commands/watch.d.ts +3 -3
  161. package/dist/src/functions/commands/workspace-validate.d.ts +3 -3
  162. package/dist/src/functions/db/db-codegen.js +14 -0
  163. package/dist/src/functions/db/sqlite/sqlite-runtime-bun.js +10 -0
  164. package/dist/src/functions/runtimes/fetch/index.d.ts +1 -1
  165. package/dist/src/functions/runtimes/nextjs/pikku-command-nextjs.d.ts +1 -1
  166. package/dist/src/functions/runtimes/tanstack-start/pikku-command-tanstack-start.d.ts +1 -1
  167. package/dist/src/functions/runtimes/websocket/pikku-command-websocket-typed.d.ts +1 -1
  168. package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent-types.d.ts +1 -1
  169. package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent.d.ts +1 -1
  170. package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.d.ts +1 -1
  171. package/dist/src/functions/wirings/auth/pikku-command-auth.d.ts +7 -1
  172. package/dist/src/functions/wirings/auth/pikku-command-auth.js +14 -2
  173. package/dist/src/functions/wirings/auth/serialize-auth-types.d.ts +10 -0
  174. package/dist/src/functions/wirings/auth/serialize-auth-types.js +15 -0
  175. package/dist/src/functions/wirings/channels/pikku-channels.d.ts +1 -1
  176. package/dist/src/functions/wirings/channels/pikku-command-channel-types.d.ts +1 -1
  177. package/dist/src/functions/wirings/channels/pikku-command-channels-map.d.ts +1 -1
  178. package/dist/src/functions/wirings/channels/pikku-command-channels.d.ts +1 -1
  179. package/dist/src/functions/wirings/cli/pikku-command-cli-entry.d.ts +1 -1
  180. package/dist/src/functions/wirings/cli/pikku-command-cli-types.d.ts +1 -1
  181. package/dist/src/functions/wirings/cli/pikku-command-cli.d.ts +1 -1
  182. package/dist/src/functions/wirings/console/pikku-command-console-functions.d.ts +1 -1
  183. package/dist/src/functions/wirings/console/pikku-command-node-types.d.ts +1 -1
  184. package/dist/src/functions/wirings/console/pikku-command-nodes-meta.d.ts +1 -1
  185. package/dist/src/functions/wirings/credentials/pikku-command-credentials.d.ts +1 -1
  186. package/dist/src/functions/wirings/emails/pikku-command-emails.d.ts +1 -1
  187. package/dist/src/functions/wirings/functions/pikku-command-addon-types.d.ts +1 -1
  188. package/dist/src/functions/wirings/functions/pikku-command-function-types-split.d.ts +3 -3
  189. package/dist/src/functions/wirings/functions/pikku-command-function-types.d.ts +3 -3
  190. package/dist/src/functions/wirings/functions/pikku-command-function-types.js +10 -3
  191. package/dist/src/functions/wirings/functions/pikku-command-functions.d.ts +1 -1
  192. package/dist/src/functions/wirings/functions/pikku-command-services.d.ts +1 -1
  193. package/dist/src/functions/wirings/functions/schemas.d.ts +1 -1
  194. package/dist/src/functions/wirings/functions/serialize-function-types.js +6 -29
  195. package/dist/src/functions/wirings/gateway/pikku-command-gateway.d.ts +1 -1
  196. package/dist/src/functions/wirings/http/pikku-command-http-map.d.ts +1 -1
  197. package/dist/src/functions/wirings/http/pikku-command-http-routes.d.ts +1 -1
  198. package/dist/src/functions/wirings/http/pikku-command-http-types.d.ts +1 -1
  199. package/dist/src/functions/wirings/http/pikku-command-openapi.d.ts +1 -1
  200. package/dist/src/functions/wirings/http/pikku-http-routes.d.ts +1 -1
  201. package/dist/src/functions/wirings/mcp/pikku-command-mcp-json.d.ts +1 -1
  202. package/dist/src/functions/wirings/mcp/pikku-command-mcp-types.d.ts +1 -1
  203. package/dist/src/functions/wirings/mcp/pikku-command-mcp.d.ts +1 -1
  204. package/dist/src/functions/wirings/middleware/pikku-command-middleware.d.ts +1 -1
  205. package/dist/src/functions/wirings/package/pikku-command-package-types.d.ts +2 -2
  206. package/dist/src/functions/wirings/package/pikku-command-package.d.ts +1 -1
  207. package/dist/src/functions/wirings/permissions/pikku-command-permissions.d.ts +1 -1
  208. package/dist/src/functions/wirings/queue/pikku-command-queue-map.d.ts +1 -1
  209. package/dist/src/functions/wirings/queue/pikku-command-queue-service.d.ts +1 -1
  210. package/dist/src/functions/wirings/queue/pikku-command-queue-types.d.ts +1 -1
  211. package/dist/src/functions/wirings/queue/pikku-command-queue.d.ts +1 -1
  212. package/dist/src/functions/wirings/queue/pikku-queue-map.d.ts +1 -1
  213. package/dist/src/functions/wirings/queue/pikku-queue.d.ts +1 -1
  214. package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.d.ts +1 -1
  215. package/dist/src/functions/wirings/realtime/pikku-command-realtime.d.ts +1 -1
  216. package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.d.ts +1 -1
  217. package/dist/src/functions/wirings/rpc/pikku-command-react-query.d.ts +1 -1
  218. package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.d.ts +1 -1
  219. package/dist/src/functions/wirings/rpc/pikku-command-rpc-client.d.ts +1 -1
  220. package/dist/src/functions/wirings/rpc/pikku-command-rpc-map.d.ts +2 -2
  221. package/dist/src/functions/wirings/rpc/pikku-command-rpc.d.ts +1 -1
  222. package/dist/src/functions/wirings/scheduler/pikku-command-scheduler-types.d.ts +1 -1
  223. package/dist/src/functions/wirings/scheduler/pikku-command-scheduler.d.ts +1 -1
  224. package/dist/src/functions/wirings/secrets/pikku-command-secrets.d.ts +1 -1
  225. package/dist/src/functions/wirings/triggers/pikku-command-trigger-types.d.ts +3 -3
  226. package/dist/src/functions/wirings/triggers/pikku-command-trigger.d.ts +1 -1
  227. package/dist/src/functions/wirings/variables/pikku-command-variables.d.ts +1 -1
  228. package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.d.ts +1 -1
  229. package/dist/src/functions/wirings/workflow/pikku-command-workflow.d.ts +1 -1
  230. package/dist/src/functions/workflows/all.workflow.js +6 -1
  231. package/dist/src/scaffold/rpc-remote.gen.d.ts +3 -3
  232. package/dist/src/scaffold/rpc-remote.gen.js +1 -1
  233. package/dist/src/server/bun-server-runner.d.ts +17 -0
  234. package/dist/src/server/bun-server-runner.js +25 -0
  235. package/dist/src/server/dev-server-runner.interface.d.ts +31 -0
  236. package/dist/src/server/dev-server-runner.interface.js +11 -0
  237. package/dist/src/server/node-server-runner.d.ts +12 -0
  238. package/dist/src/server/node-server-runner.js +30 -0
  239. package/dist/src/services/cli-logger.service.js +7 -1
  240. package/dist/src/services.js +18 -0
  241. package/dist/src/utils/detect-better-auth.d.ts +7 -0
  242. package/dist/src/utils/detect-better-auth.js +29 -0
  243. package/dist/src/utils/parse-cli-filters.d.ts +1 -0
  244. package/dist/src/utils/parse-cli-filters.js +1 -0
  245. package/dist/src/utils/pikku-cli-config.js +1 -1
  246. package/dist/src/utils/serialize-schemas.js +5 -1
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +4 -4
  249. package/skills/pikku-addon/SKILL.md +25 -117
  250. package/skills/pikku-addon/references/addon-package-manifest.md +63 -0
  251. package/skills/pikku-cli/SKILL.md +7 -93
  252. package/skills/pikku-cli/references/complete-example.md +82 -0
  253. package/skills/pikku-concepts/SKILL.md +17 -69
  254. package/skills/pikku-concepts/references/concept-mapping.md +37 -13
  255. package/skills/pikku-concepts/references/packages.md +29 -0
  256. package/skills/pikku-http/SKILL.md +14 -105
  257. package/skills/pikku-http/references/http-options.md +57 -0
  258. package/skills/pikku-middleware/SKILL.md +11 -68
  259. package/skills/pikku-middleware/references/middleware-patterns.md +61 -0
  260. package/skills/pikku-realtime/SKILL.md +56 -105
  261. package/skills/pikku-realtime/references/other-routes.md +23 -0
  262. package/skills/pikku-services/SKILL.md +25 -108
  263. package/skills/pikku-services/references/audit-wire-service.md +34 -0
  264. package/skills/pikku-testing/SKILL.md +51 -359
  265. package/skills/pikku-testing/references/cucumber-bdd-testing.md +176 -0
  266. package/skills/pikku-workflow/SKILL.md +93 -259
  267. package/skills/pikku-workflow/references/workflow-reference.md +63 -0
@@ -77,20 +77,17 @@ wireHTTP({
77
77
 
78
78
  ## Global Middleware (`addGlobalMiddleware`)
79
79
 
80
- `addGlobalMiddleware` registers middleware that runs before everything else across every wire type: HTTP, Queue, Channel, Trigger, Scheduler, Workflow, Agent, CLI, MCP. Use it for cross-cutting concerns like telemetry that must wrap every invocation regardless of transport.
80
+ Runs before everything else, across every wire type: HTTP, Queue, Channel, Trigger, Scheduler, Workflow, Agent, CLI, MCP. Use it for cross-cutting concerns (e.g. telemetry) that must wrap every invocation regardless of transport.
81
81
 
82
82
  ```typescript
83
83
  import { addGlobalMiddleware } from '@pikku/core'
84
84
  import { telemetryOuter, telemetryInner } from '@pikku/core/middleware'
85
85
 
86
- // Outer telemetry: wraps the full call (highest priority)
87
- addGlobalMiddleware([telemetryOuter({ environmentId: env.STAGE_ID })])
88
-
89
- // Inner telemetry: closest to the function body (lowest priority)
90
- addGlobalMiddleware([telemetryInner({ environmentId: env.STAGE_ID })])
86
+ addGlobalMiddleware([telemetryOuter({ environmentId: env.STAGE_ID })]) // wraps the full call
87
+ addGlobalMiddleware([telemetryInner({ environmentId: env.STAGE_ID })]) // closest to the function body
91
88
  ```
92
89
 
93
- `telemetryOuter` ships with `priority: 'highest'` and `telemetryInner` with `priority: 'lowest'` — so even if both are added in the same call, priority sorting places outer first regardless of array order.
90
+ `telemetryOuter` ships with `priority: 'highest'`, `telemetryInner` with `priority: 'lowest'` — so priority sorting places outer first regardless of array/call order.
94
91
 
95
92
  ## HTTP & Prefix Middleware (`addHTTPMiddleware`)
96
93
 
@@ -165,15 +162,13 @@ const earlyMiddleware = pikkuMiddleware({
165
162
  })
166
163
  ```
167
164
 
168
- Within the same priority level, registration order is preserved. Priority is the primary sort key — use it when a middleware must run before or after others regardless of registration order (e.g. telemetry wrapping everything, session extraction before auth checks).
169
-
170
- ## Common Patterns
165
+ Priority is the primary sort key; within the same level, registration order is preserved. Use priority when a middleware must run before/after others regardless of registration order (e.g. telemetry wrapping everything, session extraction before auth checks).
171
166
 
172
- ### Service-to-Service Bearer Auth
167
+ ## Service-to-Service Bearer Auth (canonical pattern)
173
168
 
174
- The canonical pattern for a server that exposes RPCs only to a trusted caller (e.g. an API calling a machine-agent):
169
+ A server that exposes RPCs only to a trusted caller (e.g. an API calling a machine-agent). Auth lives in a tag middleware — NOT in the function body. Authorization/permission checks belong in the `permissions` field (see `pikku-permissions`), never inside `func`.
175
170
 
176
- **On the server (the service being called):**
171
+ **On the server (the service being called):** tag the function, register a `pikkuMiddleware` that reads the `Authorization` header on that tag.
177
172
 
178
173
  ```typescript
179
174
  // lib/host-token.ts
@@ -217,63 +212,11 @@ export const myFunc = pikkuSessionlessFunc({
217
212
  })
218
213
  ```
219
214
 
220
- **On the client (the caller):**
221
-
222
- Use the generated `RPCInvoke` type from `.pikku/rpc/pikku-rpc-wirings-map.gen.d.ts` — never hand-write the input/output types:
223
-
224
- ```typescript
225
- import type { RPCInvoke } from '../../backends/my-service/.pikku/rpc/pikku-rpc-wirings-map.gen.d.js'
226
-
227
- export function getServiceRPC(baseUrl: string, token: string): RPCInvoke {
228
- return async (name: string, data?: unknown) => {
229
- const res = await fetch(`${baseUrl}/rpc/${String(name)}`, {
230
- method: 'POST',
231
- headers: {
232
- 'Content-Type': 'application/json',
233
- Authorization: `Bearer ${token}`,
234
- },
235
- body: JSON.stringify({ data: data ?? {} }),
236
- })
237
- if (!res.ok) {
238
- const text = await res.text().catch(() => '')
239
- throw new Error(`rpc ${String(name)} failed: ${res.status} ${text}`)
240
- }
241
- return res.json()
242
- } as RPCInvoke
243
- }
244
- ```
245
-
246
- ### Session-Setting Middleware
247
-
248
- ```typescript
249
- const apiKeyAuth = pikkuMiddleware(async ({ kysely }, { http, setSession, session }, next) => {
250
- if (session) return next() // already authenticated
251
-
252
- const header = http?.request?.header?.('x-api-key')
253
- if (!header) return next()
254
-
255
- const row = await kysely.selectFrom('apiKey').select('userId').where('key', '=', header).executeTakeFirst()
256
- if (row) setSession?.({ userId: row.userId })
257
-
258
- return next()
259
- })
260
-
261
- addTagMiddleware('api-key-auth', [apiKeyAuth])
262
- ```
263
-
264
- Functions tagged `'api-key-auth'` with `auth: true` reject requests without a valid key; those with `auth: false` can inspect the session but won't reject.
215
+ **On the client (the caller):** use the generated `RPCInvoke` type — never hand-write a `fetch` wrapper's types. See `references/middleware-patterns.md`.
265
216
 
266
- ### Request Logging / Audit
217
+ ## More patterns
267
218
 
268
- ```typescript
269
- const auditLog = pikkuMiddleware(async ({ logger, db }, wire, next) => {
270
- const start = Date.now()
271
- await next()
272
- await db.createAuditLog({ duration: Date.now() - start })
273
- })
274
-
275
- addHTTPMiddleware('/admin/*', [auditLog])
276
- ```
219
+ `references/middleware-patterns.md` covers the client-side `RPCInvoke` caller, session-setting middleware (set a session from an API key), and request logging / audit middleware.
277
220
 
278
221
  ## After Changes
279
222
 
@@ -0,0 +1,61 @@
1
+ # Middleware Patterns (extended)
2
+
3
+ Detailed, less-common middleware recipes. The common-path bearer-auth pattern lives inline in SKILL.md; this file holds the client-side caller, session-setting, and audit recipes.
4
+
5
+ ## Service-to-Service: the client (caller) side
6
+
7
+ Use the generated `RPCInvoke` type from `.pikku/rpc/pikku-rpc-wirings-map.gen.d.ts` — never hand-write the input/output types:
8
+
9
+ ```typescript
10
+ import type { RPCInvoke } from '../../backends/my-service/.pikku/rpc/pikku-rpc-wirings-map.gen.d.js'
11
+
12
+ export function getServiceRPC(baseUrl: string, token: string): RPCInvoke {
13
+ return async (name: string, data?: unknown) => {
14
+ const res = await fetch(`${baseUrl}/rpc/${String(name)}`, {
15
+ method: 'POST',
16
+ headers: {
17
+ 'Content-Type': 'application/json',
18
+ Authorization: `Bearer ${token}`,
19
+ },
20
+ body: JSON.stringify({ data: data ?? {} }),
21
+ })
22
+ if (!res.ok) {
23
+ const text = await res.text().catch(() => '')
24
+ throw new Error(`rpc ${String(name)} failed: ${res.status} ${text}`)
25
+ }
26
+ return res.json()
27
+ } as RPCInvoke
28
+ }
29
+ ```
30
+
31
+ ## Session-Setting Middleware
32
+
33
+ ```typescript
34
+ const apiKeyAuth = pikkuMiddleware(async ({ kysely }, { http, setSession, session }, next) => {
35
+ if (session) return next() // already authenticated
36
+
37
+ const header = http?.request?.header?.('x-api-key')
38
+ if (!header) return next()
39
+
40
+ const row = await kysely.selectFrom('apiKey').select('userId').where('key', '=', header).executeTakeFirst()
41
+ if (row) setSession?.({ userId: row.userId })
42
+
43
+ return next()
44
+ })
45
+
46
+ addTagMiddleware('api-key-auth', [apiKeyAuth])
47
+ ```
48
+
49
+ Functions tagged `'api-key-auth'` with `auth: true` reject requests without a valid key; those with `auth: false` can inspect the session but won't reject.
50
+
51
+ ## Request Logging / Audit
52
+
53
+ ```typescript
54
+ const auditLog = pikkuMiddleware(async ({ logger, db }, wire, next) => {
55
+ const start = Date.now()
56
+ await next()
57
+ await db.createAuditLog({ duration: Date.now() - start })
58
+ })
59
+
60
+ addHTTPMiddleware('/admin/*', [auditLog])
61
+ ```
@@ -16,16 +16,13 @@ Use this skill as an execution checklist, not reference material.
16
16
  4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
17
17
  5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
18
18
 
19
- Most realtime UI is just typed pub/sub: a server pushes `todo-created`, the
20
- client renders it. Pikku's realtime feature ships exactly that, two ways:
19
+ Most realtime UI is just typed pub/sub: a server pushes `todo-created`, the client
20
+ renders it. Pikku ships exactly that, two ways — both use the same `EventHubService`
21
+ and the same publish call, so choose by transport, not by code shape:
21
22
 
22
23
  - **WebSocket** at `/events` — one connection, many topic subscriptions.
23
- - **SSE** at `GET /events/:topic` — one connection per topic, auto-cleanup
24
- on disconnect. Good for environments where WebSocket is blocked or for
25
- trivially streaming one topic.
26
-
27
- Both transports use the same `EventHubService` and the same publish call.
28
- Choose by transport, not by code shape.
24
+ - **SSE** at `GET /events/:topic` — one connection per topic, auto-cleanup on
25
+ disconnect. Good when WebSocket is blocked or for trivially streaming one topic.
29
26
 
30
27
  ## 1. Declare your topics
31
28
 
@@ -41,28 +38,24 @@ export type EventHubTopics = {
41
38
  }
42
39
  ```
43
40
 
44
- Reference it in `application-types.d.ts`:
41
+ Reference it in `application-types.d.ts` and instantiate it in `services.ts`:
45
42
 
46
43
  ```ts
44
+ // application-types.d.ts
47
45
  import type { EventHubService } from '@pikku/core/channel'
48
46
  import type { EventHubTopics } from './eventhub-topics.js'
49
47
 
50
48
  export interface SingletonServices extends CoreSingletonServices<Config> {
51
49
  eventHub?: EventHubService<EventHubTopics>
52
- // ...
53
50
  }
54
- ```
55
-
56
- And instantiate it in `services.ts`:
57
51
 
58
- ```ts
52
+ // services.ts
59
53
  import { LocalEventHubService } from '@pikku/core/channel'
60
- // ...
61
54
  const eventHub = new LocalEventHubService<EventHubTopics>()
62
55
  ```
63
56
 
64
- (For multi-instance deployments use `CloudflareEventHubService` /
65
- `LambdaEventHubService` / `UWSEventHubService` instead — same interface.)
57
+ For multi-instance deployments use `CloudflareEventHubService` /
58
+ `LambdaEventHubService` / `UWSEventHubService` instead — same interface.
66
59
 
67
60
  ## 2. Enable the server side
68
61
 
@@ -71,15 +64,13 @@ yarn pikku enable events # auth required by default
71
64
  yarn pikku enable events --noAuth # public events
72
65
  ```
73
66
 
74
- This sets `scaffold.events` in `pikku.config.json`. The next `pikku all`
75
- generates `events.gen.ts` in your scaffold dir, which wires:
67
+ This sets `scaffold.events` in `pikku.config.json`. The next `pikku all` generates
68
+ `events.gen.ts` in your scaffold dir, wiring (using whatever `eventHub` is in your
69
+ singletons — you write neither by hand):
76
70
 
77
71
  - A WebSocket channel at `/events` handling `{action: 'subscribe' | 'unsubscribe', topic}` messages.
78
72
  - An SSE handler at `GET /events/:topic`.
79
73
 
80
- You don't write either by hand. They use whatever `eventHub` service is
81
- in your singletons.
82
-
83
74
  ## 3. Generate the typed client
84
75
 
85
76
  Add to `pikku.config.json`:
@@ -87,7 +78,6 @@ Add to `pikku.config.json`:
87
78
  ```jsonc
88
79
  {
89
80
  "clientFiles": {
90
- // ...
91
81
  "realtimeFile": "packages/sdk/src/pikku/realtime.gen.ts",
92
82
  // Optional: full type inference for subscribe/unsubscribe
93
83
  "realtimeEventHubTopicsImport": "../../../functions/types/eventhub-topics.js#EventHubTopics",
@@ -95,8 +85,8 @@ Add to `pikku.config.json`:
95
85
  }
96
86
  ```
97
87
 
98
- Run `pikku all` (or `pikku realtime` to regenerate just this file). The
99
- generated file exports two surfaces:
88
+ Run `pikku all` (or `pikku realtime` to regenerate just this file). The generated
89
+ file exports two surfaces:
100
90
 
101
91
  ```ts
102
92
  export class PikkuRealtime {
@@ -112,13 +102,15 @@ export function subscribeToTopicViaSSE<K extends keyof EventHubTopics>(
112
102
  ```
113
103
 
114
104
  Without `realtimeEventHubTopicsImport`, the client falls back to
115
- `Record<string, unknown>` — usable but untyped. Set the import for full
116
- typed subscribe/unsubscribe.
105
+ `Record<string, unknown>` — usable but untyped. Set the import for full typed
106
+ subscribe/unsubscribe.
117
107
 
118
108
  ## 4. Publish events from a function
119
109
 
120
- The `/events` channel listens for client subscriptions; the eventHub fans
121
- out publishes. Functions publish like this:
110
+ The `/events` channel listens for client subscriptions; the eventHub fans out
111
+ publishes. Envelope the payload with `topic` so the client dispatcher works; the
112
+ `null` channelId means "broadcast to all subscribers" (pass a specific channel id
113
+ to exclude/include a single connection):
122
114
 
123
115
  ```ts
124
116
  import { pikkuFunc } from '#pikku'
@@ -128,47 +120,35 @@ export const createTodo = pikkuFunc({
128
120
  output: CreateTodoOutput,
129
121
  func: async ({ kysely, eventHub }, data) => {
130
122
  const todo = await kysely
131
- .insertInto('todos')
132
- .values(data)
133
- .returningAll()
123
+ .insertInto('todos').values(data).returningAll()
134
124
  .executeTakeFirstOrThrow()
135
125
 
136
126
  if (eventHub) {
137
- // Envelope the payload with `topic` so the client dispatcher works.
138
127
  await eventHub.publish('todo-created', null, {
139
128
  topic: 'todo-created',
140
129
  data: { todo },
141
130
  })
142
131
  }
143
-
144
132
  return { id: todo.id }
145
133
  },
146
134
  })
147
135
  ```
148
136
 
149
- The `null` channelId means "broadcast to all subscribers." Pass a
150
- specific channel id to exclude/include a single connection.
151
-
152
137
  A thin helper removes the duplication:
153
138
 
154
139
  ```ts
155
140
  async function publishEvent<K extends keyof EventHubTopics>(
156
- hub: EventHubService<EventHubTopics>,
157
- topic: K,
158
- data: EventHubTopics[K]
141
+ hub: EventHubService<EventHubTopics>, topic: K, data: EventHubTopics[K]
159
142
  ) {
160
143
  return hub.publish(topic, null, { topic, data })
161
144
  }
162
-
163
- // usage:
164
- await publishEvent(eventHub, 'todo-created', { todo })
145
+ // usage: await publishEvent(eventHub, 'todo-created', { todo })
165
146
  ```
166
147
 
167
148
  ## 5. Wire it up — share fetch with PikkuRPC
168
149
 
169
- `PikkuRealtime` mirrors `PikkuRPC`: it wraps the same `PikkuFetch`, so
170
- server URL + auth are configured **once** and shared across HTTP, RPC,
171
- and realtime transports.
150
+ `PikkuRealtime` mirrors `PikkuRPC`: it wraps the same `PikkuFetch`, so server URL +
151
+ auth are configured **once** and shared across HTTP, RPC, and realtime transports.
172
152
 
173
153
  ```tsx
174
154
  import { createPikku, PikkuProvider } from '@pikku/react'
@@ -185,9 +165,7 @@ const pikku = createPikku(
185
165
  // pikku.fetch / pikku.rpc / pikku.realtime — all share the same fetch.
186
166
 
187
167
  createRoot(document.getElementById('root')!).render(
188
- <PikkuProvider pikku={pikku}>
189
- <App />
190
- </PikkuProvider>
168
+ <PikkuProvider pikku={pikku}><App /></PikkuProvider>
191
169
  )
192
170
  ```
193
171
 
@@ -200,64 +178,38 @@ realtime.setPikkuFetch(pikku.fetch) // inherits serverUrl + auth
200
178
 
201
179
  ## 6. Subscribe from React
202
180
 
181
+ Subscribe inside `useEffect` (never the render path, or you create a subscription
182
+ per render). `subscribe` returns an unsubscribe function; SSE's `subscribeToTopic`
183
+ returns a handle with `close()`:
184
+
203
185
  ```tsx
204
186
  import { useEffect, useState } from 'react'
205
187
 
206
188
  function TodoList() {
207
- const { realtime } = usePikku() // assuming you expose a hook over your context
189
+ const { realtime } = usePikku() // a hook over your context
208
190
  const [todos, setTodos] = useState<Todo[]>([])
209
191
 
210
192
  useEffect(() => {
211
- const off = realtime.subscribe('todo-created', ({ todo }) => {
212
- setTodos((prev) => [...prev, todo])
213
- })
193
+ // WebSocket multi-topic:
194
+ const off = realtime.subscribe('todo-created', ({ todo }) =>
195
+ setTodos((prev) => [...prev, todo]))
214
196
  return off
197
+
198
+ // Single-topic SSE (auto-cleanup on close) instead:
199
+ // const sub = realtime.subscribeToTopic('todo-created', ({ todo }) =>
200
+ // setTodos((prev) => [...prev, todo]))
201
+ // return () => sub.close()
215
202
  }, [realtime])
216
203
 
217
- return (
218
- <ul>
219
- {todos.map((t) => (
220
- <li key={t.id}>{t.title}</li>
221
- ))}
222
- </ul>
223
- )
204
+ return <ul>{todos.map((t) => <li key={t.id}>{t.title}</li>)}</ul>
224
205
  }
225
206
  ```
226
207
 
227
- Single-topic SSE (auto-cleanup on close):
228
-
229
- ```tsx
230
- useEffect(() => {
231
- const sub = realtime.subscribeToTopic('todo-created', ({ todo }) => {
232
- setTodos((prev) => [...prev, todo])
233
- })
234
- return () => sub.close()
235
- }, [realtime])
236
- ```
237
-
238
- ## Subscribing to other SSE / WebSocket routes
239
-
240
- Same client also handles generic SSE + channel routes — use the path,
241
- the base URL is inherited from PikkuFetch:
242
-
243
- ```ts
244
- // Any sse: true HTTP route
245
- const sub = realtime.subscribeToSSE<{ progress: number }>(
246
- `/workflow-run/${runId}/stream`,
247
- (event) => setProgress(event.progress)
248
- )
249
- // later: sub.close()
250
-
251
- // Any wireChannel — open a raw socket, wrap in PikkuWebSocket for typed I/O
252
- const ws = realtime.connectToChannel('/ws/kanban')
253
- const typed = new PikkuWebSocket<'kanban-live'>(ws)
254
- typed.getRoute('command').subscribe('message', (data) => {
255
- /* ... */
256
- })
257
- ```
208
+ ## Other SSE / WebSocket routes
258
209
 
259
- Discover what's available with `pikku meta clients --json` `channels`
260
- and any HTTP `sse: true` routes are listed there.
210
+ The same client also subscribes to generic `sse: true` routes and raw `wireChannel`
211
+ sockets (`subscribeToSSE`, `connectToChannel`). See
212
+ [references/other-routes.md](references/other-routes.md).
261
213
 
262
214
  ## When to pick which transport
263
215
 
@@ -268,18 +220,17 @@ and any HTTP `sse: true` routes are listed there.
268
220
  | Bidirectional (client also sends messages) | **PikkuRealtime** |
269
221
  | WebSockets blocked by infra | **subscribeToTopicViaSSE** |
270
222
 
271
- Both auto-clean on the server (the eventHub's `onChannelClosed` hook
272
- unsubscribes all topics for the dead channel id). Don't write manual
273
- cleanup unless you're unsubscribing partway through a session.
223
+ Both auto-clean on the server (the eventHub's `onChannelClosed` hook unsubscribes
224
+ all topics for the dead channel id). Don't write manual cleanup unless you're
225
+ unsubscribing partway through a session.
274
226
 
275
227
  ## What NOT to do
276
228
 
277
- - Don't call `eventHub.publish(topic, ..., rawData)` without the
278
- `{topic, data}` envelope — clients use `topic` to dispatch handlers.
279
- - Don't create your own `/events` channel by hand — `pikku enable events`
280
- already does it correctly with disconnect cleanup.
281
- - Don't subscribe inside the render path — use `useEffect`. Otherwise
282
- you'll create a subscription per render.
283
- - Don't subscribe to topics that don't exist in `EventHubTopics`. The
284
- generated client's types prevent it; if you find yourself reaching for
285
- `as any` to subscribe to a string, declare the topic first.
229
+ - Don't call `eventHub.publish(topic, ..., rawData)` without the `{topic, data}`
230
+ envelope — clients use `topic` to dispatch handlers.
231
+ - Don't create your own `/events` channel by hand — `pikku enable events` already
232
+ does it correctly with disconnect cleanup.
233
+ - Don't subscribe inside the render path — use `useEffect`.
234
+ - Don't subscribe to topics that don't exist in `EventHubTopics`. The generated
235
+ client's types prevent it; if you reach for `as any` to subscribe to a string,
236
+ declare the topic first.
@@ -0,0 +1,23 @@
1
+ # Subscribing to other SSE / WebSocket routes
2
+
3
+ The same `PikkuRealtime` client also handles generic SSE + channel routes (not just
4
+ `/events` topics). Use the path; the base URL is inherited from `PikkuFetch`.
5
+
6
+ ```ts
7
+ // Any `sse: true` HTTP route
8
+ const sub = realtime.subscribeToSSE<{ progress: number }>(
9
+ `/workflow-run/${runId}/stream`,
10
+ (event) => setProgress(event.progress)
11
+ )
12
+ // later: sub.close()
13
+
14
+ // Any wireChannel — open a raw socket, wrap in PikkuWebSocket for typed I/O
15
+ const ws = realtime.connectToChannel('/ws/kanban')
16
+ const typed = new PikkuWebSocket<'kanban-live'>(ws)
17
+ typed.getRoute('command').subscribe('message', (data) => {
18
+ /* ... */
19
+ })
20
+ ```
21
+
22
+ Discover what's available with `pikku meta clients --json` — `channels` and any HTTP
23
+ `sse: true` routes are listed there.