@pikku/cli 0.12.96 → 0.12.99

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 (271) hide show
  1. package/console-app/assets/abnfDiagram-VRR7QNED-CytV-CG1.js +1 -0
  2. package/console-app/assets/arc-C5PvmnaA.js +1 -0
  3. package/console-app/assets/architecture-TIHT7OUA-C1_ScvPX.js +1 -0
  4. package/console-app/assets/architectureDiagram-ZJ3FMSHR-CJ2xb7C-.js +36 -0
  5. package/console-app/assets/array-BifhSqXX.js +1 -0
  6. package/console-app/assets/blockDiagram-677ZJIJ3-CCecrBrk.js +132 -0
  7. package/console-app/assets/c4Diagram-LMCZKHZV-CBnpukvQ.js +10 -0
  8. package/console-app/assets/channel-CwDOkXGI.js +1 -0
  9. package/console-app/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  10. package/console-app/assets/chunk-32BRIVSS-D8qWWZRQ.js +1 -0
  11. package/console-app/assets/chunk-52WLFC77-BEpXHMsp.js +10 -0
  12. package/console-app/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  13. package/console-app/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  14. package/console-app/assets/chunk-C7G6YPKG-DsHUMkOp.js +1 -0
  15. package/console-app/assets/chunk-EX3LRPZG-mM7TjVx9.js +231 -0
  16. package/console-app/assets/chunk-FWX5IMBZ-CndRAn18.js +2 -0
  17. package/console-app/assets/chunk-HOUHSVGY-D1kT8umn.js +1 -0
  18. package/console-app/assets/chunk-ICXQ74PX-CeSaGyro.js +2 -0
  19. package/console-app/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  20. package/console-app/assets/chunk-KEIR6QF5-DNzq6p3w.js +161 -0
  21. package/console-app/assets/chunk-MOJQB5TN-CaZOCHYr.js +88 -0
  22. package/console-app/assets/chunk-OGEWGWER-CnB1CsPt.js +1 -0
  23. package/console-app/assets/chunk-PUDLZKDR-BbGulHJm.js +156 -0
  24. package/console-app/assets/chunk-Q4XR5HBZ-BywwzeeR.js +70 -0
  25. package/console-app/assets/chunk-RYQCIY6F-CV0R1Adv.js +1 -0
  26. package/console-app/assets/chunk-V7JOEXUC-DGFaAWzB.js +206 -0
  27. package/console-app/assets/chunk-VAUOI2AC-DxPUd8Yb.js +1 -0
  28. package/console-app/assets/chunk-VR4S4FIN-D4-UaW_J.js +1 -0
  29. package/console-app/assets/chunk-WYO6CB5R-D_TFN0d9.js +127 -0
  30. package/console-app/assets/chunk-XXDRQBXY-BzVuweA_.js +1 -0
  31. package/console-app/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  32. package/console-app/assets/chunk-ZGVPDNZ5-C6hdkGQb.js +62 -0
  33. package/console-app/assets/chunk-ZIRB5QZD-H-kepumB.js +32 -0
  34. package/console-app/assets/classDiagram-OUVF2IWQ-CTYJkTT0.js +1 -0
  35. package/console-app/assets/classDiagram-v2-EOCWNBFH-CTYJkTT0.js +1 -0
  36. package/console-app/assets/cose-bilkent-JH36ORCC-B6ZPxN6v.js +1 -0
  37. package/console-app/assets/cynefin-VYW2F7L2-D_nmxNz_.js +1 -0
  38. package/console-app/assets/cynefinDiagram-TSTJHNR4-CHy5QN0S.js +62 -0
  39. package/console-app/assets/cytoscape.esm-h6BdjjI9.js +321 -0
  40. package/console-app/assets/dagre-CXRCoUWR.js +1 -0
  41. package/console-app/assets/dagre-VKFMJZFB-DYfukM34.js +4 -0
  42. package/console-app/assets/defaultLocale-C8Fc0cco.js +1 -0
  43. package/console-app/assets/diagram-FQU43EPY-Dgb9TPSB.js +3 -0
  44. package/console-app/assets/diagram-G47NLZAW-CnFNZs9Z.js +24 -0
  45. package/console-app/assets/diagram-NH7WQ7WH-DN7h2DU-.js +24 -0
  46. package/console-app/assets/diagram-OA4YK3LP-RLaQaNtK.js +30 -0
  47. package/console-app/assets/diagram-WEI45ONY-DxHWhVGd.js +41 -0
  48. package/console-app/assets/dist-BaJNIo4I.js +1 -0
  49. package/console-app/assets/ebnfDiagram-CCIWWBDH-UN3Z81-l.js +1 -0
  50. package/console-app/assets/erDiagram-Q63AITRT-C9lGAY3i.js +85 -0
  51. package/console-app/assets/eventmodeling-45OFAUF4-Dc5wNSSK.js +1 -0
  52. package/console-app/assets/flowDiagram-23GEKE2U-zPyGHMi4.js +1 -0
  53. package/console-app/assets/ganttDiagram-NO4QXBWP-CvBjBcdK.js +292 -0
  54. package/console-app/assets/gitGraph-TEB2WS4Q-Cs5Z9jMo.js +1 -0
  55. package/console-app/assets/gitGraphDiagram-IHSO6WYX-B0i_IJ5r.js +106 -0
  56. package/console-app/assets/graphlib-B8gBHxth.js +1 -0
  57. package/console-app/assets/{index-CeQodYfg.js → index-71U8EEj7.js} +155 -153
  58. package/console-app/assets/{index-CyYHTGWZ.css → index-BXMjqLQ5.css} +1 -1
  59. package/console-app/assets/info-DKCQHKI2-DHL0afNl.js +1 -0
  60. package/console-app/assets/infoDiagram-FWYZ7A6U-CBWykodX.js +2 -0
  61. package/console-app/assets/init-D6jRqBbL.js +1 -0
  62. package/console-app/assets/ishikawaDiagram-FXEZZL3T-DM377eW_.js +70 -0
  63. package/console-app/assets/journeyDiagram-5HDEW3XC-BpX_-Cns.js +139 -0
  64. package/console-app/assets/kanban-definition-HUTT4EX6-D3xFsQkO.js +89 -0
  65. package/console-app/assets/katex-Vhh-h91d.js +257 -0
  66. package/console-app/assets/line-CTSKHTE0.js +1 -0
  67. package/console-app/assets/linear-R5GlBvXT.js +1 -0
  68. package/console-app/assets/map-DsCK-0Cs.js +1 -0
  69. package/console-app/assets/mermaid-parser.core-CkHk4BPi.js +7 -0
  70. package/console-app/assets/mermaid.core-CcjGXuV6.js +11 -0
  71. package/console-app/assets/mindmap-definition-LN4V7U3C-CtolazqQ.js +96 -0
  72. package/console-app/assets/ordinal-hYBb2elL.js +1 -0
  73. package/console-app/assets/packet-7NZHBO7P-BxSOj_Ny.js +1 -0
  74. package/console-app/assets/path-BWPyau1x.js +1 -0
  75. package/console-app/assets/pegDiagram-2B236MQR-BNsMtxsM.js +1 -0
  76. package/console-app/assets/pie-RZYD4A2V-BbkKQBA5.js +1 -0
  77. package/console-app/assets/pieDiagram-ENE6RG2P-BAZLIz2f.js +39 -0
  78. package/console-app/assets/quadrantDiagram-ABIIQ3AL-Dpvn-1Fs.js +7 -0
  79. package/console-app/assets/radar-I7S5WNFK-B-uKXIAH.js +1 -0
  80. package/console-app/assets/railroad-3IZDKUUU-BHXXK04t.js +1 -0
  81. package/console-app/assets/railroad-abnf-AHOZXSZD-tXSQaBvY.js +1 -0
  82. package/console-app/assets/railroad-ebnf-EBAXGLYW-DG3aohR0.js +1 -0
  83. package/console-app/assets/railroad-peg-LSFZ7HO6-DY_gBA-x.js +1 -0
  84. package/console-app/assets/railroadDiagram-RFXS5EU6-DfUApEQj.js +1 -0
  85. package/console-app/assets/requirementDiagram-TGXJPOKE-B2zX0jqo.js +84 -0
  86. package/console-app/assets/rough.esm-CSKSodPl.js +1 -0
  87. package/console-app/assets/sankeyDiagram-HTMAVEWB-CbQ2zc7z.js +40 -0
  88. package/console-app/assets/sequenceDiagram-DBY2YBRQ-BLT8PXI_.js +162 -0
  89. package/console-app/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  90. package/console-app/assets/src-BLuPUFWW.js +1 -0
  91. package/console-app/assets/stateDiagram-2N3HPSRC-BvEyVp85.js +1 -0
  92. package/console-app/assets/stateDiagram-v2-6OUMAXLB-RGKS9iU4.js +1 -0
  93. package/console-app/assets/swimlanes-5IMT3BWC-1AZ459s6.js +2 -0
  94. package/console-app/assets/swimlanesDiagram-G3AALYLV-Ck_0-rfN.js +8 -0
  95. package/console-app/assets/timeline-definition-FHXFAJF6-dLuvH4s2.js +120 -0
  96. package/console-app/assets/treeView-QDETBFTQ-xL2msjo2.js +1 -0
  97. package/console-app/assets/treemap-6X3UGDF4-C98ichVP.js +1 -0
  98. package/console-app/assets/vennDiagram-L72KCM5P-HbUmidhv.js +34 -0
  99. package/console-app/assets/wardley-OPB4EBWU-C4gJS-m2.js +1 -0
  100. package/console-app/assets/wardleyDiagram-EHGQE667-B7b-LB02.js +78 -0
  101. package/console-app/assets/xychartDiagram-FW5EYKEG-Cm03zUGy.js +7 -0
  102. package/console-app/index.html +2 -2
  103. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  104. package/dist/.pikku/auth/auth.types.d.ts +1 -1
  105. package/dist/.pikku/auth/auth.types.js +1 -1
  106. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  107. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  108. package/dist/.pikku/cli/pikku-cli-channel.js +1 -6
  109. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  110. package/dist/.pikku/cli/pikku-cli-client.gen.js +36 -9
  111. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  112. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  113. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  114. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  115. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  116. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +7 -8
  117. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  118. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  119. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  120. package/dist/.pikku/cli/pikku-cli.gen.js +18 -2
  121. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  122. package/dist/.pikku/function/pikku-function-types.gen.d.ts +12 -6
  123. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  124. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  125. package/dist/.pikku/function/pikku-functions-meta.gen.json +39 -30
  126. package/dist/.pikku/function/pikku-functions.gen.js +3 -3
  127. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  128. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  129. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  130. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  131. package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
  132. package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
  133. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  134. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  135. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  136. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  137. package/dist/.pikku/pikku-services.gen.d.ts +2 -1
  138. package/dist/.pikku/pikku-services.gen.js +1 -0
  139. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  140. package/dist/.pikku/pikku-types.gen.js +1 -1
  141. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  142. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  143. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  144. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  145. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  146. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  147. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +1 -1
  148. package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
  149. package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
  150. package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
  151. package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
  152. package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
  153. package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
  154. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  155. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  156. package/dist/.pikku/schemas/register.gen.js +3 -3
  157. package/dist/.pikku/schemas/schemas/DbResetInput.schema.json +1 -1
  158. package/dist/.pikku/schemas/schemas/{DbSeedInput.schema.json → PikkuVirtualUserFunctionsOutput.schema.json} +1 -1
  159. package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
  160. package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
  161. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  162. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  163. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  164. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  165. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  166. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  167. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  168. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  169. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  170. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  171. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  172. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  173. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  174. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +20 -14
  175. package/dist/.pikku/workflow/pikku-personas.gen.js +1 -1
  176. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +6 -6
  177. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  178. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  179. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  180. package/dist/bin/pikku-bin.mjs +2 -2
  181. package/dist/src/cli.wiring.js +8 -7
  182. package/dist/src/fabric/functions/validate.function.js +76 -176
  183. package/dist/src/functions/commands/all.d.ts +1 -1
  184. package/dist/src/functions/commands/bootstrap.d.ts +1 -1
  185. package/dist/src/functions/commands/db-audit.js +1 -1
  186. package/dist/src/functions/commands/db-baseline.js +1 -1
  187. package/dist/src/functions/commands/db-check.js +6 -5
  188. package/dist/src/functions/commands/db-codegen.js +1 -1
  189. package/dist/src/functions/commands/db-generate.js +1 -1
  190. package/dist/src/functions/commands/db-migrate.js +1 -1
  191. package/dist/src/functions/commands/db-reset.d.ts +15 -1
  192. package/dist/src/functions/commands/db-reset.js +18 -6
  193. package/dist/src/functions/commands/db-shared.d.ts +14 -0
  194. package/dist/src/functions/commands/deploy-info.d.ts +1 -1
  195. package/dist/src/functions/commands/dev.js +1 -1
  196. package/dist/src/functions/commands/enable.d.ts +8 -8
  197. package/dist/src/functions/commands/new-addon.js +2 -2
  198. package/dist/src/functions/commands/persona-sync.d.ts +1 -1
  199. package/dist/src/functions/commands/persona-sync.js +1 -1
  200. package/dist/src/functions/commands/persona.js +16 -18
  201. package/dist/src/functions/commands/scenario-ladder.js +1 -1
  202. package/dist/src/functions/commands/scenario.js +4 -2
  203. package/dist/src/functions/commands/scopes-shared.d.ts +4 -0
  204. package/dist/src/functions/commands/scopes-shared.js +1 -1
  205. package/dist/src/functions/commands/serve.js +1 -1
  206. package/dist/src/functions/commands/versions-check.js +3 -3
  207. package/dist/src/functions/db/annotation-parser.d.ts +14 -0
  208. package/dist/src/functions/db/annotation-parser.js +50 -2
  209. package/dist/src/functions/db/better-auth-schema.js +2 -1
  210. package/dist/src/functions/db/db-codegen.d.ts +12 -0
  211. package/dist/src/functions/db/db-codegen.js +149 -16
  212. package/dist/src/functions/db/local-db.d.ts +87 -6
  213. package/dist/src/functions/db/local-db.js +202 -35
  214. package/dist/src/functions/db/sqlite/dev-seed.d.ts +12 -0
  215. package/dist/src/functions/db/sqlite/dev-seed.js +23 -0
  216. package/dist/src/functions/db/sqlite/sqlite-runtime-bun.js +1 -1
  217. package/dist/src/functions/validate/bootstrap-checks.d.ts +19 -0
  218. package/dist/src/functions/validate/bootstrap-checks.js +90 -0
  219. package/dist/src/functions/validate/persona-checks.d.ts +24 -0
  220. package/dist/src/functions/validate/persona-checks.js +136 -0
  221. package/dist/src/functions/validate/scenario-file-checks.d.ts +17 -0
  222. package/dist/src/functions/validate/scenario-file-checks.js +123 -0
  223. package/dist/src/functions/validate/shared-checks.d.ts +59 -0
  224. package/dist/src/functions/validate/shared-checks.js +311 -0
  225. package/dist/src/functions/validate/workspace-validate.d.ts +1 -2
  226. package/dist/src/functions/validate/workspace-validate.js +4 -196
  227. package/dist/src/functions/wirings/auth/serialize-auth-gen.js +16 -1
  228. package/dist/src/functions/wirings/auth/serialize-auth-types.d.ts +3 -1
  229. package/dist/src/functions/wirings/auth/serialize-auth-types.js +3 -1
  230. package/dist/src/functions/wirings/channels/pikku-channels.d.ts +1 -1
  231. package/dist/src/functions/wirings/channels/serialize-typed-channel-map.js +10 -2
  232. package/dist/src/functions/wirings/cli/pikku-command-cli-entry.js +9 -4
  233. package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +32 -10
  234. package/dist/src/functions/wirings/cli/serialize-cli-entrypoint-guard.d.ts +12 -0
  235. package/dist/src/functions/wirings/cli/serialize-cli-entrypoint-guard.js +28 -0
  236. package/dist/src/functions/wirings/cli/serialize-local-cli-bootstrap.js +4 -1
  237. package/dist/src/functions/wirings/console/serialize-console-functions.js +1 -1
  238. package/dist/src/functions/wirings/functions/serialize-addon-types.js +1 -1
  239. package/dist/src/functions/wirings/functions/serialize-function-types.js +19 -5
  240. package/dist/src/functions/wirings/package/pikku-command-package-types.d.ts +3 -3
  241. package/dist/src/functions/wirings/personas/personas-secrets-file.d.ts +8 -0
  242. package/dist/src/functions/wirings/personas/personas-secrets-file.js +9 -0
  243. package/dist/src/functions/wirings/personas/pikku-command-personas.js +14 -0
  244. package/dist/src/functions/wirings/personas/serialize-personas-secrets.d.ts +16 -0
  245. package/dist/src/functions/wirings/personas/serialize-personas-secrets.js +34 -0
  246. package/dist/src/functions/wirings/queue/serialize-queue-map.js +2 -1
  247. package/dist/src/functions/wirings/queue/serialize-queue-wrapper.js +2 -1
  248. package/dist/src/functions/wirings/virtual-user/pikku-command-virtual-user-functions.d.ts +1 -0
  249. package/dist/src/functions/wirings/virtual-user/pikku-command-virtual-user-functions.js +42 -0
  250. package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.d.ts +28 -0
  251. package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.js +439 -0
  252. package/dist/src/functions/wirings/workflow/serialize-scenario-step-map.js +2 -2
  253. package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +5 -11
  254. package/dist/src/functions/workflows/all.workflow.js +49 -16
  255. package/dist/src/server/bun-server-runner.d.ts +2 -2
  256. package/dist/src/server/bun-server-runner.js +5 -1
  257. package/dist/src/services/cli-logger.service.d.ts +28 -16
  258. package/dist/src/services/cli-logger.service.js +25 -16
  259. package/dist/src/services.js +8 -0
  260. package/dist/src/utils/file-import-path.js +9 -0
  261. package/dist/src/utils/pikku-cli-config.js +7 -0
  262. package/dist/src/utils/resolve-personas.d.ts +4 -9
  263. package/dist/src/utils/resolve-personas.js +4 -15
  264. package/dist/tsconfig.tsbuildinfo +1 -1
  265. package/package.json +11 -11
  266. package/dist/.pikku/schemas/schemas/BootstrapInput.schema.json +0 -1
  267. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +0 -1
  268. package/dist/src/functions/commands/db-seed.d.ts +0 -1
  269. package/dist/src/functions/commands/db-seed.js +0 -24
  270. package/dist/src/functions/db/sqlite/seed.d.ts +0 -11
  271. package/dist/src/functions/db/sqlite/seed.js +0 -22
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ export { readJsonSafe, readTextSafe } from './shared-checks.js';
2
3
  export declare const FindingSchema: z.ZodObject<{
3
4
  id: z.ZodString;
4
5
  severity: z.ZodEnum<{
@@ -28,7 +29,5 @@ export declare const WorkspaceValidateOutput: z.ZodObject<{
28
29
  }, z.core.$strip>>;
29
30
  }, z.core.$strip>;
30
31
  export declare function findProjectRoot(startDir: string): Promise<string>;
31
- export declare function readJsonSafe<T>(path: string): Promise<T | null>;
32
- export declare function readTextSafe(path: string): Promise<string | null>;
33
32
  export declare function runWorkspaceValidate(startDir?: string): Promise<z.infer<typeof WorkspaceValidateOutput>>;
34
33
  export declare const renderWorkspaceValidate: (_s: unknown, { ok, root, findings }: z.infer<typeof WorkspaceValidateOutput>) => void;
@@ -1,8 +1,10 @@
1
1
  import { existsSync } from 'node:fs';
2
- import { readFile, readdir } from 'node:fs/promises';
2
+ import { readFile } from 'node:fs/promises';
3
3
  import { dirname, join } from 'node:path';
4
4
  import { z } from 'zod';
5
5
  import { added, changed, dim, removed } from '../../fabric/lib/output.js';
6
+ import { runSharedProjectChecks } from './shared-checks.js';
7
+ export { readJsonSafe, readTextSafe } from './shared-checks.js';
6
8
  export const FindingSchema = z.object({
7
9
  id: z.string(),
8
10
  severity: z.enum(['error', 'warn', 'info']),
@@ -35,203 +37,9 @@ export async function findProjectRoot(startDir) {
35
37
  dir = parent;
36
38
  }
37
39
  }
38
- export async function readJsonSafe(path) {
39
- if (!existsSync(path))
40
- return null;
41
- try {
42
- return JSON.parse(await readFile(path, 'utf8'));
43
- }
44
- catch (err) {
45
- const message = err instanceof Error ? err.message : String(err);
46
- throw new Error(`Invalid JSON in ${path}: ${message}`);
47
- }
48
- }
49
- export async function readTextSafe(path) {
50
- if (!existsSync(path))
51
- return null;
52
- try {
53
- return await readFile(path, 'utf8');
54
- }
55
- catch {
56
- return null;
57
- }
58
- }
59
- async function hasAuthSessionMiddleware(fnDir) {
60
- const metaPath = join(fnDir, '.pikku', 'middleware', 'pikku-middleware-groups-meta.gen.json');
61
- const meta = await readJsonSafe(metaPath);
62
- if (!meta?.instances)
63
- return false;
64
- return Object.values(meta.instances).some((instance) => instance.definitionId === 'betterAuthSession');
65
- }
66
- function migrationCreatesTable(sql, tableName) {
67
- const escapedTable = tableName.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
68
- const re = new RegExp(`\\bcreate\\s+table\\s+(?:if\\s+not\\s+exists\\s+)?["'\`]?${escapedTable}["'\`]?\\b`, 'i');
69
- return re.test(sql);
70
- }
71
40
  export async function runWorkspaceValidate(startDir = process.cwd()) {
72
41
  const root = await findProjectRoot(startDir);
73
- const findings = [];
74
- const e = (id, message, path, fixHint) => {
75
- findings.push({ id, severity: 'error', message, path, fixHint });
76
- };
77
- const w = (id, message, path, fixHint) => {
78
- findings.push({ id, severity: 'warn', message, path, fixHint });
79
- };
80
- const info = (id, message, path, fixHint) => {
81
- findings.push({ id, severity: 'info', message, path, fixHint });
82
- };
83
- const pikkuConfigPath = join(root, 'pikku.config.json');
84
- const pikkuConfig = await readJsonSafe(pikkuConfigPath);
85
- if (!pikkuConfig) {
86
- e('pikku-config-missing', 'pikku.config.json not found at project root', pikkuConfigPath, 'Create pikku.config.json with srcDirectories pointing to packages/functions/src, outDir, and clientFiles');
87
- }
88
- else {
89
- if (!pikkuConfig.srcDirectories) {
90
- e('pikku-config-no-src-dirs', 'pikku.config.json missing "srcDirectories"', pikkuConfigPath, 'Add "srcDirectories": ["packages/functions/src"] to pikku.config.json');
91
- }
92
- if (!pikkuConfig.outDir) {
93
- e('pikku-config-no-out-dir', 'pikku.config.json missing "outDir"', pikkuConfigPath, 'Add "outDir": "packages/functions/.pikku" to pikku.config.json');
94
- }
95
- if (!pikkuConfig.clientFiles) {
96
- info('pikku-config-no-client-files', 'pikku.config.json missing "clientFiles" — generated RPC client files and React Query hooks will not be written', pikkuConfigPath, 'Add clientFiles.rpcMapDeclarationFile and clientFiles.reactQueryFile pointing to packages/functions-sdk/src/pikku/ (for example: rpc-map.gen.d.ts and api.gen.ts)');
97
- }
98
- const scaffold = pikkuConfig.scaffold;
99
- if (!scaffold?.console) {
100
- e('pikku-config-no-console-scaffold', 'pikku.config.json missing "scaffold.console" — Fabric cannot introspect the running app (console:getFunctionsMeta and friends 404), so the sandbox builder shows no functions', pikkuConfigPath, 'Add "console": true under "scaffold" in pikku.config.json — the console requires an authenticated session, so Better Auth must be set up (see the pikku-better-auth skill)');
101
- }
102
- }
103
- const rootPkgPath = join(root, 'package.json');
104
- const rootPkg = await readJsonSafe(rootPkgPath);
105
- if (!rootPkg) {
106
- e('root-package-missing', 'root package.json not found', rootPkgPath, 'Create a root package.json with workspaces: {"workspaces": ["packages/*", "apps/*"]}');
107
- }
108
- else {
109
- if (!rootPkg.workspaces) {
110
- w('root-package-no-workspaces', 'root package.json missing "workspaces"', rootPkgPath, 'Add "workspaces": ["packages/*", "apps/*"] to enable yarn workspaces');
111
- }
112
- const allDeps = {
113
- ...rootPkg.dependencies,
114
- ...rootPkg.devDependencies,
115
- };
116
- if (!allDeps['@pikku/core']) {
117
- e('missing-core', '@pikku/core not in dependencies', rootPkgPath, 'Add "@pikku/core" to dependencies');
118
- }
119
- for (const [pkg, spec] of Object.entries(allDeps)) {
120
- if (typeof spec !== 'string' || !spec.startsWith('file:'))
121
- continue;
122
- const relPath = spec.slice(5);
123
- if (!relPath.includes('vendor'))
124
- continue;
125
- const absPath = join(root, relPath);
126
- if (!existsSync(absPath)) {
127
- w(`vendor-missing-${pkg.replace(/[@/]/g, '-')}`, `Vendor file missing for ${pkg}: ${relPath}`, absPath, `Restore or replace the missing vendor package at ${relPath}`);
128
- }
129
- }
130
- }
131
- const fnDir = join(root, 'packages', 'functions');
132
- if (!existsSync(fnDir)) {
133
- e('functions-pkg-missing', 'packages/functions/ directory not found', fnDir, 'Create packages/functions/ as a workspace containing src/, tests/, config.ts, and any local db assets you use');
134
- }
135
- else {
136
- const fnPkgPath = join(fnDir, 'package.json');
137
- const fnPkg = await readJsonSafe(fnPkgPath);
138
- if (!fnPkg) {
139
- e('functions-package-json-missing', 'packages/functions/package.json not found', fnPkgPath, 'Create packages/functions/package.json and declare the workspace package');
140
- }
141
- else if (fnPkg.type !== 'module') {
142
- w('functions-pkg-no-esm', 'packages/functions/package.json is missing "type": "module"', fnPkgPath, 'Add "type": "module" to packages/functions/package.json');
143
- }
144
- // zod v4 must be installed in the functions package: pikku's generated
145
- // schemas and the auth scaffold (auth-secrets.gen.ts) both `import { z }
146
- // from 'zod'`, so a missing/old zod fails codegen (PKU489) or type-checks.
147
- if (fnPkg) {
148
- const fnDeps = { ...fnPkg.dependencies, ...fnPkg.devDependencies };
149
- const zodRange = fnDeps.zod;
150
- const zodMajor = zodRange?.match(/(\d+)/)?.[1];
151
- if (!zodRange) {
152
- e('functions-missing-zod', 'packages/functions/package.json does not declare "zod" — pikku schemas and the generated auth scaffold import it', fnPkgPath, 'Add "zod": "^4" to packages/functions dependencies');
153
- }
154
- else if (zodMajor !== '4') {
155
- e('functions-zod-not-v4', `packages/functions requires zod v4 but found "${zodRange}"`, fnPkgPath, 'Set "zod": "^4" in packages/functions dependencies');
156
- }
157
- }
158
- const servicesPath = join(fnDir, 'src', 'services.ts');
159
- const servicesText = await readTextSafe(servicesPath);
160
- if (!servicesText) {
161
- w('services-missing', 'packages/functions/src/services.ts not found', servicesPath, 'Create services.ts and export your service factory for the workspace');
162
- }
163
- const authEnabled = await hasAuthSessionMiddleware(fnDir);
164
- const configText = await readTextSafe(join(fnDir, 'src', 'config.ts'));
165
- const hasConfiguredDevDb = /sqliteDb/.test(configText ?? '');
166
- const hasPostgresUrl = /postgresUrl/.test(configText ?? '');
167
- const migrationsDir = hasPostgresUrl
168
- ? join(fnDir, 'db', 'postgres')
169
- : join(fnDir, 'db', 'sqlite');
170
- let createsAppUser = false;
171
- let createsAuthVerificationToken = false;
172
- if (existsSync(migrationsDir)) {
173
- try {
174
- const files = (await readdir(migrationsDir))
175
- .filter((f) => f.endsWith('.sql'))
176
- .sort();
177
- const nums = [];
178
- for (const f of files) {
179
- const m = f.match(/^(\d+)/);
180
- if (m)
181
- nums.push(parseInt(m[1], 10));
182
- }
183
- for (let idx = 1; idx < nums.length; idx++) {
184
- if (nums[idx] !== nums[idx - 1] + 1) {
185
- const missing = `${nums[idx - 1] + 1}..${nums[idx] - 1}`;
186
- e('migration-gap', `Migration numbering gap: IDs ${missing} are missing`, migrationsDir, 'Migrations must be consecutive. Add the missing .sql file or renumber if not yet applied.');
187
- break;
188
- }
189
- }
190
- for (const f of files) {
191
- const sql = await readTextSafe(join(migrationsDir, f));
192
- if (!sql)
193
- continue;
194
- createsAppUser ||= migrationCreatesTable(sql, 'app_user');
195
- createsAuthVerificationToken ||= migrationCreatesTable(sql, 'auth_verification_token');
196
- }
197
- }
198
- catch {
199
- // readdir failure — skip
200
- }
201
- }
202
- if (authEnabled && !hasConfiguredDevDb) {
203
- e('auth-dev-db-missing', 'Auth middleware is registered, but createConfig is missing sqliteDb so local auth schema validation and db migrate cannot run', pikkuConfigPath, 'Add sqliteDb to createConfig so `pikku db migrate` can create and validate the local auth schema');
204
- }
205
- if (authEnabled && !createsAppUser) {
206
- e('auth-schema-missing-app-user', 'Auth middleware is registered, but no SQL migration creates the app_user table', migrationsDir, 'Add a migration that creates app_user before enabling auth');
207
- }
208
- if (authEnabled && !createsAuthVerificationToken) {
209
- e('auth-schema-missing-verification-token', 'Auth middleware is registered, but no SQL migration creates the auth_verification_token table', migrationsDir, 'Add a migration that creates auth_verification_token before enabling auth');
210
- }
211
- const dbTypesPath = join(fnDir, 'src', 'types', 'db.types.ts');
212
- const dbTypesText = await readTextSafe(dbTypesPath);
213
- if (dbTypesText) {
214
- const isReexport = dbTypesText.includes('.pikku/db/schema') ||
215
- dbTypesText.includes('.pikku\\db\\schema');
216
- const hasInlineTypes = /(?:^|\n)\s*(?:export\s+)?(?:interface\s+\w|type\s+\w+\s*=)/.test(dbTypesText);
217
- if (hasInlineTypes && !isReexport) {
218
- w('db-types-hand-edited', 'src/types/db.types.ts contains inline type definitions — it should only re-export from .pikku', dbTypesPath, "Replace the file with a single line: export type { DB } from '../../.pikku/db/schema.gen.js' then regenerate");
219
- }
220
- }
221
- if (!existsSync(join(fnDir, 'src', 'functions'))) {
222
- info('functions-dir-missing', 'packages/functions/src/functions/ not found', join(fnDir, 'src', 'functions'), 'Create src/functions/ to hold pikkuSessionlessFunc definitions');
223
- }
224
- if (!existsSync(join(fnDir, 'src', 'wirings'))) {
225
- info('wirings-dir-missing', 'packages/functions/src/wirings/ not found', join(fnDir, 'src', 'wirings'), 'Create src/wirings/ for transport bindings such as *.http.ts or *.queue.ts');
226
- }
227
- if (!existsSync(join(fnDir, 'src', 'config.ts'))) {
228
- info('config-missing', 'packages/functions/src/config.ts not found', join(fnDir, 'src', 'config.ts'), 'Create src/config.ts and export your workspace config factory');
229
- }
230
- }
231
- const sdkDir = join(root, 'packages', 'functions-sdk');
232
- if (!existsSync(sdkDir)) {
233
- info('functions-sdk-missing', 'packages/functions-sdk/ not found — generated RPC client and React Query hooks will not be available', sdkDir, 'Create packages/functions-sdk/ as a workspace with src/pikku/ as the generated output root; point clientFiles.rpcMapDeclarationFile and clientFiles.reactQueryFile there');
234
- }
42
+ const { findings } = await runSharedProjectChecks(root);
235
43
  const ok = !findings.some((f) => f.severity === 'error');
236
44
  return { ok, root, findings };
237
45
  }
@@ -40,11 +40,26 @@ function variableSchemaName(name, field) {
40
40
  // addHTTPMiddleware('*') call as the session middleware: the inspector keys
41
41
  // route-middleware groups by pattern, so a second '*' registration from another
42
42
  // file would silently displace this one in deployed units.
43
+ //
44
+ // The session carries the two scope roots the console addon gates itself on.
45
+ // Without them this token authenticates but authorizes nothing: `wireAddon`
46
+ // gates the whole addon on `admin`, so every console:* RPC — reads included —
47
+ // answers MissingScopeError, and an external console can reach the deployment
48
+ // while being unable to do a single thing in it.
49
+ //
50
+ // Roots rather than a wildcard: a parent grant satisfies its children, so
51
+ // `admin` covers `admin:*` and `pikku` covers `pikku:scopes:*`/`pikku:audit:*`,
52
+ // which is every scope the console's own functions require. A `*` would also
53
+ // hand the token every scope the HOST app declares, which is authority the
54
+ // console never asks for.
43
55
  const consoleTokenMiddlewareLines = () => [
44
56
  ` authBearer({`,
45
57
  ` token: {`,
46
58
  ` secretId: 'PIKKU_CONSOLE_TOKEN',`,
47
- ` userSession: { userId: 'pikku-console-token' },`,
59
+ ` userSession: {`,
60
+ ` userId: 'pikku-console-token',`,
61
+ ` scopes: ['admin', 'pikku'],`,
62
+ ` },`,
48
63
  ` },`,
49
64
  ` }),`,
50
65
  ];
@@ -16,7 +16,9 @@
16
16
  * them at runtime — the same treatment addon services get from
17
17
  * `pikkuAddonServices`. That gives the factory typed, map-aware access:
18
18
  *
19
- * socialProviders: { github: await secrets.getSecret('GITHUB_OAUTH') }
19
+ * socialProviders: {
20
+ * github: (await secrets.getSecret('GITHUB_OAUTH')).reveal(),
21
+ * }
20
22
  *
21
23
  * with no inline `getSecrets<{ ... }>()` generic, because the secret types flow
22
24
  * from the generated `CredentialsMap`.
@@ -17,7 +17,9 @@ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
17
17
  * them at runtime — the same treatment addon services get from
18
18
  * `pikkuAddonServices`. That gives the factory typed, map-aware access:
19
19
  *
20
- * socialProviders: { github: await secrets.getSecret('GITHUB_OAUTH') }
20
+ * socialProviders: {
21
+ * github: (await secrets.getSecret('GITHUB_OAUTH')).reveal(),
22
+ * }
21
23
  *
22
24
  * with no inline `getSecrets<{ ... }>()` generic, because the secret types flow
23
25
  * from the generated `CredentialsMap`.
@@ -1 +1 @@
1
- export declare const pikkuChannels: import("#pikku").PikkuFunctionConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
1
+ export declare const pikkuChannels: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -109,15 +109,23 @@ function generateChannels(logger, typesMap, functionsMeta, addonFunctions, chann
109
109
  }
110
110
  }
111
111
  }
112
+ /**
113
+ * A route or message key that is not a bare identifier has to be quoted to be
114
+ * a legal property name. Channel routes are author-chosen strings and a CLI
115
+ * channel's are command ids, where `app-smoke` and `registry.search` are the
116
+ * norm — unquoted, each one ends the property early and the whole map fails
117
+ * to parse. Quoted only when it has to be, so existing output is unchanged.
118
+ */
119
+ const propertyKey = (key) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${key}'`;
112
120
  let routesStr = 'export type ChannelsMap = {\n';
113
121
  for (const [channelPath, { routes, message }] of Object.entries(channelsObject)) {
114
122
  routesStr += ` readonly '${channelPath}': {\n`;
115
123
  // Add `routes` object
116
124
  routesStr += ` readonly routes: {\n`;
117
125
  for (const [key, methods] of Object.entries(routes)) {
118
- routesStr += ` readonly ${key}: {\n`;
126
+ routesStr += ` readonly ${propertyKey(key)}: {\n`;
119
127
  for (const [method, handler] of Object.entries(methods)) {
120
- routesStr += ` readonly ${method}: ChannelHandler<${formatTypeArray(handler.inputTypes) || 'void'}, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`;
128
+ routesStr += ` readonly ${propertyKey(method)}: ChannelHandler<${formatTypeArray(handler.inputTypes) || 'void'}, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`;
121
129
  }
122
130
  routesStr += ' },\n';
123
131
  }
@@ -64,15 +64,20 @@ export const pikkuCLIEntry = pikkuSessionlessFunc({
64
64
  // Generate client code if clientPath is provided
65
65
  if (channelClientPath) {
66
66
  const channelClientFile = join(config.rootDir, channelClientPath);
67
- // Validate that renderers don't depend on services (client-side renderers can't access server services)
67
+ // A renderer for a CLI-over-channel program runs on the client, where
68
+ // there is no service container to resolve from — the only thing the
69
+ // runtime can hand it is a logger. Anything else it destructures
70
+ // would be undefined at runtime, so it fails generation instead.
68
71
  const rendererNames = collectRendererNames(programMeta);
69
72
  const problematicRenderers = [];
70
73
  for (const rendererName of rendererNames) {
71
74
  const rendererMeta = visitState.cli.meta.renderers[rendererName];
72
- if (rendererMeta?.services?.services?.length > 0) {
75
+ const services = rendererMeta?.services?.services ?? [];
76
+ const unavailable = services.filter((name) => name !== 'logger');
77
+ if (unavailable.length > 0) {
73
78
  problematicRenderers.push({
74
79
  name: rendererName,
75
- services: rendererMeta.services.services,
80
+ services: unavailable,
76
81
  });
77
82
  }
78
83
  }
@@ -81,7 +86,7 @@ export const pikkuCLIEntry = pikkuSessionlessFunc({
81
86
  const details = problematicRenderers
82
87
  .map((r) => ` - ${r.name} depends on: ${r.services.join(', ')}`)
83
88
  .join('\n');
84
- logger.critical(ErrorCode.CLI_CLIENTSIDE_RENDERER_HAS_SERVICES, `Cannot generate CLI channel client for '${programName}': renderers cannot depend on services (client-side execution)\n${details}\n\nRenderers used in CLI-over-channel must be service-free since they execute on the client.`);
89
+ logger.critical(ErrorCode.CLI_CLIENTSIDE_RENDERER_HAS_SERVICES, `Cannot generate CLI channel client for '${programName}': a renderer reached for a service that does not exist on the client\n${details}\n\nRenderers in a CLI-over-channel program run on the client side of the socket, where the only available service is 'logger'.`);
85
90
  // Delete existing client file if it exists
86
91
  if (existsSync(channelClientFile)) {
87
92
  await rm(channelClientFile);
@@ -1,4 +1,5 @@
1
1
  import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
2
+ import { DIRECT_EXECUTION_GUARD } from './serialize-cli-entrypoint-guard.js';
2
3
  /**
3
4
  * Collect all unique renderer names from CLI metadata (populated by inspector)
4
5
  */
@@ -107,10 +108,11 @@ export function serializeChannelCLIClient(programName, programMeta, clientFile,
107
108
  ? resolveRendererBinding(programMeta.defaultRenderName, renderersMeta)
108
109
  : null;
109
110
  const defaultRendererCode = defaultRendererBinding
110
- ? `,\n defaultRenderer: ${defaultRendererBinding}`
111
+ ? `,\n defaultRenderer: ${defaultRendererBinding} as CorePikkuCLIClientRender<any>`
111
112
  : '';
112
113
  return `
113
114
  import { executeRawCLIViaChannel } from '@pikku/core/cli/channel'
115
+ import type { CorePikkuCLIClientRender } from '@pikku/core/cli/channel'
114
116
  import type { Capabilities } from '@pikku/core/channel'
115
117
  import { CorePikkuWebsocket } from '@pikku/websocket'
116
118
  ${rendererImports}
@@ -136,8 +138,12 @@ export async function ${capitalizedName}CLIClient(
136
138
  // Create Pikku WebSocket wrapper
137
139
  const pikkuWS = new CorePikkuWebsocket(ws)
138
140
 
139
- // Register renderers for CLI commands
140
- const renderers = ${renderersMap}
141
+ // Renderers are declared against this app's \`SingletonServices\`, but on this
142
+ // side of the socket the only service that exists is a logger. The cast is
143
+ // sound because generation refuses to emit this file at all when a renderer
144
+ // reaches for anything else — see CLI_CLIENTSIDE_RENDERER_HAS_SERVICES. It is
145
+ // localised here so \`executeRawCLIViaChannel\` can keep an honest signature.
146
+ const renderers = ${renderersMap} as Record<string, CorePikkuCLIClientRender<any>>
141
147
 
142
148
  return executeRawCLIViaChannel({
143
149
  pikkuWS,
@@ -151,15 +157,17 @@ export async function ${capitalizedName}CLIClient(
151
157
  export default ${capitalizedName}CLIClient
152
158
 
153
159
  // For direct execution (if this file is run directly)
154
- if (import.meta.url === \`file://\${process.argv[1]}\`) {
160
+ ${DIRECT_EXECUTION_GUARD}
161
+
162
+ if (isDirectExecution) {
155
163
  const url = process.env.PIKKU_WS_URL || 'ws://localhost:4002${finalChannelRoute}'
156
164
 
157
165
  // Attach credentials so the channel authenticates like any other pikku client.
158
166
  // A machine API key (PIKKU_API_KEY -> x-api-key) takes precedence; otherwise
159
167
  // the human session token saved by \`pikku login\` (~/.pikku/session.json ->
160
- // Authorization: Bearer) is used. This block only runs under Node (direct
161
- // execution), so reading the session file and using the 'ws' headers option
162
- // is safe the browser WebSocket cannot set custom headers anyway.
168
+ // Authorization: Bearer) is used. This block only runs on a server runtime
169
+ // (direct execution), so reading the session file is safe a browser could
170
+ // neither reach it nor set custom headers on its WebSocket.
163
171
  const headers: Record<string, string> = {}
164
172
  if (process.env.PIKKU_API_KEY) {
165
173
  headers['x-api-key'] = process.env.PIKKU_API_KEY
@@ -186,12 +194,26 @@ if (import.meta.url === \`file://\${process.argv[1]}\`) {
186
194
  }
187
195
  const hasAuth = Object.keys(headers).length > 0
188
196
 
189
- // Custom headers require the Node 'ws' module the global/browser WebSocket
190
- // cannot set them so prefer 'ws' whenever we have credentials to send.
197
+ // Node's global WebSocket reads its second argument as subprotocols and drops
198
+ // custom headers on the floor, so credentials there need the 'ws' module.
199
+ // Bun's honours them natively, and reaching for 'ws' under Bun would load its
200
+ // compatibility shim for nothing. Detected once, the way the CLI picks its
201
+ // dev-server runner.
202
+ const isBun = typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'
203
+
204
+ // Only the header-carrying Bun call needs the cast: the DOM lib types the
205
+ // second argument as subprotocols, which is what Node implements.
206
+ type WebSocketWithHeaders = new (
207
+ url: string,
208
+ options: { headers: Record<string, string> }
209
+ ) => WebSocket
210
+
191
211
  let ws: WebSocket
192
- if (hasAuth || typeof WebSocket === 'undefined') {
212
+ if (!isBun && (hasAuth || typeof WebSocket === 'undefined')) {
193
213
  const wsModule = await import('ws')
194
214
  ws = new wsModule.default(url, { headers }) as unknown as WebSocket
215
+ } else if (hasAuth) {
216
+ ws = new (WebSocket as unknown as WebSocketWithHeaders)(url, { headers })
195
217
  } else {
196
218
  ws = new WebSocket(url)
197
219
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The snippet every generated CLI entrypoint uses to decide whether it is being
3
+ * run or merely imported. It declares `isDirectExecution`; the caller writes the
4
+ * `if`.
5
+ *
6
+ * `import.meta.url === \`file://${process.argv[1]}\`` — the shape this replaces —
7
+ * is false for any CLI invoked through a symlinked bin, because Node reports the
8
+ * symlink in argv and the realpath in the URL, so the block never ran for an
9
+ * installed `node_modules/.bin/<name>`. It also fails on paths the URL has to
10
+ * percent-encode, such as one containing a space.
11
+ */
12
+ export declare const DIRECT_EXECUTION_GUARD = "const isDirectExecution = await (async () => {\n if (typeof import.meta.main === 'boolean') {\n return import.meta.main\n }\n // Node exposes import.meta.main from 24.2; earlier 24.x compares realpaths,\n // which is what it is shorthand for.\n try {\n const { fileURLToPath } = await import('node:url')\n const { realpathSync } = await import('node:fs')\n return (\n process.argv[1] !== undefined &&\n realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)\n )\n } catch {\n return false\n }\n})()";
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The snippet every generated CLI entrypoint uses to decide whether it is being
3
+ * run or merely imported. It declares `isDirectExecution`; the caller writes the
4
+ * `if`.
5
+ *
6
+ * `import.meta.url === \`file://${process.argv[1]}\`` — the shape this replaces —
7
+ * is false for any CLI invoked through a symlinked bin, because Node reports the
8
+ * symlink in argv and the realpath in the URL, so the block never ran for an
9
+ * installed `node_modules/.bin/<name>`. It also fails on paths the URL has to
10
+ * percent-encode, such as one containing a space.
11
+ */
12
+ export const DIRECT_EXECUTION_GUARD = `const isDirectExecution = await (async () => {
13
+ if (typeof import.meta.main === 'boolean') {
14
+ return import.meta.main
15
+ }
16
+ // Node exposes import.meta.main from 24.2; earlier 24.x compares realpaths,
17
+ // which is what it is shorthand for.
18
+ try {
19
+ const { fileURLToPath } = await import('node:url')
20
+ const { realpathSync } = await import('node:fs')
21
+ return (
22
+ process.argv[1] !== undefined &&
23
+ realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)
24
+ )
25
+ } catch {
26
+ return false
27
+ }
28
+ })()`;
@@ -1,4 +1,5 @@
1
1
  import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
2
+ import { DIRECT_EXECUTION_GUARD } from './serialize-cli-entrypoint-guard.js';
2
3
  /**
3
4
  * Serializes the local (in-program) CLI bootstrap code
4
5
  */
@@ -40,7 +41,9 @@ ${wireServicesFactory ? ' createWireServices,' : ''}
40
41
  export default ${capitalizedName}CLI
41
42
 
42
43
  // For direct execution (if this file is run directly)
43
- if (import.meta.url === \`file://\${process.argv[1]}\`) {
44
+ ${DIRECT_EXECUTION_GUARD}
45
+
46
+ if (isDirectExecution) {
44
47
  ${capitalizedName}CLI(process.argv.slice(2)).catch(error => {
45
48
  console.error('Fatal error:', error.message)
46
49
  process.exit(1)
@@ -115,7 +115,7 @@ export const pikkuConsoleGetSecret = pikkuFunc({
115
115
  return { exists: false, value: null }
116
116
  }
117
117
  const value = await secrets.getSecret(secretId)
118
- return { exists: true, value }
118
+ return { exists: true, value: value.reveal() }
119
119
  },
120
120
  })
121
121
 
@@ -53,7 +53,7 @@ export const pikkuAddonConfig = <ExistingServices extends Omit<Partial<Singleton
53
53
  * { secrets }
54
54
  * ) => {
55
55
  * const creds = await secrets.getSecret<GithubCredentials>('GITHUB_CREDENTIALS')
56
- * const github = new GithubService(creds)
56
+ * const github = new GithubService(creds.reveal())
57
57
  * return { github }
58
58
  * })
59
59
  * \`\`\`
@@ -16,7 +16,7 @@ export const serializeFunctionTypes = (userSessionTypeImport, userSessionTypeNam
16
16
  */
17
17
 
18
18
  import type { CorePikkuMiddleware, CorePermissionGroup, ListInput, ListOutput, PikkuWire, PickRequired, SecretlessServices, SecretService } from '@pikku/core'
19
- import type { CorePikkuFunctionConfig, CorePikkuAuth, CorePikkuAuthConfig, CorePikkuPermission } from '@pikku/core/function'
19
+ import type { CorePikkuFunctionConfig, CorePikkuSessionlessFunctionConfig, CorePikkuAuth, CorePikkuAuthConfig, CorePikkuPermission } from '@pikku/core/function'
20
20
  import { pikkuAuth as pikkuAuthCore } from '@pikku/core/function'
21
21
  import {
22
22
  addTagMiddleware as addTagMiddlewareCore,
@@ -358,6 +358,19 @@ export type PikkuFunctionConfig<
358
358
  OutputSchema extends StandardSchemaV1 | undefined = undefined
359
359
  > = CorePikkuFunctionConfig<PikkuFunc, PikkuPermission<In>, PikkuMiddleware, InputSchema, OutputSchema, ScopeId>
360
360
 
361
+ /**
362
+ * {@link PikkuFunctionConfig} for a function that runs without a session.
363
+ * Has no \`scopes\`: an anonymous caller holds none, so none can ever be met.
364
+ */
365
+ export type PikkuFunctionSessionlessConfig<
366
+ In = unknown,
367
+ Out = unknown,
368
+ RequiredWires extends keyof PikkuWire = never,
369
+ PikkuFunc extends PikkuFunctionSessionless<In, Out, RequiredWires, any> = PikkuFunctionSessionless<In, Out, RequiredWires>,
370
+ InputSchema extends StandardSchemaV1 | undefined = undefined,
371
+ OutputSchema extends StandardSchemaV1 | undefined = undefined
372
+ > = CorePikkuSessionlessFunctionConfig<PikkuFunc, PikkuPermission<In>, PikkuMiddleware, InputSchema, OutputSchema>
373
+
361
374
  /**
362
375
  * Configuration object for Pikku functions with Zod schema validation.
363
376
  * Use this when you want to define input/output schemas using Zod.
@@ -479,7 +492,8 @@ export const pikkuListFunc = <
479
492
  */
480
493
  /**
481
494
  * Schema-overload variant for pikkuSessionlessFunc. Derived from
482
- * CorePikkuFunctionConfig to stay in sync with the generic-typed config.
495
+ * CorePikkuSessionlessFunctionConfig to stay in sync with the generic-typed
496
+ * config — so it has no \`scopes\` either.
483
497
  */
484
498
  export type PikkuFunctionSessionlessConfigWithSchema<
485
499
  InputSchema extends StandardSchemaV1 | undefined = undefined,
@@ -487,7 +501,7 @@ export type PikkuFunctionSessionlessConfigWithSchema<
487
501
  RequiredWires extends keyof PikkuWire = never,
488
502
  RequiredServices extends SecretlessServices<Services> = WiredServices
489
503
  > = Omit<
490
- CorePikkuFunctionConfig<
504
+ CorePikkuSessionlessFunctionConfig<
491
505
  PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
492
506
  >,
493
507
  'func' | 'input' | 'output' | 'permissions' | 'approvalDescription'
@@ -542,7 +556,7 @@ export function pikkuSessionlessFunc<
542
556
  export function pikkuSessionlessFunc<In, Out = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices>(
543
557
  func:
544
558
  | PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>
545
- | PikkuFunctionConfig<In, Out, 'session' | 'rpc', PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>>
559
+ | PikkuFunctionSessionlessConfig<In, Out, 'session' | 'rpc', PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>>
546
560
  ): PikkuFunctionConfig<In, Out, 'session' | 'rpc'>
547
561
  export function pikkuSessionlessFunc(func: any) {
548
562
  return typeof func === 'function' ? { func } : func
@@ -567,7 +581,7 @@ export function pikkuSessionlessFunc(func: any) {
567
581
  export const pikkuVoidFunc = (
568
582
  func:
569
583
  | PikkuFunctionSessionless<void, void, 'session' | 'rpc'>
570
- | PikkuFunctionConfig<void, void, 'session' | 'rpc'>
584
+ | PikkuFunctionSessionlessConfig<void, void, 'session' | 'rpc'>
571
585
  ) => {
572
586
  return typeof func === 'function' ? { func } : func
573
587
  }
@@ -1,3 +1,3 @@
1
- export declare const pikkuSecretDefinitionTypes: import("#pikku").PikkuFunctionConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
2
- export declare const pikkuScopeDefinitionTypes: import("#pikku").PikkuFunctionConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
3
- export declare const pikkuVariableDefinitionTypes: import("#pikku").PikkuFunctionConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
1
+ export declare const pikkuSecretDefinitionTypes: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
2
+ export declare const pikkuScopeDefinitionTypes: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
3
+ export declare const pikkuVariableDefinitionTypes: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Where the generated `SCENARIO_ACTOR_SECRET` declaration lives — beside the
3
+ * personas file, like `auth-secrets.gen.ts` sits beside the auth scaffold.
4
+ *
5
+ * Shared with the inspector's scaffold-file list: nothing imports this file, so
6
+ * it is unreachable through the import graph and has to be inspected explicitly.
7
+ */
8
+ export declare const personasSecretsFilePath: (personasFile: string) => string;
@@ -0,0 +1,9 @@
1
+ import { join, dirname } from 'node:path';
2
+ /**
3
+ * Where the generated `SCENARIO_ACTOR_SECRET` declaration lives — beside the
4
+ * personas file, like `auth-secrets.gen.ts` sits beside the auth scaffold.
5
+ *
6
+ * Shared with the inspector's scaffold-file list: nothing imports this file, so
7
+ * it is unreachable through the import graph and has to be inspected explicitly.
8
+ */
9
+ export const personasSecretsFilePath = (personasFile) => join(dirname(personasFile), 'pikku-personas-secrets.gen.ts');