@pikku/cli 0.12.160 → 0.12.163
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-C__s-OXa.js} +1 -1
- package/console-app/assets/{abnfDiagram-VCTEODGH-BVwdT3Es.js → abnfDiagram-VCTEODGH-DLIFOOvF.js} +1 -1
- package/console-app/assets/architecture-7GRP2DOG-C3aOtis2.js +1 -0
- package/console-app/assets/{architectureDiagram-5GKGNRK7-XfzqZ3mW.js → architectureDiagram-5GKGNRK7-DTilS9zr.js} +1 -1
- package/console-app/assets/{blockDiagram-I7D4REHJ-B5omSqDK.js → blockDiagram-I7D4REHJ-CCTMqaSo.js} +1 -1
- package/console-app/assets/{c4Diagram-7LVT6UL2-DkPe7xCg.js → c4Diagram-7LVT6UL2-HTxceuVS.js} +1 -1
- package/console-app/assets/channel-C9rJmzgz.js +1 -0
- package/console-app/assets/{chunk-4HAMMTFA-QfSXT_X7.js → chunk-4HAMMTFA-CB4W3eSt.js} +1 -1
- package/console-app/assets/{chunk-75Z2AOVW-h7UnPWNo.js → chunk-75Z2AOVW-C9TP1VXB.js} +1 -1
- package/console-app/assets/{chunk-DU6HZSFF-VaMy-LOI.js → chunk-DU6HZSFF-84ww5mPe.js} +1 -1
- package/console-app/assets/{chunk-F27PBJKO-toywqOqS.js → chunk-F27PBJKO-B6nEGqlt.js} +1 -1
- package/console-app/assets/{chunk-GMAD6QVW-Cpa-YKLB.js → chunk-GMAD6QVW-SJ1Qwv1p.js} +1 -1
- package/console-app/assets/{chunk-GVQU2GXP-BWSHPLNL.js → chunk-GVQU2GXP-CpvfZAir.js} +1 -1
- package/console-app/assets/{chunk-IMKFNOWR-yhQzfQuj.js → chunk-IMKFNOWR-CdZpInOk.js} +1 -1
- package/console-app/assets/{chunk-L3NEJ4N5-C8pAfDlo.js → chunk-L3NEJ4N5-DDwTgcch.js} +1 -1
- package/console-app/assets/{chunk-OSK3NFVY-749yk2fa.js → chunk-OSK3NFVY-Ce8laAeV.js} +1 -1
- package/console-app/assets/{chunk-P2QGCYS3-C1Y9GyYT.js → chunk-P2QGCYS3-CfBNms3b.js} +1 -1
- package/console-app/assets/{chunk-POPQ4Y6H-DzI9aRsX.js → chunk-POPQ4Y6H-BZI0KZav.js} +1 -1
- package/console-app/assets/{chunk-PWAF6VOD-D3fAPSwz.js → chunk-PWAF6VOD-Car_F-5i.js} +1 -1
- package/console-app/assets/{chunk-SHT3W25Y-D9w7LzM9.js → chunk-SHT3W25Y-B7o3qSVw.js} +1 -1
- package/console-app/assets/{chunk-SVP7TREG-D55MjOJw.js → chunk-SVP7TREG-8bi0TugS.js} +1 -1
- package/console-app/assets/{chunk-TICWLB2K-DV8q7H-z.js → chunk-TICWLB2K-BT94BHEH.js} +1 -1
- package/console-app/assets/chunk-XXDRQBXY-CN-XariJ.js +1 -0
- package/console-app/assets/classDiagram-ZZMXUADV-C-G692c4.js +1 -0
- package/console-app/assets/classDiagram-v2-VYDZK3BY-C-G692c4.js +1 -0
- package/console-app/assets/{cose-bilkent-JH36ORCC-CLedPW9a.js → cose-bilkent-JH36ORCC-Bpn1bn9K.js} +1 -1
- package/console-app/assets/{cynefin-OW5HDTMX-CS5NKw2p.js → cynefin-OW5HDTMX-CfFkO8xq.js} +1 -1
- package/console-app/assets/{cynefinDiagram-5FMLGOSQ-DGTHW90E.js → cynefinDiagram-5FMLGOSQ-E66AVAFL.js} +1 -1
- package/console-app/assets/{dagre-BNQdos_2.js → dagre-54kLhRyV.js} +1 -1
- package/console-app/assets/{dagre-GXQ25YYZ-DHZ8wtwQ.js → dagre-GXQ25YYZ-D4En0mXW.js} +1 -1
- package/console-app/assets/{diagram-S7CK7UJ4-C41Begsy.js → diagram-S7CK7UJ4-DhFYC_I5.js} +1 -1
- package/console-app/assets/{diagram-UQ7AKVKN-CU8D-sRT.js → diagram-UQ7AKVKN-QV1teZ2Z.js} +1 -1
- package/console-app/assets/{diagram-VSXAHHWV-DTTiXYnQ.js → diagram-VSXAHHWV-CTZbzeS4.js} +1 -1
- package/console-app/assets/{diagram-VX7I27RA-BBy91pxm.js → diagram-VX7I27RA-BFoMlx0h.js} +1 -1
- package/console-app/assets/{diagram-Z3DM3KII-D50xTYe5.js → diagram-Z3DM3KII-DXYj_9Q8.js} +1 -1
- package/console-app/assets/{ebnfDiagram-PWID7BFC-BHjnFZgE.js → ebnfDiagram-PWID7BFC-C7TLD6M3.js} +1 -1
- package/console-app/assets/{erDiagram-RLTQ6QDP-B4-yVo9b.js → erDiagram-RLTQ6QDP-hPkM-ewN.js} +1 -1
- package/console-app/assets/eventmodeling-NTZA5JFV-U-EsOY6h.js +1 -0
- package/console-app/assets/flowDiagram-HODETNUW-LmjHrpKd.js +1 -0
- package/console-app/assets/{ganttDiagram-EL5Y4UJY-D1T-2BlO.js → ganttDiagram-EL5Y4UJY-B6TmOQZX.js} +1 -1
- package/console-app/assets/{gitGraph-4MIJSDKK-ClqKTUfQ.js → gitGraph-4MIJSDKK-BwbHr20B.js} +1 -1
- package/console-app/assets/{gitGraphDiagram-WWUBYQGX-ruq2MAhM.js → gitGraphDiagram-WWUBYQGX-Dl1TcmWc.js} +1 -1
- package/console-app/assets/{graphlib-D-vLYPdw.js → graphlib-DHZpPJUN.js} +1 -1
- package/console-app/assets/{index-BIEZPuyK.js → index-BzStIuLU.js} +137 -137
- package/console-app/assets/{info-A6RAGUB7-BGI-8HNB.js → info-A6RAGUB7-D708VGlV.js} +1 -1
- package/console-app/assets/{infoDiagram-27XIBGKW-BGURgKHv.js → infoDiagram-27XIBGKW-UHD7ySe3.js} +1 -1
- package/console-app/assets/{ishikawaDiagram-5VMMS53U-DzgAaPTR.js → ishikawaDiagram-5VMMS53U-GyFZr765.js} +1 -1
- package/console-app/assets/{journeyDiagram-3NMN7TZE-BsyWad8z.js → journeyDiagram-3NMN7TZE-CoewHpEg.js} +1 -1
- package/console-app/assets/{kanban-definition-UXKFOSKX-g1nO2rWF.js → kanban-definition-UXKFOSKX-F0W6Aec5.js} +1 -1
- package/console-app/assets/{line-CeFoQ5y-.js → line-C4wYKh6f.js} +1 -1
- package/console-app/assets/{linear-C4Pk-YMX.js → linear-nPQacEjt.js} +1 -1
- package/console-app/assets/{mermaid-parser.core-U7wquvx8.js → mermaid-parser.core-BVBt0Hmw.js} +3 -3
- package/console-app/assets/{mermaid.core-8TRpFRm9.js → mermaid.core-BMrHbMBm.js} +4 -4
- package/console-app/assets/{mindmap-definition-YA3MSWOX-C7lzwqBX.js → mindmap-definition-YA3MSWOX-Dhdn4hmh.js} +1 -1
- package/console-app/assets/{packet-AYTQ26CC-DiQV_rU3.js → packet-AYTQ26CC-CleVGuC-.js} +1 -1
- package/console-app/assets/{pegDiagram-XKGWAZYB-63ajP7-W.js → pegDiagram-XKGWAZYB-NDJ5URs9.js} +1 -1
- package/console-app/assets/{pie-WAS4IAKB-B5q_o6dr.js → pie-WAS4IAKB-DCgq6z8V.js} +1 -1
- package/console-app/assets/{pieDiagram-E7YTZNPT-BTbvj-by.js → pieDiagram-E7YTZNPT-BPo__c-e.js} +1 -1
- package/console-app/assets/{quadrantDiagram-AXDQQJYC-CulqsAYd.js → quadrantDiagram-AXDQQJYC-C6AlGJWn.js} +1 -1
- package/console-app/assets/{radar-RG4KPBEZ-CW_KoURS.js → radar-RG4KPBEZ-iKELPo6S.js} +1 -1
- package/console-app/assets/{railroad-74A4TZTK-CUmF6uBQ.js → railroad-74A4TZTK-D7o-4Y2z.js} +1 -1
- package/console-app/assets/railroad-abnf-HS5TGJTU-SJ0ZNV52.js +1 -0
- package/console-app/assets/railroad-ebnf-LZEXJU2U-CoxgM6s2.js +1 -0
- package/console-app/assets/railroad-peg-WCYAUIDC-Dt1jr0ie.js +1 -0
- package/console-app/assets/{railroadDiagram-O6MQD6OU-WlkBu_N3.js → railroadDiagram-O6MQD6OU-Bxb416Ip.js} +1 -1
- package/console-app/assets/{requirementDiagram-BXWQKSXE-CJK_CbPR.js → requirementDiagram-BXWQKSXE-wpPz84xe.js} +1 -1
- package/console-app/assets/{sankeyDiagram-P5KCCOFB-C466WOH8.js → sankeyDiagram-P5KCCOFB-DCtqI-U8.js} +1 -1
- package/console-app/assets/{sequenceDiagram-WJ2MYXX4-CV0dCcj0.js → sequenceDiagram-WJ2MYXX4-B9qErfQU.js} +1 -1
- package/console-app/assets/{src-P4Nw8sY0.js → src-CrUEtLgb.js} +1 -1
- package/console-app/assets/{stateDiagram-D77RDMKH-HaLGm8V9.js → stateDiagram-D77RDMKH-DVQO4UZZ.js} +1 -1
- package/console-app/assets/stateDiagram-v2-MP3YSRHH-qOQfgOOB.js +1 -0
- package/console-app/assets/{swimlanes-42K2YHIH-Bi-O5vWa.js → swimlanes-42K2YHIH-CfBqlUg-.js} +1 -1
- package/console-app/assets/swimlanesDiagram-VR7AAH4N-D6fTU5Cq.js +8 -0
- package/console-app/assets/{timeline-definition-24CTP7MA-B4h-gx-i.js → timeline-definition-24CTP7MA-CPFn_B-h.js} +1 -1
- package/console-app/assets/{treeView-Q6P3EWNA-CXJ_pHQw.js → treeView-Q6P3EWNA-CVWAH-EI.js} +1 -1
- package/console-app/assets/{treemap-WGGIJYW6-M84p2a_3.js → treemap-WGGIJYW6-DEBgfaYx.js} +1 -1
- package/console-app/assets/{vennDiagram-4TSXK5OY-BesF4k_r.js → vennDiagram-4TSXK5OY-BA4GGrwY.js} +1 -1
- package/console-app/assets/{wardley-WFR3VGLG-n9ulickP.js → wardley-WFR3VGLG-TajUo-aF.js} +1 -1
- package/console-app/assets/{wardleyDiagram-VM6X3IG4-BG0nnWDf.js → wardleyDiagram-VM6X3IG4-Bd1y8DdK.js} +1 -1
- package/console-app/assets/{xychartDiagram-S5SC5T6Z-BtOW7fpF.js → xychartDiagram-S5SC5T6Z-CWQmkOFg.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-meta.gen.json +20 -2
- 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 +16 -16
- 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/schemas/schemas/KnowledgePlanProgressOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/KnowledgePlanSetOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/KnowledgePlanShowOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +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/cli.wiring.js +20 -2
- package/dist/src/deploy/analyzer/analyzer.js +7 -1
- package/dist/src/functions/commands/dev-credentials.d.ts +18 -0
- package/dist/src/functions/commands/dev-credentials.js +59 -0
- package/dist/src/functions/commands/dev.js +11 -2
- package/dist/src/functions/commands/install-addon.d.ts +45 -0
- package/dist/src/functions/commands/install-addon.js +225 -0
- package/dist/src/functions/commands/knowledge-plan.d.ts +9 -0
- package/dist/src/functions/commands/knowledge-plan.js +13 -3
- package/dist/src/functions/commands/new-addon.d.ts +47 -1
- package/dist/src/functions/commands/new-addon.js +284 -106
- package/dist/src/functions/commands/serve.js +7 -2
- package/dist/src/functions/db/better-auth-schema.d.ts +1 -0
- package/dist/src/functions/db/better-auth-schema.js +75 -2
- package/dist/src/functions/db/ensure-db-types.d.ts +12 -0
- package/dist/src/functions/db/ensure-db-types.js +29 -0
- package/dist/src/functions/knowledge/console-url.d.ts +13 -0
- package/dist/src/functions/knowledge/console-url.js +18 -0
- package/dist/src/functions/knowledge/render.d.ts +7 -3
- package/dist/src/functions/knowledge/render.js +10 -3
- package/dist/src/functions/knowledge/schemas.d.ts +3 -0
- package/dist/src/functions/knowledge/schemas.js +4 -3
- 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 +60 -3
- package/dist/src/functions/workflows/all.workflow.js +7 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/snippets-meta.json +1 -0
- package/snippets.json +1 -0
- package/surface.json +37 -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
|
@@ -106,11 +106,28 @@ function fakeSecretService() {
|
|
|
106
106
|
setSecret: async () => { },
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
+
// Better Auth checks its tables against the database the moment it is built,
|
|
110
|
+
// and logs "Database schema mismatch" when they are missing. Here they are
|
|
111
|
+
// always missing: the database is a scratch one the auth migrations are about
|
|
112
|
+
// to run into. The check reaches the database through `connection()` alone,
|
|
113
|
+
// so parking that call keeps the instance quiet without touching the queries
|
|
114
|
+
// the migrator runs.
|
|
115
|
+
export function withoutAuthSchemaCheck(kysely) {
|
|
116
|
+
return new Proxy(kysely, {
|
|
117
|
+
get: (target, prop) => {
|
|
118
|
+
if (prop === 'connection') {
|
|
119
|
+
return () => ({ execute: () => new Promise(() => { }) });
|
|
120
|
+
}
|
|
121
|
+
const value = Reflect.get(target, prop, target);
|
|
122
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
}
|
|
109
126
|
function schemaServicesStub(kysely, logger) {
|
|
110
127
|
const variables = new LocalVariablesService();
|
|
111
128
|
const secrets = fakeSecretService();
|
|
112
129
|
const base = {
|
|
113
|
-
kysely,
|
|
130
|
+
kysely: withoutAuthSchemaCheck(kysely),
|
|
114
131
|
logger,
|
|
115
132
|
secrets,
|
|
116
133
|
variables,
|
|
@@ -144,6 +161,62 @@ async function loadAuthConfig(opts) {
|
|
|
144
161
|
return undefined;
|
|
145
162
|
return userCreateConfig(new LocalVariablesService());
|
|
146
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Build the auth instance without a plugin's background init being able to kill
|
|
166
|
+
* the process.
|
|
167
|
+
*
|
|
168
|
+
* Reading the schema means reading `options`, which Better Auth assembles while
|
|
169
|
+
* the constructor runs — but from 1.7 a plugin's `init` also starts real work
|
|
170
|
+
* and does not wait for it. The OAuth provider behind `@better-auth/mcp` seeds
|
|
171
|
+
* its `oauthResource` rows this way. Here that work has nowhere to go: the
|
|
172
|
+
* database it is handed is a throwaway whose auth tables do not exist yet, and
|
|
173
|
+
* on the SQLite path the handle is closed as soon as the options have been
|
|
174
|
+
* read. The seed then rejects with nothing awaiting it, and Node's default for
|
|
175
|
+
* an unhandled rejection is to terminate — so `pikku db generate` died on
|
|
176
|
+
* `database is not open`, from a write the schema derivation never wanted, in a
|
|
177
|
+
* project whose only offence was configuring MCP.
|
|
178
|
+
*
|
|
179
|
+
* Rejections are reported rather than swallowed: they say a plugin tried to
|
|
180
|
+
* touch the database while being introspected, which is worth seeing, but never
|
|
181
|
+
* worth failing the command over. Whatever the plugin was doing is irrelevant
|
|
182
|
+
* to the shape of its tables, which is all that is being read.
|
|
183
|
+
*
|
|
184
|
+
* The handler is installed only around the call and only added to whatever the
|
|
185
|
+
* host already has, so a real unhandled rejection anywhere else still behaves
|
|
186
|
+
* exactly as it did.
|
|
187
|
+
*/
|
|
188
|
+
async function withoutPluginInitCrashing(build) {
|
|
189
|
+
const existing = process.listeners('unhandledRejection');
|
|
190
|
+
const swallow = (reason) => {
|
|
191
|
+
const message = reason instanceof Error ? reason.message : String(reason);
|
|
192
|
+
debugInitRejection(message);
|
|
193
|
+
};
|
|
194
|
+
for (const listener of existing) {
|
|
195
|
+
process.off('unhandledRejection', listener);
|
|
196
|
+
}
|
|
197
|
+
process.on('unhandledRejection', swallow);
|
|
198
|
+
try {
|
|
199
|
+
const instance = await build();
|
|
200
|
+
// One turn of the loop, so an init that rejects immediately does so while
|
|
201
|
+
// the guard is still the only listener. A slower one is caught by the
|
|
202
|
+
// `swallow` handler that outlives this only if the host had none of its
|
|
203
|
+
// own — which is why the originals go back on before it comes off.
|
|
204
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
205
|
+
return instance;
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
for (const listener of existing) {
|
|
209
|
+
process.on('unhandledRejection', listener);
|
|
210
|
+
}
|
|
211
|
+
process.off('unhandledRejection', swallow);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function debugInitRejection(message) {
|
|
215
|
+
if (process.env.PIKKU_DEBUG) {
|
|
216
|
+
// eslint-disable-next-line no-console
|
|
217
|
+
console.debug(`[pikku] a Better Auth plugin's init failed while its schema was being read, which does not affect the schema: ${message}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
147
220
|
export async function loadAuthOptions(opts) {
|
|
148
221
|
const sourceFile = findAuthSourceFile(opts.rootDir, opts.srcDirectories);
|
|
149
222
|
if (!sourceFile)
|
|
@@ -153,7 +226,7 @@ export async function loadAuthOptions(opts) {
|
|
|
153
226
|
return null;
|
|
154
227
|
const services = schemaServicesStub(opts.kysely, opts.logger);
|
|
155
228
|
services.config = await loadAuthConfig(opts);
|
|
156
|
-
const instance = await factory(services);
|
|
229
|
+
const instance = await withoutPluginInitCrashing(() => factory(services));
|
|
157
230
|
const options = instance.options;
|
|
158
231
|
return options ?? null;
|
|
159
232
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { resolveDb } from './local-db.js';
|
|
2
|
+
/**
|
|
3
|
+
* Make sure `db/schema.gen.ts` exists before anything is typechecked.
|
|
4
|
+
*
|
|
5
|
+
* A fresh project's services import `DB` from `#pikku/db/schema.gen.js`, but
|
|
6
|
+
* only `pikku db migrate` / `pikku db codegen` used to write it, so the first
|
|
7
|
+
* `pikku all` failed on a module that had not been generated yet. The types
|
|
8
|
+
* come from the migrations alone (a scratch database), so nothing needs to be
|
|
9
|
+
* reachable. If even that fails, an empty `DB` keeps the import resolvable
|
|
10
|
+
* until `db migrate` writes the real one.
|
|
11
|
+
*/
|
|
12
|
+
export declare function ensureDbTypes(rootDir: string, outDir: string, runtimeDir?: string, dbConfig?: Parameters<typeof resolveDb>[4]): Promise<'present' | 'generated' | 'stubbed' | 'no-db'>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { resolveDb, migrateAndCodegen } from './local-db.js';
|
|
4
|
+
/**
|
|
5
|
+
* Make sure `db/schema.gen.ts` exists before anything is typechecked.
|
|
6
|
+
*
|
|
7
|
+
* A fresh project's services import `DB` from `#pikku/db/schema.gen.js`, but
|
|
8
|
+
* only `pikku db migrate` / `pikku db codegen` used to write it, so the first
|
|
9
|
+
* `pikku all` failed on a module that had not been generated yet. The types
|
|
10
|
+
* come from the migrations alone (a scratch database), so nothing needs to be
|
|
11
|
+
* reachable. If even that fails, an empty `DB` keeps the import resolvable
|
|
12
|
+
* until `db migrate` writes the real one.
|
|
13
|
+
*/
|
|
14
|
+
export async function ensureDbTypes(rootDir, outDir, runtimeDir, dbConfig) {
|
|
15
|
+
const resolved = resolveDb({}, rootDir, outDir, runtimeDir, dbConfig);
|
|
16
|
+
if (!resolved)
|
|
17
|
+
return 'no-db';
|
|
18
|
+
if (existsSync(resolved.schemaFile))
|
|
19
|
+
return 'present';
|
|
20
|
+
try {
|
|
21
|
+
await migrateAndCodegen(resolved, { scratch: true });
|
|
22
|
+
if (existsSync(resolved.schemaFile))
|
|
23
|
+
return 'generated';
|
|
24
|
+
}
|
|
25
|
+
catch { }
|
|
26
|
+
mkdirSync(dirname(resolved.schemaFile), { recursive: true });
|
|
27
|
+
writeFileSync(resolved.schemaFile, 'export interface DB {}\n', 'utf8');
|
|
28
|
+
return 'stubbed';
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ConsoleUrlOutput: z.ZodObject<{
|
|
3
|
+
consoleUrl: z.ZodOptional<z.ZodString>;
|
|
4
|
+
}, z.core.$strip>;
|
|
5
|
+
/**
|
|
6
|
+
* Where the console shows a knowledge file: the running dev server's address
|
|
7
|
+
* when there is one, the default port otherwise. The id keeps its slashes so the
|
|
8
|
+
* link reads as the path it names.
|
|
9
|
+
*/
|
|
10
|
+
export declare const knowledgeConsoleUrl: (config: {
|
|
11
|
+
rootDir: string;
|
|
12
|
+
runtimeDir?: string;
|
|
13
|
+
}, path: string) => string | undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { readDevAddress } from '../commands/dev-address.js';
|
|
4
|
+
const FALLBACK_ORIGIN = 'http://localhost:3000';
|
|
5
|
+
export const ConsoleUrlOutput = z.object({ consoleUrl: z.string().optional() });
|
|
6
|
+
/**
|
|
7
|
+
* Where the console shows a knowledge file: the running dev server's address
|
|
8
|
+
* when there is one, the default port otherwise. The id keeps its slashes so the
|
|
9
|
+
* link reads as the path it names.
|
|
10
|
+
*/
|
|
11
|
+
export const knowledgeConsoleUrl = (config, path) => {
|
|
12
|
+
if (!path)
|
|
13
|
+
return undefined;
|
|
14
|
+
const runtimeDir = config.runtimeDir ?? join(config.rootDir, '.pikku-runtime');
|
|
15
|
+
const origin = (readDevAddress(runtimeDir)?.apiUrl ?? FALLBACK_ORIGIN).replace(/\/+$/, '');
|
|
16
|
+
const id = encodeURIComponent(path).replace(/%2F/g, '/');
|
|
17
|
+
return `${origin}/console/knowledge?id=${id}`;
|
|
18
|
+
};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { KnowledgeIndexResult, KnowledgePlanDeferResult, KnowledgePlanProgressResult, KnowledgePlanSchemaResult, KnowledgePlanSetResult, KnowledgePlanShowResult, KnowledgeReconcileResult, KnowledgeValidateResult } from '@pikku/knowledge';
|
|
2
2
|
export declare const renderKnowledgeValidate: (_services: unknown, { ok, notes, findings }: KnowledgeValidateResult) => void;
|
|
3
3
|
export declare const renderKnowledgeIndex: (_services: unknown, { ok, check, files }: KnowledgeIndexResult) => void;
|
|
4
|
+
type ConsoleUrl = {
|
|
5
|
+
consoleUrl?: string;
|
|
6
|
+
};
|
|
4
7
|
export declare const renderKnowledgePlanSchema: (_services: unknown, { schema }: KnowledgePlanSchemaResult) => void;
|
|
5
|
-
export declare const renderKnowledgePlanShow: (_services: unknown, { ok, path, body }: KnowledgePlanShowResult) => void;
|
|
6
|
-
export declare const renderKnowledgePlanProgress: (_services: unknown, { ok, path, message, done, missing, deferred, problems, }: KnowledgePlanProgressResult) => void;
|
|
7
|
-
export declare const renderKnowledgePlanSet: (_services: unknown, { ok, path, problems, schema }: KnowledgePlanSetResult) => void;
|
|
8
|
+
export declare const renderKnowledgePlanShow: (_services: unknown, { ok, path, body, consoleUrl }: KnowledgePlanShowResult & ConsoleUrl) => void;
|
|
9
|
+
export declare const renderKnowledgePlanProgress: (_services: unknown, { ok, path, message, done, missing, deferred, problems, consoleUrl, }: KnowledgePlanProgressResult & ConsoleUrl) => void;
|
|
10
|
+
export declare const renderKnowledgePlanSet: (_services: unknown, { ok, path, problems, schema, consoleUrl, }: KnowledgePlanSetResult & ConsoleUrl) => void;
|
|
8
11
|
export declare const renderKnowledgePlanDefer: (_services: unknown, { ok, message }: KnowledgePlanDeferResult) => void;
|
|
9
12
|
/**
|
|
10
13
|
* What to do next, and — when only a person can settle it — the question to put to
|
|
@@ -17,3 +20,4 @@ export declare const renderKnowledgePlanDefer: (_services: unknown, { ok, messag
|
|
|
17
20
|
* better reads the same answer as JSON.
|
|
18
21
|
*/
|
|
19
22
|
export declare const renderKnowledgeReconcile: (_services: unknown, { kind, reason, note, hold, notes, question, required, satisfied, }: KnowledgeReconcileResult) => void;
|
|
23
|
+
export {};
|
|
@@ -82,10 +82,14 @@ export const renderKnowledgeIndex = (_services, { ok, check, files }) => {
|
|
|
82
82
|
process.exitCode = 1;
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
|
+
const printConsoleUrl = (url) => {
|
|
86
|
+
if (url)
|
|
87
|
+
console.log(`${dim('see it in the console:')} ${url}`);
|
|
88
|
+
};
|
|
85
89
|
export const renderKnowledgePlanSchema = (_services, { schema }) => {
|
|
86
90
|
console.log(schema);
|
|
87
91
|
};
|
|
88
|
-
export const renderKnowledgePlanShow = (_services, { ok, path, body }) => {
|
|
92
|
+
export const renderKnowledgePlanShow = (_services, { ok, path, body, consoleUrl }) => {
|
|
89
93
|
if (!ok) {
|
|
90
94
|
console.log(`${removed('✗')} ${body}`);
|
|
91
95
|
process.exitCode = 1;
|
|
@@ -93,6 +97,7 @@ export const renderKnowledgePlanShow = (_services, { ok, path, body }) => {
|
|
|
93
97
|
}
|
|
94
98
|
console.log(dim(path));
|
|
95
99
|
console.log(body);
|
|
100
|
+
printConsoleUrl(consoleUrl);
|
|
96
101
|
};
|
|
97
102
|
const list = (label, entries, colour) => {
|
|
98
103
|
if (entries.length === 0)
|
|
@@ -102,13 +107,14 @@ const list = (label, entries, colour) => {
|
|
|
102
107
|
console.log(` ${entry}`);
|
|
103
108
|
console.log();
|
|
104
109
|
};
|
|
105
|
-
export const renderKnowledgePlanProgress = (_services, { ok, path, message, done, missing, deferred, problems, }) => {
|
|
110
|
+
export const renderKnowledgePlanProgress = (_services, { ok, path, message, done, missing, deferred, problems, consoleUrl, }) => {
|
|
106
111
|
if (message) {
|
|
107
112
|
console.log(`${removed('✗')} ${message}`);
|
|
108
113
|
process.exitCode = 1;
|
|
109
114
|
return;
|
|
110
115
|
}
|
|
111
116
|
console.log(dim(path));
|
|
117
|
+
printConsoleUrl(consoleUrl);
|
|
112
118
|
console.log();
|
|
113
119
|
list('DONE', done, added);
|
|
114
120
|
list('MISSING', missing, removed);
|
|
@@ -134,10 +140,11 @@ export const renderKnowledgePlanProgress = (_services, { ok, path, message, done
|
|
|
134
140
|
// and not only by whoever is reading the output.
|
|
135
141
|
process.exitCode = 1;
|
|
136
142
|
};
|
|
137
|
-
export const renderKnowledgePlanSet = (_services, { ok, path, problems, schema }) => {
|
|
143
|
+
export const renderKnowledgePlanSet = (_services, { ok, path, problems, schema, consoleUrl, }) => {
|
|
138
144
|
if (ok) {
|
|
139
145
|
console.log(`${added('✓')} plan written to ${path}`);
|
|
140
146
|
console.log(dim('the build is measured against it'));
|
|
147
|
+
printConsoleUrl(consoleUrl);
|
|
141
148
|
return;
|
|
142
149
|
}
|
|
143
150
|
console.log(`${removed('✗')} not written:`);
|
|
@@ -64,6 +64,7 @@ export declare const KnowledgePlanProgressOutputSchema: import("zod").ZodObject<
|
|
|
64
64
|
missing: import("zod").ZodArray<import("zod").ZodString>;
|
|
65
65
|
deferred: import("zod").ZodArray<import("zod").ZodString>;
|
|
66
66
|
problems: import("zod").ZodArray<import("zod").ZodString>;
|
|
67
|
+
consoleUrl: import("zod").ZodOptional<import("zod").ZodString>;
|
|
67
68
|
}, import("zod/v4/core").$strip>;
|
|
68
69
|
export declare const KnowledgePlanShowInputSchema: import("zod").ZodObject<{
|
|
69
70
|
milestone: import("zod").ZodString;
|
|
@@ -73,6 +74,7 @@ export declare const KnowledgePlanShowOutputSchema: import("zod").ZodObject<{
|
|
|
73
74
|
ok: import("zod").ZodBoolean;
|
|
74
75
|
path: import("zod").ZodString;
|
|
75
76
|
body: import("zod").ZodString;
|
|
77
|
+
consoleUrl: import("zod").ZodOptional<import("zod").ZodString>;
|
|
76
78
|
}, import("zod/v4/core").$strip>;
|
|
77
79
|
export declare const KnowledgePlanSetInputSchema: import("zod").ZodObject<{
|
|
78
80
|
milestone: import("zod").ZodString;
|
|
@@ -83,6 +85,7 @@ export declare const KnowledgePlanSetOutputSchema: import("zod").ZodObject<{
|
|
|
83
85
|
path: import("zod").ZodString;
|
|
84
86
|
problems: import("zod").ZodArray<import("zod").ZodString>;
|
|
85
87
|
schema: import("zod").ZodOptional<import("zod").ZodString>;
|
|
88
|
+
consoleUrl: import("zod").ZodOptional<import("zod").ZodString>;
|
|
86
89
|
}, import("zod/v4/core").$strip>;
|
|
87
90
|
export declare const KnowledgePlanDeferInputSchema: import("zod").ZodObject<{
|
|
88
91
|
milestone: import("zod").ZodString;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KnowledgeIndexInput, KnowledgeIndexOutput, KnowledgePlanDeferInput, KnowledgePlanDeferOutput, KnowledgePlanProgressInput, KnowledgePlanProgressOutput, KnowledgePlanSchemaInput, KnowledgePlanSchemaOutput, KnowledgePlanSetInput, KnowledgePlanSetOutput, KnowledgePlanShowInput, KnowledgePlanShowOutput, KnowledgeReconcileInput, KnowledgeReconcileOutput, KnowledgeValidateInput, KnowledgeValidateOutput, } from '@pikku/knowledge';
|
|
2
|
+
import { ConsoleUrlOutput } from './console-url.js';
|
|
2
3
|
/**
|
|
3
4
|
* The knowledge command schemas, re-bound to variables declared HERE rather than
|
|
4
5
|
* imported straight into the command files.
|
|
@@ -26,11 +27,11 @@ export const KnowledgeValidateOutputSchema = KnowledgeValidateOutput;
|
|
|
26
27
|
export const KnowledgePlanSchemaInputSchema = KnowledgePlanSchemaInput;
|
|
27
28
|
export const KnowledgePlanSchemaOutputSchema = KnowledgePlanSchemaOutput;
|
|
28
29
|
export const KnowledgePlanProgressInputSchema = KnowledgePlanProgressInput;
|
|
29
|
-
export const KnowledgePlanProgressOutputSchema = KnowledgePlanProgressOutput;
|
|
30
|
+
export const KnowledgePlanProgressOutputSchema = KnowledgePlanProgressOutput.extend(ConsoleUrlOutput.shape);
|
|
30
31
|
export const KnowledgePlanShowInputSchema = KnowledgePlanShowInput;
|
|
31
|
-
export const KnowledgePlanShowOutputSchema = KnowledgePlanShowOutput;
|
|
32
|
+
export const KnowledgePlanShowOutputSchema = KnowledgePlanShowOutput.extend(ConsoleUrlOutput.shape);
|
|
32
33
|
export const KnowledgePlanSetInputSchema = KnowledgePlanSetInput;
|
|
33
|
-
export const KnowledgePlanSetOutputSchema = KnowledgePlanSetOutput;
|
|
34
|
+
export const KnowledgePlanSetOutputSchema = KnowledgePlanSetOutput.extend(ConsoleUrlOutput.shape);
|
|
34
35
|
export const KnowledgePlanDeferInputSchema = KnowledgePlanDeferInput;
|
|
35
36
|
export const KnowledgePlanDeferOutputSchema = KnowledgePlanDeferOutput;
|
|
36
37
|
export const KnowledgeReconcileInputSchema = KnowledgeReconcileInput;
|
|
@@ -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;
|