@pikku/cli 0.12.160 → 0.12.162
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.
- package/console-app/assets/{HelpPanel-C06T226y.js → HelpPanel-DR6oJReA.js} +1 -1
- package/console-app/assets/{abnfDiagram-VCTEODGH-BVwdT3Es.js → abnfDiagram-VCTEODGH-C6mt0F-I.js} +1 -1
- package/console-app/assets/architecture-7GRP2DOG-C3gcY2os.js +1 -0
- package/console-app/assets/{architectureDiagram-5GKGNRK7-XfzqZ3mW.js → architectureDiagram-5GKGNRK7-BPUTuzrJ.js} +1 -1
- package/console-app/assets/{blockDiagram-I7D4REHJ-B5omSqDK.js → blockDiagram-I7D4REHJ-IE8X3BZC.js} +1 -1
- package/console-app/assets/{c4Diagram-7LVT6UL2-DkPe7xCg.js → c4Diagram-7LVT6UL2--HhbjXSJ.js} +1 -1
- package/console-app/assets/channel-CGrTWPVh.js +1 -0
- package/console-app/assets/{chunk-4HAMMTFA-QfSXT_X7.js → chunk-4HAMMTFA-B2Cljp_-.js} +1 -1
- package/console-app/assets/{chunk-75Z2AOVW-h7UnPWNo.js → chunk-75Z2AOVW-D4684ofZ.js} +1 -1
- package/console-app/assets/{chunk-DU6HZSFF-VaMy-LOI.js → chunk-DU6HZSFF-BXipkMhY.js} +1 -1
- package/console-app/assets/{chunk-F27PBJKO-toywqOqS.js → chunk-F27PBJKO-BsSS2TqC.js} +1 -1
- package/console-app/assets/{chunk-GMAD6QVW-Cpa-YKLB.js → chunk-GMAD6QVW-DJqDw8yU.js} +1 -1
- package/console-app/assets/{chunk-GVQU2GXP-BWSHPLNL.js → chunk-GVQU2GXP-CguL9TtP.js} +1 -1
- package/console-app/assets/{chunk-IMKFNOWR-yhQzfQuj.js → chunk-IMKFNOWR-DoB5kv29.js} +1 -1
- package/console-app/assets/{chunk-L3NEJ4N5-C8pAfDlo.js → chunk-L3NEJ4N5-BspKBmrG.js} +1 -1
- package/console-app/assets/{chunk-OSK3NFVY-749yk2fa.js → chunk-OSK3NFVY-DzLs9ozF.js} +1 -1
- package/console-app/assets/{chunk-P2QGCYS3-C1Y9GyYT.js → chunk-P2QGCYS3-DAxcyv2x.js} +1 -1
- package/console-app/assets/{chunk-POPQ4Y6H-DzI9aRsX.js → chunk-POPQ4Y6H-DyLFn-sn.js} +1 -1
- package/console-app/assets/{chunk-PWAF6VOD-D3fAPSwz.js → chunk-PWAF6VOD-VPwoG6QJ.js} +1 -1
- package/console-app/assets/{chunk-SHT3W25Y-D9w7LzM9.js → chunk-SHT3W25Y-C0R9Ptyj.js} +1 -1
- package/console-app/assets/{chunk-SVP7TREG-D55MjOJw.js → chunk-SVP7TREG-cLgcNTyh.js} +1 -1
- package/console-app/assets/{chunk-TICWLB2K-DV8q7H-z.js → chunk-TICWLB2K-C3se3Npx.js} +1 -1
- package/console-app/assets/chunk-XXDRQBXY-DLdC0jYP.js +1 -0
- package/console-app/assets/classDiagram-ZZMXUADV-yt7BCzQS.js +1 -0
- package/console-app/assets/classDiagram-v2-VYDZK3BY-yt7BCzQS.js +1 -0
- package/console-app/assets/{cose-bilkent-JH36ORCC-CLedPW9a.js → cose-bilkent-JH36ORCC-L5Nhs9N1.js} +1 -1
- package/console-app/assets/{cynefin-OW5HDTMX-CS5NKw2p.js → cynefin-OW5HDTMX-jbgNKIs_.js} +1 -1
- package/console-app/assets/{cynefinDiagram-5FMLGOSQ-DGTHW90E.js → cynefinDiagram-5FMLGOSQ-D10NQDH4.js} +1 -1
- package/console-app/assets/{dagre-BNQdos_2.js → dagre-DrsKN-Kd.js} +1 -1
- package/console-app/assets/{dagre-GXQ25YYZ-DHZ8wtwQ.js → dagre-GXQ25YYZ-NDp4fO1z.js} +1 -1
- package/console-app/assets/{diagram-S7CK7UJ4-C41Begsy.js → diagram-S7CK7UJ4-B-9PMbK8.js} +1 -1
- package/console-app/assets/{diagram-UQ7AKVKN-CU8D-sRT.js → diagram-UQ7AKVKN-NXSn7aYB.js} +1 -1
- package/console-app/assets/{diagram-VSXAHHWV-DTTiXYnQ.js → diagram-VSXAHHWV-DrZgXRIZ.js} +1 -1
- package/console-app/assets/{diagram-VX7I27RA-BBy91pxm.js → diagram-VX7I27RA-V3OLFF3v.js} +1 -1
- package/console-app/assets/{diagram-Z3DM3KII-D50xTYe5.js → diagram-Z3DM3KII-CawCD3BR.js} +1 -1
- package/console-app/assets/{ebnfDiagram-PWID7BFC-BHjnFZgE.js → ebnfDiagram-PWID7BFC-QScQWlzV.js} +1 -1
- package/console-app/assets/{erDiagram-RLTQ6QDP-B4-yVo9b.js → erDiagram-RLTQ6QDP-DIhmCYb6.js} +1 -1
- package/console-app/assets/eventmodeling-NTZA5JFV-BbwPCOs2.js +1 -0
- package/console-app/assets/flowDiagram-HODETNUW-B-xUNJdv.js +1 -0
- package/console-app/assets/{ganttDiagram-EL5Y4UJY-D1T-2BlO.js → ganttDiagram-EL5Y4UJY-Bcg0H_3-.js} +1 -1
- package/console-app/assets/{gitGraph-4MIJSDKK-ClqKTUfQ.js → gitGraph-4MIJSDKK-BUYXp4LH.js} +1 -1
- package/console-app/assets/{gitGraphDiagram-WWUBYQGX-ruq2MAhM.js → gitGraphDiagram-WWUBYQGX-DRxwgliX.js} +1 -1
- package/console-app/assets/{graphlib-D-vLYPdw.js → graphlib-BXZn3TnO.js} +1 -1
- package/console-app/assets/{index-BIEZPuyK.js → index-D7ATEpJh.js} +27 -27
- package/console-app/assets/{info-A6RAGUB7-BGI-8HNB.js → info-A6RAGUB7-BAfA_BVB.js} +1 -1
- package/console-app/assets/{infoDiagram-27XIBGKW-BGURgKHv.js → infoDiagram-27XIBGKW-JPbCbDjB.js} +1 -1
- package/console-app/assets/{ishikawaDiagram-5VMMS53U-DzgAaPTR.js → ishikawaDiagram-5VMMS53U-528xNFds.js} +1 -1
- package/console-app/assets/{journeyDiagram-3NMN7TZE-BsyWad8z.js → journeyDiagram-3NMN7TZE-CpnC76my.js} +1 -1
- package/console-app/assets/{kanban-definition-UXKFOSKX-g1nO2rWF.js → kanban-definition-UXKFOSKX-7v_OexVf.js} +1 -1
- package/console-app/assets/{line-CeFoQ5y-.js → line-BXTtRzTv.js} +1 -1
- package/console-app/assets/{linear-C4Pk-YMX.js → linear-BXIxFuy8.js} +1 -1
- package/console-app/assets/{mermaid-parser.core-U7wquvx8.js → mermaid-parser.core-Bn81UzgU.js} +3 -3
- package/console-app/assets/{mermaid.core-8TRpFRm9.js → mermaid.core-CShTFU_y.js} +4 -4
- package/console-app/assets/{mindmap-definition-YA3MSWOX-C7lzwqBX.js → mindmap-definition-YA3MSWOX-Dozk2qNE.js} +1 -1
- package/console-app/assets/{packet-AYTQ26CC-DiQV_rU3.js → packet-AYTQ26CC-CQ1T9gCW.js} +1 -1
- package/console-app/assets/{pegDiagram-XKGWAZYB-63ajP7-W.js → pegDiagram-XKGWAZYB-CAKNYwkF.js} +1 -1
- package/console-app/assets/{pie-WAS4IAKB-B5q_o6dr.js → pie-WAS4IAKB-XBhMekP0.js} +1 -1
- package/console-app/assets/{pieDiagram-E7YTZNPT-BTbvj-by.js → pieDiagram-E7YTZNPT-CQH9g9Im.js} +1 -1
- package/console-app/assets/{quadrantDiagram-AXDQQJYC-CulqsAYd.js → quadrantDiagram-AXDQQJYC-BYry9NEL.js} +1 -1
- package/console-app/assets/{radar-RG4KPBEZ-CW_KoURS.js → radar-RG4KPBEZ-BHk3GM2h.js} +1 -1
- package/console-app/assets/{railroad-74A4TZTK-CUmF6uBQ.js → railroad-74A4TZTK-B-GsJq3u.js} +1 -1
- package/console-app/assets/railroad-abnf-HS5TGJTU-Dqco3Udm.js +1 -0
- package/console-app/assets/railroad-ebnf-LZEXJU2U-DZqyOzxq.js +1 -0
- package/console-app/assets/railroad-peg-WCYAUIDC-DtfiBwRd.js +1 -0
- package/console-app/assets/{railroadDiagram-O6MQD6OU-WlkBu_N3.js → railroadDiagram-O6MQD6OU-CAIv58C8.js} +1 -1
- package/console-app/assets/{requirementDiagram-BXWQKSXE-CJK_CbPR.js → requirementDiagram-BXWQKSXE-DJ3f5870.js} +1 -1
- package/console-app/assets/{sankeyDiagram-P5KCCOFB-C466WOH8.js → sankeyDiagram-P5KCCOFB-YrQnQsb7.js} +1 -1
- package/console-app/assets/{sequenceDiagram-WJ2MYXX4-CV0dCcj0.js → sequenceDiagram-WJ2MYXX4-B-tyzF2R.js} +1 -1
- package/console-app/assets/{src-P4Nw8sY0.js → src-DV6LWVlf.js} +1 -1
- package/console-app/assets/{stateDiagram-D77RDMKH-HaLGm8V9.js → stateDiagram-D77RDMKH-vMePRkxV.js} +1 -1
- package/console-app/assets/stateDiagram-v2-MP3YSRHH-Cojsq9SW.js +1 -0
- package/console-app/assets/{swimlanes-42K2YHIH-Bi-O5vWa.js → swimlanes-42K2YHIH-CqQsTH0R.js} +1 -1
- package/console-app/assets/swimlanesDiagram-VR7AAH4N-0DUuvodn.js +8 -0
- package/console-app/assets/{timeline-definition-24CTP7MA-B4h-gx-i.js → timeline-definition-24CTP7MA-D3OGq7c8.js} +1 -1
- package/console-app/assets/{treeView-Q6P3EWNA-CXJ_pHQw.js → treeView-Q6P3EWNA-DZA143I6.js} +1 -1
- package/console-app/assets/{treemap-WGGIJYW6-M84p2a_3.js → treemap-WGGIJYW6-N5Dr2J8o.js} +1 -1
- package/console-app/assets/{vennDiagram-4TSXK5OY-BesF4k_r.js → vennDiagram-4TSXK5OY-CjQrrdPE.js} +1 -1
- package/console-app/assets/{wardley-WFR3VGLG-n9ulickP.js → wardley-WFR3VGLG-CWrUebhA.js} +1 -1
- package/console-app/assets/{wardleyDiagram-VM6X3IG4-BG0nnWDf.js → wardleyDiagram-VM6X3IG4-Bd-nerY3.js} +1 -1
- package/console-app/assets/{xychartDiagram-S5SC5T6Z-BtOW7fpF.js → xychartDiagram-S5SC5T6Z-CK3-JaeF.js} +1 -1
- package/console-app/index.html +1 -1
- package/dist/.pikku/addon/index.d.ts +1 -1
- package/dist/.pikku/addon/index.js +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.d.ts +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.js +1 -1
- package/dist/.pikku/agent/index.d.ts +1 -1
- package/dist/.pikku/agent/index.js +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/agent/pikku-model-aliases.gen.js +1 -1
- package/dist/.pikku/analytics/index.d.ts +1 -1
- package/dist/.pikku/analytics/index.js +1 -1
- package/dist/.pikku/analytics/pikku-analytics-types.gen.d.ts +1 -1
- package/dist/.pikku/analytics/pikku-analytics-types.gen.js +1 -1
- package/dist/.pikku/auth/index.d.ts +1 -1
- package/dist/.pikku/auth/index.js +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.d.ts +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.js +1 -1
- package/dist/.pikku/channel/index.d.ts +1 -1
- package/dist/.pikku/channel/index.js +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/index.d.ts +1 -1
- package/dist/.pikku/cli/index.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/error/index.d.ts +1 -1
- package/dist/.pikku/error/index.js +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.d.ts +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.js +1 -1
- package/dist/.pikku/function/index.d.ts +1 -1
- package/dist/.pikku/function/index.js +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +2 -2
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/gateway/index.d.ts +1 -1
- package/dist/.pikku/gateway/index.js +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.d.ts +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.js +1 -1
- package/dist/.pikku/http/index.d.ts +1 -1
- package/dist/.pikku/http/index.js +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/mcp/index.d.ts +1 -1
- package/dist/.pikku/mcp/index.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/middleware/index.d.ts +1 -1
- package/dist/.pikku/middleware/index.js +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.d.ts +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/queue/index.d.ts +1 -1
- package/dist/.pikku/queue/index.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/scenarios/index.d.ts +1 -1
- package/dist/.pikku/scenarios/index.js +1 -1
- package/dist/.pikku/scenarios/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-types.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
- package/dist/.pikku/scheduler/index.d.ts +1 -1
- package/dist/.pikku/scheduler/index.js +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +1 -1
- package/dist/.pikku/scopes/index.d.ts +1 -1
- package/dist/.pikku/scopes/index.js +1 -1
- package/dist/.pikku/scopes/pikku-flags.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/index.d.ts +1 -1
- package/dist/.pikku/secrets/index.js +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/setup/index.d.ts +1 -1
- package/dist/.pikku/setup/index.js +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
- package/dist/.pikku/trigger/index.d.ts +1 -1
- package/dist/.pikku/trigger/index.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/index.d.ts +1 -1
- package/dist/.pikku/variables/index.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/index.d.ts +1 -1
- package/dist/.pikku/workflow/index.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/deploy/analyzer/analyzer.js +7 -1
- package/dist/src/functions/commands/serve.js +7 -2
- package/dist/src/functions/surface/collect-snippets.d.ts +1 -13
- package/dist/src/functions/surface/collect-snippets.js +1 -83
- package/dist/src/functions/validate/type-identity-checks.d.ts +3 -2
- package/dist/src/functions/validate/type-identity-checks.js +74 -5
- package/dist/src/functions/validate/validate-registry.js +3 -3
- package/dist/src/functions/wirings/auth/serialize-auth-gen.js +33 -1
- package/dist/src/functions/wirings/functions/serialize-addon-types.js +4 -2
- package/dist/src/functions/wirings/rpc/pikku-command-react-query.js +3 -2
- package/dist/src/functions/wirings/rpc/serialize-react-query-hooks.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/serialize-react-query-hooks.js +54 -3
- package/package.json +10 -10
- package/snippets-meta.json +1 -0
- package/snippets.json +1 -0
- package/surface.json +7 -3
- package/console-app/assets/architecture-7GRP2DOG-3y7bWtag.js +0 -1
- package/console-app/assets/channel-CTiluQVw.js +0 -1
- package/console-app/assets/chunk-XXDRQBXY-DBtYQykd.js +0 -1
- package/console-app/assets/classDiagram-ZZMXUADV-BnWa-i9n.js +0 -1
- package/console-app/assets/classDiagram-v2-VYDZK3BY-BnWa-i9n.js +0 -1
- package/console-app/assets/eventmodeling-NTZA5JFV-C_IpFSCw.js +0 -1
- package/console-app/assets/flowDiagram-HODETNUW-Q90rgVpx.js +0 -1
- package/console-app/assets/railroad-abnf-HS5TGJTU-CcPw9q8a.js +0 -1
- package/console-app/assets/railroad-ebnf-LZEXJU2U-Ci_fZics.js +0 -1
- package/console-app/assets/railroad-peg-WCYAUIDC-DTsDykSf.js +0 -1
- package/console-app/assets/stateDiagram-v2-MP3YSRHH--GM14Hz5.js +0 -1
- package/console-app/assets/swimlanesDiagram-VR7AAH4N-_6rRi6Wt.js +0 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.162
|
|
3
3
|
*/
|
|
4
4
|
import { WorkflowCancelledException } from '@pikku/core/workflow';
|
|
5
5
|
import type { PikkuWorkflowGraphConfig, PikkuWorkflowGraphResult } from '@pikku/core/workflow';
|
package/dist/bin/pikku-bin.mjs
CHANGED
|
@@ -11,8 +11,8 @@ async function checkForUpdate() {
|
|
|
11
11
|
})
|
|
12
12
|
if (!res.ok) return
|
|
13
13
|
const { version: latest } = await res.json()
|
|
14
|
-
if (latest !== '0.12.
|
|
15
|
-
process.stderr.write(`\n Update available 0.12.
|
|
14
|
+
if (latest !== '0.12.162') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.162 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
|
|
16
16
|
}
|
|
17
17
|
} catch {}
|
|
18
18
|
}
|
|
@@ -303,7 +303,13 @@ export function analyzeDeployment(state, options) {
|
|
|
303
303
|
// ── Step 1b: Addon units ───────────────────────────────────────────
|
|
304
304
|
const addonUnitByRpcName = new Map();
|
|
305
305
|
for (const [namespace, addonMeta] of entries(state.addonFunctions ?? {})) {
|
|
306
|
-
|
|
306
|
+
// The wiring's `expose` decides when it is `false` or a list; otherwise
|
|
307
|
+
// the addon's own `expose: true` does — the same rule `rpc.exposed`
|
|
308
|
+
// applies at runtime, so the unit carries exactly what can be called.
|
|
309
|
+
const wiredExpose = state.rpc?.wireAddonDeclarations?.get(namespace)?.expose;
|
|
310
|
+
const exposed = entries(addonMeta).filter(([funcName, meta]) => Array.isArray(wiredExpose)
|
|
311
|
+
? wiredExpose.includes(funcName)
|
|
312
|
+
: wiredExpose !== false && meta.expose);
|
|
307
313
|
if (exposed.length === 0) {
|
|
308
314
|
continue;
|
|
309
315
|
}
|
|
@@ -180,8 +180,13 @@ export const serve = pikkuSessionlessFunc({
|
|
|
180
180
|
? await resolveFrontendMount(config.frontend)
|
|
181
181
|
: undefined;
|
|
182
182
|
// The console goes first so a frontend mounted at `/` cannot claim
|
|
183
|
-
// `/console` before the console's own mount is offered the request
|
|
184
|
-
|
|
183
|
+
// `/console` before the console's own mount is offered the request, and
|
|
184
|
+
// the app's own mounts are kept ahead of the catch-all frontend.
|
|
185
|
+
const staticMounts = [
|
|
186
|
+
...(consoleMount ? [consoleMount] : []),
|
|
187
|
+
...(userConfig.staticMounts ?? []),
|
|
188
|
+
...(frontendMount ? [frontendMount] : []),
|
|
189
|
+
];
|
|
185
190
|
const pikkuServer = devServerRunner.createServer({
|
|
186
191
|
...userConfig,
|
|
187
192
|
hostname: bindHostname,
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
constructor(name: string, file: string);
|
|
3
|
-
}
|
|
4
|
-
export declare class DuplicateSnippetError extends Error {
|
|
5
|
-
constructor(name: string, file: string, other: string);
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* The `// @snippet start <name>` regions in a project's source, so an example
|
|
9
|
-
* in a doc comment can name one instead of restating it. The same mechanism the
|
|
10
|
-
* website uses to pull its code blocks out of the shop template: the code that
|
|
11
|
-
* reaches the reader is the code that compiles, and it cannot drift.
|
|
12
|
-
*/
|
|
13
|
-
export declare const collectSnippets: (projectDir: string, into?: Map<string, string>, origins?: Map<string, string>) => Promise<Map<string, string>>;
|
|
1
|
+
export { collectSnippets, UnclosedSnippetError, DuplicateSnippetError, } from '@pikku/skills';
|
|
@@ -1,83 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { join, relative } from 'node:path';
|
|
3
|
-
const START = /^\s*(?:\/\/|--)\s*@snippet start (\S+)\s*$/;
|
|
4
|
-
const END = /^\s*(?:\/\/|--)\s*@snippet end (\S+)\s*$/;
|
|
5
|
-
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.sql'];
|
|
6
|
-
const SKIPPED_DIRECTORIES = new Set(['node_modules', '.pikku', 'dist', '.git']);
|
|
7
|
-
export class UnclosedSnippetError extends Error {
|
|
8
|
-
constructor(name, file) {
|
|
9
|
-
super(`The snippet "${name}" opens in ${file} and never closes. Add "// @snippet end ${name}".`);
|
|
10
|
-
this.name = 'UnclosedSnippetError';
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export class DuplicateSnippetError extends Error {
|
|
14
|
-
constructor(name, file, other) {
|
|
15
|
-
super(`The snippet "${name}" is defined twice, in ${other} and ${file}. Snippet names are the reference an example uses, so they have to be unique.`);
|
|
16
|
-
this.name = 'DuplicateSnippetError';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
const dedent = (lines) => {
|
|
20
|
-
const indents = lines
|
|
21
|
-
.filter((line) => line.trim().length > 0)
|
|
22
|
-
.map((line) => line.length - line.trimStart().length);
|
|
23
|
-
const shortest = indents.length > 0 ? Math.min(...indents) : 0;
|
|
24
|
-
return lines
|
|
25
|
-
.map((line) => line.slice(shortest))
|
|
26
|
-
.join('\n')
|
|
27
|
-
.trim();
|
|
28
|
-
};
|
|
29
|
-
const sourceFilesIn = async (directory, found = []) => {
|
|
30
|
-
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
31
|
-
const full = join(directory, entry.name);
|
|
32
|
-
if (entry.isDirectory()) {
|
|
33
|
-
if (SKIPPED_DIRECTORIES.has(entry.name) || entry.name.startsWith('.')) {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
await sourceFilesIn(full, found);
|
|
37
|
-
}
|
|
38
|
-
else if (SOURCE_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
39
|
-
found.push(full);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return found;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* The `// @snippet start <name>` regions in a project's source, so an example
|
|
46
|
-
* in a doc comment can name one instead of restating it. The same mechanism the
|
|
47
|
-
* website uses to pull its code blocks out of the shop template: the code that
|
|
48
|
-
* reaches the reader is the code that compiles, and it cannot drift.
|
|
49
|
-
*/
|
|
50
|
-
export const collectSnippets = async (projectDir, into = new Map(), origins = new Map()) => {
|
|
51
|
-
for (const file of await sourceFilesIn(projectDir)) {
|
|
52
|
-
const where = relative(projectDir, file);
|
|
53
|
-
const lines = (await readFile(file, 'utf8')).split('\n');
|
|
54
|
-
const open = new Map();
|
|
55
|
-
for (const line of lines) {
|
|
56
|
-
const end = line.match(END);
|
|
57
|
-
if (end?.[1] && open.has(end[1])) {
|
|
58
|
-
const name = end[1];
|
|
59
|
-
const existing = origins.get(name);
|
|
60
|
-
if (existing)
|
|
61
|
-
throw new DuplicateSnippetError(name, where, existing);
|
|
62
|
-
into.set(name, dedent(open.get(name)));
|
|
63
|
-
origins.set(name, where);
|
|
64
|
-
open.delete(name);
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
const start = line.match(START);
|
|
68
|
-
if (start?.[1]) {
|
|
69
|
-
if (!open.has(start[1]))
|
|
70
|
-
open.set(start[1], []);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (end)
|
|
74
|
-
continue;
|
|
75
|
-
for (const body of open.values())
|
|
76
|
-
body.push(line);
|
|
77
|
-
}
|
|
78
|
-
const [unclosed] = open.keys();
|
|
79
|
-
if (unclosed)
|
|
80
|
-
throw new UnclosedSnippetError(unclosed, where);
|
|
81
|
-
}
|
|
82
|
-
return into;
|
|
83
|
-
};
|
|
1
|
+
export { collectSnippets, UnclosedSnippetError, DuplicateSnippetError, } from '@pikku/skills';
|
|
@@ -2,8 +2,9 @@ import type { ValidateFinding } from './persona-checks.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* A linked dependency resolves its own imports from its own checkout, so it can
|
|
4
4
|
* hand the project types built against a different version of a shared package.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* An installed pikku package can do the same from its own store entry. The
|
|
6
|
+
* symptom is a typecheck that OOMs rather than one that fails, so nothing else
|
|
7
|
+
* in this validator would catch it.
|
|
7
8
|
*
|
|
8
9
|
* Runs against the workspace root only. The mismatch is a property of the
|
|
9
10
|
* install, not of any one package in it, so running per workspace package would
|
|
@@ -153,18 +153,87 @@ async function externalDependencyRoots(root) {
|
|
|
153
153
|
}
|
|
154
154
|
return found;
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Every installed `@pikku/*` package, by the real directory its imports resolve
|
|
158
|
+
* from. Probed under the root and each workspace package, because an isolated
|
|
159
|
+
* install links a dependency only under the package that declares it.
|
|
160
|
+
*/
|
|
161
|
+
async function installedPikkuPackages(root) {
|
|
162
|
+
const bases = [root];
|
|
163
|
+
for (const group of ['packages', 'apps', 'backends']) {
|
|
164
|
+
const entries = await readdir(join(root, group), {
|
|
165
|
+
withFileTypes: true,
|
|
166
|
+
}).catch(() => []);
|
|
167
|
+
for (const d of entries) {
|
|
168
|
+
if (d.isDirectory())
|
|
169
|
+
bases.push(join(root, group, d.name));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const found = new Map();
|
|
173
|
+
for (const base of bases) {
|
|
174
|
+
const scope = join(base, 'node_modules', '@pikku');
|
|
175
|
+
const entries = await readdir(scope).catch(() => []);
|
|
176
|
+
for (const entry of entries) {
|
|
177
|
+
const real = await realpath(join(scope, entry)).catch(() => null);
|
|
178
|
+
if (real && !found.has(real))
|
|
179
|
+
found.set(real, `@pikku/${entry}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return found;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* An installed pikku package can resolve its own copy of a type-identity
|
|
186
|
+
* package — bun's isolated store keeps one beside each entry — so the CLI can
|
|
187
|
+
* read the project's zod schemas with a different zod than wrote them. No link
|
|
188
|
+
* leaves the project, so the linked-dependency check never sees it.
|
|
189
|
+
*
|
|
190
|
+
* Only packages that declare the dependency are compared: walking up from one
|
|
191
|
+
* that never asked for it lands on whatever the store hoisted, which says
|
|
192
|
+
* nothing about what that package loads.
|
|
193
|
+
*/
|
|
194
|
+
async function runInstallSkewChecks(root) {
|
|
195
|
+
const findings = [];
|
|
196
|
+
const installed = await installedPikkuPackages(root);
|
|
197
|
+
for (const pkg of TYPE_IDENTITY_PKGS) {
|
|
198
|
+
const local = await projectResolvedVersion(root, pkg);
|
|
199
|
+
if (!local)
|
|
200
|
+
continue;
|
|
201
|
+
for (const [real, name] of installed) {
|
|
202
|
+
if (name === pkg)
|
|
203
|
+
continue;
|
|
204
|
+
const manifest = await readJsonSafe(join(real, 'package.json'));
|
|
205
|
+
if (!manifest?.dependencies?.[pkg] && !manifest?.peerDependencies?.[pkg])
|
|
206
|
+
continue;
|
|
207
|
+
const theirs = await versionResolvedFrom(real, pkg);
|
|
208
|
+
if (!theirs || theirs === local.version)
|
|
209
|
+
continue;
|
|
210
|
+
findings.push({
|
|
211
|
+
id: `skewed-type-identity-${name.replace(/[@/]/g, '-')}-${pkg.replace(/[@/]/g, '-')}`,
|
|
212
|
+
severity: 'error',
|
|
213
|
+
message: `${name} resolves ${pkg}@${theirs}, while this project resolves ${pkg}@${local.version} — two copies of ${pkg} in one install`,
|
|
214
|
+
path: real,
|
|
215
|
+
fixHint: [
|
|
216
|
+
`${name} reads what the project builds with ${pkg} using its own copy, and TypeScript treats the two as unrelated types, so codegen can fail on schemas that are correct or exhaust the heap instead of reporting an error.`,
|
|
217
|
+
`Pin one ${pkg} for the whole install — "overrides": { "${pkg}": "${local.version}" } in the root package.json (bun/npm; "resolutions" for yarn) — and reinstall.`,
|
|
218
|
+
].join('\n'),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return findings;
|
|
223
|
+
}
|
|
156
224
|
/**
|
|
157
225
|
* A linked dependency resolves its own imports from its own checkout, so it can
|
|
158
226
|
* hand the project types built against a different version of a shared package.
|
|
159
|
-
*
|
|
160
|
-
*
|
|
227
|
+
* An installed pikku package can do the same from its own store entry. The
|
|
228
|
+
* symptom is a typecheck that OOMs rather than one that fails, so nothing else
|
|
229
|
+
* in this validator would catch it.
|
|
161
230
|
*
|
|
162
231
|
* Runs against the workspace root only. The mismatch is a property of the
|
|
163
232
|
* install, not of any one package in it, so running per workspace package would
|
|
164
233
|
* report the same pair once per package.
|
|
165
234
|
*/
|
|
166
235
|
export async function runTypeIdentityChecks(root) {
|
|
167
|
-
const findings =
|
|
236
|
+
const findings = await runInstallSkewChecks(root);
|
|
168
237
|
const external = await externalDependencyRoots(root);
|
|
169
238
|
if (external.size === 0)
|
|
170
239
|
return findings;
|
|
@@ -208,11 +277,11 @@ export async function warnOnSplitTypeIdentity(rootDir, logger) {
|
|
|
208
277
|
const findings = await runTypeIdentityChecks(rootDir).catch(() => []);
|
|
209
278
|
if (findings.length === 0)
|
|
210
279
|
return;
|
|
211
|
-
logger.warn(`[${ErrorCode.SPLIT_TYPE_IDENTITY}] ${findings.length === 1 ? 'A
|
|
280
|
+
logger.warn(`[${ErrorCode.SPLIT_TYPE_IDENTITY}] ${findings.length === 1 ? 'A dependency resolves a shared package' : 'Dependencies resolve shared packages'} at a different version than this project:\n` +
|
|
212
281
|
findings.map((f) => ` ${f.message}`).join('\n') +
|
|
213
282
|
`\nTypeScript treats each pair as two unrelated types and structurally compares them\n` +
|
|
214
283
|
`wherever they meet, which inside a generic inference chain can exhaust the heap —\n` +
|
|
215
284
|
`codegen then dies of memory pressure instead of reporting an error.\n\n` +
|
|
216
|
-
`Fix: align the versions so
|
|
285
|
+
`Fix: align the versions so the install resolves one copy, or drop the link and\n` +
|
|
217
286
|
`reinstall. Set PIKKU_SKIP_TYPE_IDENTITY_CHECK=1 to silence this.`);
|
|
218
287
|
}
|
|
@@ -82,9 +82,9 @@ export const CHECKS = [
|
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
id: 'type-identity',
|
|
85
|
-
subject: '
|
|
86
|
-
// Root of an installed tree only. A linked dependency is a
|
|
87
|
-
// install as a whole, so running this per workspace package reports the
|
|
85
|
+
subject: 'shared dependency versions',
|
|
86
|
+
// Root of an installed tree only. A linked or skewed dependency is a
|
|
87
|
+
// property of the install as a whole, so running this per workspace package reports the
|
|
88
88
|
// same pair N times — and with nothing installed there is nothing to
|
|
89
89
|
// compare.
|
|
90
90
|
applies: async ({ dir, label }) => label === '.' && existsSync(join(dir, 'node_modules')),
|
|
@@ -72,7 +72,8 @@ export const serializeAuthGen = (definition, providers, authFile, leaf, packageM
|
|
|
72
72
|
'',
|
|
73
73
|
`import { defineSecret } from '@pikku/core/secret'`,
|
|
74
74
|
];
|
|
75
|
-
const hasVariables = known.some((name) => PROVIDER_REGISTRY[name].variables)
|
|
75
|
+
const hasVariables = known.some((name) => PROVIDER_REGISTRY[name].variables) ||
|
|
76
|
+
definition.cookieCache;
|
|
76
77
|
if (hasVariables) {
|
|
77
78
|
secrets.push(`import { defineVariable } from '@pikku/core/variable'`);
|
|
78
79
|
}
|
|
@@ -133,6 +134,37 @@ export const serializeAuthGen = (definition, providers, authFile, leaf, packageM
|
|
|
133
134
|
secrets.push('');
|
|
134
135
|
}
|
|
135
136
|
}
|
|
137
|
+
// The stateless session's cookie lifetime, declared only on the cookieCache
|
|
138
|
+
// path because that is the only path where it decides anything. There the
|
|
139
|
+
// signed `session_data` cookie is the ONLY thing authenticating a request —
|
|
140
|
+
// `betterAuthStatelessSession` verifies it with the secret and never reaches
|
|
141
|
+
// the database — and an app typically calls no `/api/auth/*` route once
|
|
142
|
+
// someone is signed in, so nothing rewrites the cookie. better-auth's own
|
|
143
|
+
// 300s default therefore signs everyone out five minutes after they log in.
|
|
144
|
+
//
|
|
145
|
+
// @pikku/better-auth reads this variable and applies it to the instance, so
|
|
146
|
+
// the app's own `betterAuth({ session: { cookieCache } })` needs no `maxAge`.
|
|
147
|
+
// It is declared rather than hardcoded because the lifetime is also the
|
|
148
|
+
// longest a ban or a revoked session can go unnoticed, which is a per-stage
|
|
149
|
+
// policy decision. Optional: unset means the one-day default.
|
|
150
|
+
//
|
|
151
|
+
// The schema is a string, not a coerced number. `TypedVariablesService`
|
|
152
|
+
// returns a stored host value UNPARSED and runs the schema only to resolve a
|
|
153
|
+
// default, so a `z.coerce.number()` here would never fire on a real value and
|
|
154
|
+
// would only mislead whoever read it.
|
|
155
|
+
if (definition.cookieCache) {
|
|
156
|
+
secrets.push(`export const SessionCookieCacheMaxAgeSchema = z.string().default('86400')`);
|
|
157
|
+
secrets.push('');
|
|
158
|
+
secrets.push(`defineVariable({`);
|
|
159
|
+
secrets.push(` name: 'sessionCookieCacheMaxAge',`);
|
|
160
|
+
secrets.push(` displayName: 'Session Cookie Lifetime (seconds)',`);
|
|
161
|
+
secrets.push(` description: 'How long the signed session cookie is trusted before the API re-reads the session from the database. Also the longest a ban or a revoked session can go unnoticed. Defaults to 86400 (one day).',`);
|
|
162
|
+
secrets.push(` variableId: 'SESSION_COOKIE_CACHE_MAX_AGE',`);
|
|
163
|
+
secrets.push(` schema: SessionCookieCacheMaxAgeSchema,`);
|
|
164
|
+
secrets.push(` optional: true,`);
|
|
165
|
+
secrets.push(`})`);
|
|
166
|
+
secrets.push('');
|
|
167
|
+
}
|
|
136
168
|
// Wiring file: handler + catch-all routes. When cookieCache is enabled the
|
|
137
169
|
// global session middleware is split into its own file (see below) so this
|
|
138
170
|
// file's auth.wiring import (the full better-auth server) isn't dragged into
|
|
@@ -37,7 +37,7 @@ import type { WireAddonConfig } from '@pikku/core/addon'
|
|
|
37
37
|
export { wireRemoteAddon } from '@pikku/core/addon'
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* The functions each installed addon publishes. \`mcp\`
|
|
40
|
+
* The functions each installed addon publishes. \`mcp\` and \`expose\` name them.
|
|
41
41
|
*/
|
|
42
42
|
type AddonFunctions = {
|
|
43
43
|
${entries}
|
|
@@ -52,11 +52,13 @@ type AddonFunctionName<Package extends string> =
|
|
|
52
52
|
*
|
|
53
53
|
* \`mcp: true\` offers every function the addon itself declared as a tool; a list
|
|
54
54
|
* names the functions to offer, checked against the ones the addon publishes.
|
|
55
|
+
* \`expose\` works the same way for \`rpc.exposed\`, and \`false\` exposes none.
|
|
55
56
|
*/
|
|
56
57
|
export const wireAddon = <Package extends string>(
|
|
57
|
-
config: Omit<WireAddonConfig, 'package' | 'mcp'> & {
|
|
58
|
+
config: Omit<WireAddonConfig, 'package' | 'mcp' | 'expose'> & {
|
|
58
59
|
package: Package
|
|
59
60
|
mcp?: boolean | AddonFunctionName<Package>[]
|
|
61
|
+
expose?: boolean | AddonFunctionName<Package>[]
|
|
60
62
|
}
|
|
61
63
|
): void => wireAddonCore(config)
|
|
62
64
|
`;
|
|
@@ -14,14 +14,15 @@ export const pikkuReactQuery = pikkuSessionlessFunc({
|
|
|
14
14
|
});
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
const { workflows } = await getInspectorState();
|
|
17
|
+
const { workflows, auth } = await getInspectorState();
|
|
18
18
|
const hasWorkflows = Object.keys(workflows?.meta ?? {}).length > 0;
|
|
19
19
|
const rpcMapPath = getFileImportRelativePath(reactQueryFile, rpcMapDeclarationFile, packageMappings);
|
|
20
20
|
let workflowMapPath;
|
|
21
21
|
if (hasWorkflows) {
|
|
22
22
|
workflowMapPath = getFileImportRelativePath(reactQueryFile, workflowMapDeclarationFile, packageMappings);
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
// `useSession` only exists for an app that has auth at all.
|
|
25
|
+
const content = serializeReactQueryHooks(rpcMapPath, workflowMapPath, !!auth.definition);
|
|
25
26
|
await writeFileInDir(logger, reactQueryFile, content);
|
|
26
27
|
},
|
|
27
28
|
middleware: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const serializeReactQueryHooks: (rpcMapPath: string, workflowMapPath?: string) => string;
|
|
1
|
+
export declare const serializeReactQueryHooks: (rpcMapPath: string, workflowMapPath?: string, hasAuth?: boolean) => string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const serializeReactQueryHooks = (rpcMapPath, workflowMapPath) => {
|
|
1
|
+
export const serializeReactQueryHooks = (rpcMapPath, workflowMapPath, hasAuth) => {
|
|
2
2
|
const workflowImport = workflowMapPath
|
|
3
3
|
? `\nimport type { FlattenedWorkflowMap } from '${workflowMapPath}'`
|
|
4
4
|
: '';
|
|
@@ -49,10 +49,61 @@ export const useWorkflowStatus = (
|
|
|
49
49
|
...options,
|
|
50
50
|
})
|
|
51
51
|
}
|
|
52
|
+
`
|
|
53
|
+
: '';
|
|
54
|
+
/**
|
|
55
|
+
* The session — and, for free, the thing that heals the session cookie.
|
|
56
|
+
*
|
|
57
|
+
* Under `betterAuthStatelessSession` the signed `session_data` cookie is the
|
|
58
|
+
* only thing authenticating a request, and nothing rewrites it once someone
|
|
59
|
+
* is signed in. When it ages out, better-auth's cookie-cache branch bails on
|
|
60
|
+
* the stale payload and falls through to the database, reading the session
|
|
61
|
+
* from the still-valid `session_token` and minting a fresh cookie on the way
|
|
62
|
+
* out. So an ordinary cached read heals an expired cookie by itself.
|
|
63
|
+
*
|
|
64
|
+
* Which is why this does NOT pass `disableCookieCache`. Forcing it would turn
|
|
65
|
+
* every refetch into a database read — the exact cost the cookie cache exists
|
|
66
|
+
* to avoid — to re-mint a cookie that has most of its life left. The read is
|
|
67
|
+
* worth paying once, when the cookie has actually expired, and that is when
|
|
68
|
+
* better-auth does it anyway.
|
|
69
|
+
*
|
|
70
|
+
* better-auth's own sliding renewal (`session.cookieCache.refreshCache`) is
|
|
71
|
+
* not the answer either: it is force-disabled whenever a database is
|
|
72
|
+
* configured, and where it does apply it re-signs the cached blob without
|
|
73
|
+
* reading the database, so a banned user's cookie would renew forever.
|
|
74
|
+
*/
|
|
75
|
+
const sessionImport = hasAuth ? ', usePikkuFetch' : '';
|
|
76
|
+
const sessionHook = hasAuth
|
|
77
|
+
? `
|
|
78
|
+
/* Short enough that an expired cookie is healed long before anyone notices,
|
|
79
|
+
and cheap: while the cookie is good this is a cache hit with no database
|
|
80
|
+
behind it. */
|
|
81
|
+
const SESSION_REFETCH_MS = 10 * 60 * 1000
|
|
82
|
+
/* A tab flicked away from and back to should not refetch on every glance. */
|
|
83
|
+
const SESSION_STALE_MS = 2 * 60 * 1000
|
|
84
|
+
|
|
85
|
+
export const useSession = <Session = unknown>(
|
|
86
|
+
options?: Omit<UseQueryOptions<Session | null, Error>, 'queryKey' | 'queryFn'>
|
|
87
|
+
) => {
|
|
88
|
+
const fetch = usePikkuFetch()
|
|
89
|
+
return useQuery<Session | null, Error>({
|
|
90
|
+
queryKey: ['pikkuSession'],
|
|
91
|
+
queryFn: async () => {
|
|
92
|
+
const response = await fetch.fetch('/auth/get-session', 'GET', undefined)
|
|
93
|
+
if (!response.ok) return null
|
|
94
|
+
// Signed out is a null body, not an error status.
|
|
95
|
+
return ((await response.json().catch(() => null)) ?? null) as Session | null
|
|
96
|
+
},
|
|
97
|
+
refetchInterval: SESSION_REFETCH_MS,
|
|
98
|
+
refetchOnWindowFocus: true,
|
|
99
|
+
staleTime: SESSION_STALE_MS,
|
|
100
|
+
...options,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
52
103
|
`
|
|
53
104
|
: '';
|
|
54
105
|
return `import { useQuery, useInfiniteQuery, useMutation, type UseQueryOptions, type UseInfiniteQueryOptions, type UseMutationOptions, type InfiniteData } from '@tanstack/react-query'
|
|
55
|
-
import { usePikkuRPC } from '@pikku/react'
|
|
106
|
+
import { usePikkuRPC${sessionImport} } from '@pikku/react'
|
|
56
107
|
import type { FlattenedRPCMap } from '${rpcMapPath}'${workflowImport}
|
|
57
108
|
|
|
58
109
|
type RPCInvoke = <Name extends keyof FlattenedRPCMap>(name: Name, data: FlattenedRPCMap[Name]['input']) => Promise<FlattenedRPCMap[Name]['output']>
|
|
@@ -104,5 +155,5 @@ export const usePikkuInfiniteQuery = <Name extends PaginatedKeys>(
|
|
|
104
155
|
...options,
|
|
105
156
|
})
|
|
106
157
|
}
|
|
107
|
-
${workflowHooks}`;
|
|
158
|
+
${sessionHook}${workflowHooks}`;
|
|
108
159
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.162",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/pikkujs/pikku.git",
|
|
@@ -38,21 +38,21 @@
|
|
|
38
38
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
39
39
|
"@openapi-contrib/json-schema-to-openapi-schema": "^4.3.4",
|
|
40
40
|
"@pikku/ai-vercel": "^0.12.14",
|
|
41
|
-
"@pikku/better-auth": "^0.12.
|
|
41
|
+
"@pikku/better-auth": "^0.12.46",
|
|
42
42
|
"@pikku/bun-server": "^0.12.13",
|
|
43
43
|
"@pikku/code-edit": "^0.12.2",
|
|
44
44
|
"@pikku/deploy": "^0.12.11",
|
|
45
45
|
"@pikku/deploy-cloudflare": "^0.12.18",
|
|
46
46
|
"@pikku/fetch": "^0.12.12",
|
|
47
|
-
"@pikku/inspector": "^0.12.
|
|
47
|
+
"@pikku/inspector": "^0.12.87",
|
|
48
48
|
"@pikku/knowledge": "^0.12.15",
|
|
49
|
-
"@pikku/kysely": "^0.13.
|
|
49
|
+
"@pikku/kysely": "^0.13.28",
|
|
50
50
|
"@pikku/migrator-sql": "^0.12.5",
|
|
51
51
|
"@pikku/n8n-import": "^0.0.8",
|
|
52
52
|
"@pikku/node-http-server": "^0.12.17",
|
|
53
|
-
"@pikku/openapi-parser": "^0.12.
|
|
53
|
+
"@pikku/openapi-parser": "^0.12.22",
|
|
54
54
|
"@pikku/schedule": "^0.12.8",
|
|
55
|
-
"@pikku/skills": "^0.12.
|
|
55
|
+
"@pikku/skills": "^0.12.37",
|
|
56
56
|
"@pikku/websocket": "^0.12.5",
|
|
57
57
|
"@types/cookie": "^1.0.0",
|
|
58
58
|
"@types/json-schema": "^7.0.15",
|
|
@@ -75,15 +75,15 @@
|
|
|
75
75
|
"zod-to-ts": "^2.1.0"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"@pikku/core": "^0.12.
|
|
79
|
-
"@pikku/playwright": "^0.12.
|
|
78
|
+
"@pikku/core": "^0.12.120",
|
|
79
|
+
"@pikku/playwright": "^0.12.85",
|
|
80
80
|
"@pikku/ws": "^0.12.10",
|
|
81
81
|
"better-auth": "^1.7.5",
|
|
82
82
|
"ws": "^8.21.3"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@pikku/core": "^0.12.
|
|
86
|
-
"@pikku/playwright": "^0.12.
|
|
85
|
+
"@pikku/core": "^0.12.120",
|
|
86
|
+
"@pikku/playwright": "^0.12.85",
|
|
87
87
|
"@pikku/ws": "^0.12.10",
|
|
88
88
|
"@playwright/test": "^1.50.0",
|
|
89
89
|
"@standard-schema/spec": "^1.1.0",
|
package/snippets-meta.json
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"getBasket": "src/functions/basket/get-basket.function.ts",
|
|
51
51
|
"getItem": "src/functions/items/get-item.function.ts",
|
|
52
52
|
"getOrder": "src/functions/orders/get-order.function.ts",
|
|
53
|
+
"guideCaptureStep": "test/scenarios/guide.steps.ts",
|
|
53
54
|
"httpAuthRoute": "src/wirings/shop.http.ts",
|
|
54
55
|
"httpMiddleware": "src/wirings/shop.http.ts",
|
|
55
56
|
"httpRoutesWiring": "src/wirings/shop.http.ts",
|
package/snippets.json
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"getBasket": "export const getBasket = pikkuSessionlessFunc({\n expose: true,\n description:\n 'Get basket for the current user or session. Creates one if it does not exist.',\n input: GetBasketInput,\n output: GetBasketOutput,\n func: async ({ kysely }, { sessionId }, { session }) => {\n const userId = session?.userId ?? null\n const sid = sessionId ?? null\n\n // Find or create basket\n let basket = userId\n ? await kysely\n .selectFrom('basket')\n .selectAll()\n .where('userId', '=', userId)\n .executeTakeFirst()\n : sid\n ? await kysely\n .selectFrom('basket')\n .selectAll()\n .where('sessionId', '=', sid)\n .executeTakeFirst()\n : null\n\n if (!basket) {\n const basketId = randomUUID()\n const now = new Date().toISOString()\n await kysely\n .insertInto('basket')\n .values({\n basketId,\n userId,\n sessionId: sid,\n createdAt: now,\n updatedAt: now,\n })\n .execute()\n return { basketId, items: [], totalCents: 0, itemCount: 0 }\n }\n\n const rows = await kysely\n .selectFrom('basketItem')\n .innerJoin('item', 'item.itemId', 'basketItem.itemId')\n .select([\n 'basketItem.basketItemId',\n 'basketItem.itemId',\n 'basketItem.quantity',\n 'item.name',\n 'item.slug',\n 'item.priceCents',\n 'item.imageUrl',\n ])\n .where('basketItem.basketId', '=', basket.basketId)\n .execute()\n\n const items = rows.map((r) => ({\n basketItemId: r.basketItemId,\n itemId: r.itemId,\n name: r.name,\n slug: r.slug,\n priceCents: r.priceCents,\n imageUrl: r.imageUrl,\n quantity: r.quantity,\n lineTotalCents: r.priceCents * r.quantity,\n }))\n\n return {\n basketId: basket.basketId,\n items,\n totalCents: items.reduce((sum, i) => sum + i.lineTotalCents, 0),\n itemCount: items.reduce((sum, i) => sum + i.quantity, 0),\n }\n },\n})",
|
|
51
51
|
"getItem": "export const getItem = pikkuSessionlessFunc({\n expose: true,\n description: 'Get a single item by ID.',\n input: GetItemInput,\n output: GetItemOutput,\n func: async ({ kysely }, { itemId }) => {\n const row = await kysely\n .selectFrom('item')\n .innerJoin('category', 'category.categoryId', 'item.categoryId')\n .select([\n 'item.itemId',\n 'item.name',\n 'item.slug',\n 'item.description',\n 'item.priceCents',\n 'item.stock',\n 'item.imageUrl',\n 'item.isActive',\n 'item.createdAt',\n 'item.updatedAt',\n 'category.categoryId',\n 'category.name as categoryName',\n 'category.slug as categorySlug',\n ])\n .where('item.itemId', '=', itemId)\n .executeTakeFirst()\n\n if (!row) throw new Error(`Item not found: ${itemId}`)\n\n return {\n ...row,\n category: {\n categoryId: row.categoryId,\n name: row.categoryName,\n slug: row.categorySlug,\n },\n }\n },\n})",
|
|
52
52
|
"getOrder": "// Three parameters, always: services, data, wire.\n// services — your toolbox (db, logger, queues)\n// data — the typed input, wherever it arrived from\n// wire — the protocol context (session, http, channel, rpc)\nexport const getOrder = pikkuFunc({\n expose: true,\n description: 'Get a single order. Users can only access their own orders.',\n input: GetOrderInput,\n output: GetOrderOutput,\n func: async ({ kysely }, { orderId }, { session }) => {\n const order = await kysely\n .selectFrom('order')\n .selectAll()\n .where('orderId', '=', orderId)\n .executeTakeFirst()\n\n if (!order) throw new Error('Order not found')\n if (order.userId !== session.userId && session.role !== 'admin') {\n throw new Error('Forbidden')\n }\n\n const items = await kysely\n .selectFrom('orderItem')\n .innerJoin('item', 'item.itemId', 'orderItem.itemId')\n .select([\n 'orderItem.itemId',\n 'item.name',\n 'orderItem.quantity',\n 'orderItem.unitPriceCents',\n ])\n .where('orderItem.orderId', '=', orderId)\n .execute()\n\n return {\n orderId: order.orderId,\n status: order.status,\n totalCents: order.totalCents,\n // Nullable: a walk-through order placed before an address was captured\n // has none, and returning null beats throwing on a read.\n shippingAddress: order.shippingAddress\n ? JSON.parse(order.shippingAddress)\n : null,\n items: items.map((i) => ({\n ...i,\n lineTotalCents: i.unitPriceCents * i.quantity,\n })),\n createdAt: order.createdAt,\n }\n },\n})",
|
|
53
|
+
"guideCaptureStep": "import { z } from 'zod'\nimport { pikkuScenarioStep } from '#pikku/scenarios'\n\nexport const CapturesScreenInput = z.object({\n path: z.string(),\n name: z.string(),\n})\n\nexport const CapturesScreenOutput = z.object({ captured: z.boolean() })\n\nexport const capturesScreen = pikkuScenarioStep({\n name: 'capturesScreen',\n description: 'captures the named screen',\n template: 'captures {name}',\n input: CapturesScreenInput,\n output: CapturesScreenOutput,\n browser: async (_services, { path, name }, { browser }) => {\n await browser.goto(path)\n await browser.screenshot(name, { showcase: true })\n return { captured: true }\n },\n})",
|
|
53
54
|
"httpAuthRoute": "// Public route — no auth required\nwireHTTP({ method: 'get', route: '/items', func: listItems, auth: false })\n\n// Protected route — requires a user session\nwireHTTP({ method: 'post', route: '/orders', func: createOrder, auth: true })",
|
|
54
55
|
"httpMiddleware": "// Global middleware — applies to every HTTP route\naddHTTPMiddleware('*', [\n async ({ logger }, data, next) => {\n const start = Date.now()\n await next()\n logger.info({ path: data.http?.request?.path(), ms: Date.now() - start })\n },\n])\n\n// Prefix middleware — applies only to /orders/*\naddHTTPMiddleware('/orders', [\n async (_services, _data, next) => {\n // e.g. rate-limit order creation\n await next()\n },\n])",
|
|
55
56
|
"httpRoutesWiring": "wireHTTPRoutes({ routes: { shop: shopRoutes } })",
|
package/surface.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.12.
|
|
2
|
+
"version": "0.12.162",
|
|
3
3
|
"entryPoints": [
|
|
4
4
|
{
|
|
5
5
|
"id": "app",
|
|
@@ -1171,8 +1171,8 @@
|
|
|
1171
1171
|
"via": "generated"
|
|
1172
1172
|
},
|
|
1173
1173
|
"summary": "Installs an addon into this project: its functions, wirings and scopes become part of the app, under the namespace and options given here.",
|
|
1174
|
-
"docs": "Installs an addon into this project: its functions, wirings and scopes become\npart of the app, under the namespace and options given here.\n\n`mcp: true` offers every function the addon itself declared as a tool; a list\nnames the functions to offer, checked against the ones the addon publishes.",
|
|
1175
|
-
"signature": "<Package extends string>(config: Omit<WireAddonConfig, \"package\" | \"mcp\"> & { package: Package; mcp?: boolean | AddonFunctionName<Package>[]; }) => void",
|
|
1174
|
+
"docs": "Installs an addon into this project: its functions, wirings and scopes become\npart of the app, under the namespace and options given here.\n\n`mcp: true` offers every function the addon itself declared as a tool; a list\nnames the functions to offer, checked against the ones the addon publishes.\n`expose` works the same way for `rpc.exposed`, and `false` exposes none.",
|
|
1175
|
+
"signature": "<Package extends string>(config: Omit<WireAddonConfig, \"package\" | \"mcp\" | \"expose\"> & { package: Package; mcp?: boolean | AddonFunctionName<Package>[]; expose?: boolean | AddonFunctionName<Package>[]; }) => void",
|
|
1176
1176
|
"members": [
|
|
1177
1177
|
{
|
|
1178
1178
|
"line": "auth?: boolean",
|
|
@@ -4227,6 +4227,8 @@
|
|
|
4227
4227
|
"via": "core",
|
|
4228
4228
|
"subpath": "./workflow"
|
|
4229
4229
|
},
|
|
4230
|
+
"summary": "One actor's browser session, handed to a step as `wire.browser`.",
|
|
4231
|
+
"docs": "One actor's browser session, handed to a step as `wire.browser`.\n\nOnly what every driver can honour is declared here. A driver package adds\nthe rest by declaration-merging onto this interface — `@pikku/playwright`\ncontributes `page`, `context` and `locate` — so a step written against the\nstructural surface keeps working whichever driver runs it.",
|
|
4230
4232
|
"members": [
|
|
4231
4233
|
{
|
|
4232
4234
|
"line": "actor: string",
|
|
@@ -8132,6 +8134,8 @@
|
|
|
8132
8134
|
"via": "core",
|
|
8133
8135
|
"subpath": "./workflow"
|
|
8134
8136
|
},
|
|
8137
|
+
"summary": "One actor's browser session, handed to a step as `wire.browser`.",
|
|
8138
|
+
"docs": "One actor's browser session, handed to a step as `wire.browser`.\n\nOnly what every driver can honour is declared here. A driver package adds\nthe rest by declaration-merging onto this interface — `@pikku/playwright`\ncontributes `page`, `context` and `locate` — so a step written against the\nstructural surface keeps working whichever driver runs it.",
|
|
8135
8139
|
"members": [
|
|
8136
8140
|
{
|
|
8137
8141
|
"line": "actor: string",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./chunk-FOHPRMQF-CoA4358r.js";import{M as e}from"./mermaid-parser.core-U7wquvx8.js";export{e as createArchitectureServices};
|