@pikku/cli 0.12.151 → 0.12.153
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-CxjgE40i.js → HelpPanel-0XQ4CyKC.js} +1 -1
- package/console-app/assets/{abnfDiagram-VCTEODGH-UPW1PlxM.js → abnfDiagram-VCTEODGH-DZTF_2aX.js} +1 -1
- package/console-app/assets/architecture-7GRP2DOG-NotVOJ5Y.js +1 -0
- package/console-app/assets/{architectureDiagram-5GKGNRK7-B3XFrvZk.js → architectureDiagram-5GKGNRK7-Re4-6X-k.js} +1 -1
- package/console-app/assets/{blockDiagram-I7D4REHJ-Ca0v9UJQ.js → blockDiagram-I7D4REHJ-Dbj7SnRK.js} +1 -1
- package/console-app/assets/{c4Diagram-7LVT6UL2-CLewVsj_.js → c4Diagram-7LVT6UL2-DUr02Wxh.js} +1 -1
- package/console-app/assets/channel-DU63_zXh.js +1 -0
- package/console-app/assets/{chunk-4HAMMTFA-BwhbhOD9.js → chunk-4HAMMTFA-DjatzNf_.js} +1 -1
- package/console-app/assets/{chunk-75Z2AOVW-C7nAgNk0.js → chunk-75Z2AOVW-BGsmWEdU.js} +1 -1
- package/console-app/assets/{chunk-DU6HZSFF-D4yYAcHt.js → chunk-DU6HZSFF-CC7WiVgI.js} +1 -1
- package/console-app/assets/{chunk-F27PBJKO-UHllOPps.js → chunk-F27PBJKO-BATuW9Ej.js} +1 -1
- package/console-app/assets/{chunk-GMAD6QVW-C0l_vm7T.js → chunk-GMAD6QVW-CgHNo00B.js} +1 -1
- package/console-app/assets/{chunk-GVQU2GXP-h-H2Oird.js → chunk-GVQU2GXP-VT_xckd9.js} +1 -1
- package/console-app/assets/{chunk-IMKFNOWR-DJ_W9CSg.js → chunk-IMKFNOWR-BhSVbWtF.js} +1 -1
- package/console-app/assets/{chunk-L3NEJ4N5-Ce9oniwE.js → chunk-L3NEJ4N5-HUF6a3Xl.js} +1 -1
- package/console-app/assets/{chunk-OSK3NFVY-CdGE5qxS.js → chunk-OSK3NFVY-C_LPDGIB.js} +1 -1
- package/console-app/assets/{chunk-P2QGCYS3-DK1pHDdz.js → chunk-P2QGCYS3-lWDBgw4Q.js} +1 -1
- package/console-app/assets/{chunk-POPQ4Y6H-DjevEFNo.js → chunk-POPQ4Y6H--6JTzmZJ.js} +1 -1
- package/console-app/assets/{chunk-PWAF6VOD-BVF5N1No.js → chunk-PWAF6VOD-C1GqaJJs.js} +1 -1
- package/console-app/assets/{chunk-SHT3W25Y-BX8We-wN.js → chunk-SHT3W25Y-Dd_4Zpdj.js} +1 -1
- package/console-app/assets/{chunk-SVP7TREG-Cl0GgAPC.js → chunk-SVP7TREG-B8OY7dfD.js} +1 -1
- package/console-app/assets/{chunk-TICWLB2K-IWZAWDhu.js → chunk-TICWLB2K-B8S7Hmnu.js} +1 -1
- package/console-app/assets/chunk-XXDRQBXY-BLuHuEZN.js +1 -0
- package/console-app/assets/classDiagram-ZZMXUADV-BTYfUi7u.js +1 -0
- package/console-app/assets/classDiagram-v2-VYDZK3BY-BTYfUi7u.js +1 -0
- package/console-app/assets/{cose-bilkent-JH36ORCC-GsQ0JAnL.js → cose-bilkent-JH36ORCC-C6RM8oPO.js} +1 -1
- package/console-app/assets/{cynefin-OW5HDTMX-hZsAZp_5.js → cynefin-OW5HDTMX-COh9rFYY.js} +1 -1
- package/console-app/assets/{cynefinDiagram-5FMLGOSQ-CsyMovx1.js → cynefinDiagram-5FMLGOSQ-Dd9AR17w.js} +1 -1
- package/console-app/assets/{dagre-BP8XEFz-.js → dagre-BDMvDAer.js} +1 -1
- package/console-app/assets/{dagre-GXQ25YYZ-Jg5285rx.js → dagre-GXQ25YYZ-C_nBUPgr.js} +1 -1
- package/console-app/assets/{diagram-S7CK7UJ4-n9JiR8HK.js → diagram-S7CK7UJ4-BGOobQeC.js} +1 -1
- package/console-app/assets/{diagram-UQ7AKVKN-Cde-dgbI.js → diagram-UQ7AKVKN-CAF_vcj0.js} +1 -1
- package/console-app/assets/{diagram-VSXAHHWV-CPZUg4FP.js → diagram-VSXAHHWV-q-aY0Nsc.js} +1 -1
- package/console-app/assets/{diagram-VX7I27RA-B2rCDWvn.js → diagram-VX7I27RA-CnUibSOe.js} +1 -1
- package/console-app/assets/{diagram-Z3DM3KII-UwO0hte3.js → diagram-Z3DM3KII-DY0V5kOJ.js} +1 -1
- package/console-app/assets/{ebnfDiagram-PWID7BFC-BGJ_PBlS.js → ebnfDiagram-PWID7BFC-CXp4CmEF.js} +1 -1
- package/console-app/assets/{erDiagram-RLTQ6QDP-CKsTScr3.js → erDiagram-RLTQ6QDP-CKnfXmPl.js} +1 -1
- package/console-app/assets/eventmodeling-NTZA5JFV-CBfQhnG8.js +1 -0
- package/console-app/assets/flowDiagram-HODETNUW-BnY3G7p6.js +1 -0
- package/console-app/assets/{ganttDiagram-EL5Y4UJY-koeTkIEA.js → ganttDiagram-EL5Y4UJY-D6v_RJ7o.js} +1 -1
- package/console-app/assets/{gitGraph-4MIJSDKK-DyRPbcM4.js → gitGraph-4MIJSDKK-y3kWDddY.js} +1 -1
- package/console-app/assets/{gitGraphDiagram-WWUBYQGX-DSIejrYw.js → gitGraphDiagram-WWUBYQGX-CBaE24KN.js} +1 -1
- package/console-app/assets/{graphlib-BpQ_697T.js → graphlib-DAA_TPmU.js} +1 -1
- package/console-app/assets/{index-Du9_fRSw.js → index-HuTd6kcC.js} +147 -147
- package/console-app/assets/{info-A6RAGUB7-C63f9an_.js → info-A6RAGUB7-BvxfRJ9-.js} +1 -1
- package/console-app/assets/{infoDiagram-27XIBGKW-Dz5gMcUF.js → infoDiagram-27XIBGKW-BlFmgW96.js} +1 -1
- package/console-app/assets/{ishikawaDiagram-5VMMS53U-m-nTAZTH.js → ishikawaDiagram-5VMMS53U-Dpwhnwwq.js} +1 -1
- package/console-app/assets/{journeyDiagram-3NMN7TZE-C7mjFY7i.js → journeyDiagram-3NMN7TZE-iOSeOQma.js} +1 -1
- package/console-app/assets/{kanban-definition-UXKFOSKX-Cm7PqOOP.js → kanban-definition-UXKFOSKX-DFGTB8S5.js} +1 -1
- package/console-app/assets/{line-RZNRGurC.js → line-B_5qZKoM.js} +1 -1
- package/console-app/assets/{linear-C2IGWMlF.js → linear-BmXUYu4J.js} +1 -1
- package/console-app/assets/{mermaid-parser.core-DN1yDqgB.js → mermaid-parser.core-DyPi3Lbr.js} +3 -3
- package/console-app/assets/{mermaid.core-DDRs3TbC.js → mermaid.core-S4y9jX8K.js} +4 -4
- package/console-app/assets/{mindmap-definition-YA3MSWOX-o6riOwlF.js → mindmap-definition-YA3MSWOX-Bl09mCaS.js} +1 -1
- package/console-app/assets/{packet-AYTQ26CC-B89F6gXG.js → packet-AYTQ26CC-B5zoasmU.js} +1 -1
- package/console-app/assets/{pegDiagram-XKGWAZYB-BQ1AAIaV.js → pegDiagram-XKGWAZYB-CAa0SOHf.js} +1 -1
- package/console-app/assets/{pie-WAS4IAKB-CzuwQlQz.js → pie-WAS4IAKB-C91xXCXY.js} +1 -1
- package/console-app/assets/{pieDiagram-E7YTZNPT-DlcGHWGT.js → pieDiagram-E7YTZNPT-CmUHVYwz.js} +1 -1
- package/console-app/assets/{quadrantDiagram-AXDQQJYC-DdITwqw-.js → quadrantDiagram-AXDQQJYC-XWsej4ss.js} +1 -1
- package/console-app/assets/{radar-RG4KPBEZ-DlJ29jAN.js → radar-RG4KPBEZ-B7ieCnSw.js} +1 -1
- package/console-app/assets/{railroad-74A4TZTK-BL49fdM8.js → railroad-74A4TZTK-KTKjMg4U.js} +1 -1
- package/console-app/assets/railroad-abnf-HS5TGJTU-e9AlsYmr.js +1 -0
- package/console-app/assets/railroad-ebnf-LZEXJU2U-BVX8UG1z.js +1 -0
- package/console-app/assets/railroad-peg-WCYAUIDC-BzWQFvD9.js +1 -0
- package/console-app/assets/{railroadDiagram-O6MQD6OU-BNgQGtF5.js → railroadDiagram-O6MQD6OU-oh1FjI2K.js} +1 -1
- package/console-app/assets/{requirementDiagram-BXWQKSXE-48lE_WeD.js → requirementDiagram-BXWQKSXE-D6z7hLfj.js} +1 -1
- package/console-app/assets/{sankeyDiagram-P5KCCOFB-WmTardCP.js → sankeyDiagram-P5KCCOFB-DFb92jfp.js} +1 -1
- package/console-app/assets/{sequenceDiagram-WJ2MYXX4-Bd5cHDMs.js → sequenceDiagram-WJ2MYXX4-BRKj-PG1.js} +1 -1
- package/console-app/assets/{src-BTXg_NtK.js → src-DYBVouJk.js} +1 -1
- package/console-app/assets/{stateDiagram-D77RDMKH-DBoCkqGv.js → stateDiagram-D77RDMKH-BfTLNw5t.js} +1 -1
- package/console-app/assets/stateDiagram-v2-MP3YSRHH-B8sMNnnF.js +1 -0
- package/console-app/assets/{swimlanes-42K2YHIH-lecUPBaK.js → swimlanes-42K2YHIH-DXkNYzX9.js} +1 -1
- package/console-app/assets/swimlanesDiagram-VR7AAH4N-CiZdLDyk.js +8 -0
- package/console-app/assets/{timeline-definition-24CTP7MA-CWq0OWm1.js → timeline-definition-24CTP7MA-B8m2V75P.js} +1 -1
- package/console-app/assets/{treeView-Q6P3EWNA-C7lEeqUz.js → treeView-Q6P3EWNA-BisqOzat.js} +1 -1
- package/console-app/assets/{treemap-WGGIJYW6-Bkx2DAoI.js → treemap-WGGIJYW6-DOxEXpb1.js} +1 -1
- package/console-app/assets/{vennDiagram-4TSXK5OY-Bw_kGRL3.js → vennDiagram-4TSXK5OY-ZeuU7o23.js} +1 -1
- package/console-app/assets/{wardley-WFR3VGLG-V0zki2L0.js → wardley-WFR3VGLG-sspeOMuz.js} +1 -1
- package/console-app/assets/{wardleyDiagram-VM6X3IG4-C5vrwEHM.js → wardleyDiagram-VM6X3IG4-CF2vzNJV.js} +1 -1
- package/console-app/assets/{xychartDiagram-S5SC5T6Z-B9uA0moC.js → xychartDiagram-S5SC5T6Z-BR9XBq3s.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 +21 -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-contracts-meta.gen.json +38 -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 +94 -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 +78 -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/rpc/pikku-rpc-wirings-meta.internal.gen.json +4 -0
- 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 +17 -1
- package/dist/.pikku/schemas/schemas/ExamplesAddInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ExamplesAddOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ExamplesListInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ExamplesListOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ExamplesShowInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ExamplesShowOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricChangesFileInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricChangesFileOutput.schema.json +1 -0
- 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 +51 -0
- package/dist/src/examples.gen.d.ts +17 -0
- package/dist/src/examples.gen.js +7 -0
- package/dist/src/fabric/fabric-commands.d.ts +37 -0
- package/dist/src/fabric/fabric-commands.js +32 -1
- package/dist/src/fabric/functions/changes-file.function.d.ts +64 -0
- package/dist/src/fabric/functions/changes-file.function.js +56 -0
- package/dist/src/fabric/functions/validate.function.d.ts +34 -0
- package/dist/src/fabric/functions/validate.function.js +118 -0
- package/dist/src/fabric/lib/config.d.ts +1 -0
- package/dist/src/fabric/lib/config.js +1 -1
- package/dist/src/functions/commands/dev-address.d.ts +27 -0
- package/dist/src/functions/commands/dev-address.js +45 -0
- package/dist/src/functions/commands/dev.js +6 -0
- package/dist/src/functions/commands/environment.d.ts +8 -0
- package/dist/src/functions/commands/environment.js +15 -0
- package/dist/src/functions/commands/examples.d.ts +170 -0
- package/dist/src/functions/commands/examples.js +28 -0
- package/dist/src/functions/commands/scenario.js +356 -273
- package/dist/src/functions/db/local-db.d.ts +12 -0
- package/dist/src/functions/db/local-db.js +1 -1
- package/dist/src/functions/db/postgres/scenario-baseline.d.ts +3 -0
- package/dist/src/functions/db/postgres/scenario-baseline.js +112 -0
- package/dist/src/functions/db/scenario-baseline.d.ts +51 -0
- package/dist/src/functions/db/scenario-baseline.js +60 -0
- package/dist/src/functions/db/sqlite/scenario-baseline.d.ts +3 -0
- package/dist/src/functions/db/sqlite/scenario-baseline.js +77 -0
- package/dist/src/functions/examples/command-schemas.d.ts +69 -0
- package/dist/src/functions/examples/command-schemas.js +15 -0
- package/dist/src/functions/examples/corpus.d.ts +115 -0
- package/dist/src/functions/examples/corpus.js +307 -0
- package/dist/src/functions/examples/project.d.ts +64 -0
- package/dist/src/functions/examples/project.js +363 -0
- package/dist/src/functions/examples/render.d.ts +4 -0
- package/dist/src/functions/examples/render.js +101 -0
- package/dist/src/functions/examples/run.d.ts +9 -0
- package/dist/src/functions/examples/run.js +242 -0
- package/dist/src/functions/examples/schemas.d.ts +65 -0
- package/dist/src/functions/examples/schemas.js +76 -0
- package/dist/src/functions/surface/render-surface-doc.js +32 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/snippets-meta.json +2 -0
- package/snippets.json +2 -0
- package/surface.json +1 -1
- package/console-app/assets/architecture-7GRP2DOG-BQN972Vc.js +0 -1
- package/console-app/assets/channel-B8xtOmL3.js +0 -1
- package/console-app/assets/chunk-XXDRQBXY-CGWcS5Ol.js +0 -1
- package/console-app/assets/classDiagram-ZZMXUADV-OGsmOlmO.js +0 -1
- package/console-app/assets/classDiagram-v2-VYDZK3BY-OGsmOlmO.js +0 -1
- package/console-app/assets/eventmodeling-NTZA5JFV-CnZOTLz3.js +0 -1
- package/console-app/assets/flowDiagram-HODETNUW-TYMCrte8.js +0 -1
- package/console-app/assets/railroad-abnf-HS5TGJTU-D9Ej_sin.js +0 -1
- package/console-app/assets/railroad-ebnf-LZEXJU2U-CjzlC3qv.js +0 -1
- package/console-app/assets/railroad-peg-WCYAUIDC-BPa6lIrj.js +0 -1
- package/console-app/assets/stateDiagram-v2-MP3YSRHH-BLbaZawL.js +0 -1
- package/console-app/assets/swimlanesDiagram-VR7AAH4N-CM_5HS_7.js +0 -8
|
@@ -1130,6 +1130,43 @@ export declare const fabricCommands: {
|
|
|
1130
1130
|
thread: any;
|
|
1131
1131
|
stageUrl: string | null;
|
|
1132
1132
|
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown>, undefined, undefined>, import("../../.pikku/middleware/pikku-middleware-types.gen.js").PikkuMiddleware, (services: import("../../types/application-types.js").SingletonServices, data: any, session?: import("../../types/application-types.js").UserSession | undefined) => void | Promise<void>, string>;
|
|
1133
|
+
file: import("@pikku/core/cli").CoreCLICommandConfig<import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
1134
|
+
apiUrl?: string | undefined;
|
|
1135
|
+
projectId?: string | undefined;
|
|
1136
|
+
stageId?: string | undefined;
|
|
1137
|
+
branch?: string | undefined;
|
|
1138
|
+
title: string;
|
|
1139
|
+
body?: string | undefined;
|
|
1140
|
+
bodyFile?: string | undefined;
|
|
1141
|
+
route?: string | undefined;
|
|
1142
|
+
locale?: string | undefined;
|
|
1143
|
+
}, {
|
|
1144
|
+
change: any;
|
|
1145
|
+
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
1146
|
+
apiUrl?: string | undefined;
|
|
1147
|
+
projectId?: string | undefined;
|
|
1148
|
+
stageId?: string | undefined;
|
|
1149
|
+
branch?: string | undefined;
|
|
1150
|
+
title: string;
|
|
1151
|
+
body?: string | undefined;
|
|
1152
|
+
bodyFile?: string | undefined;
|
|
1153
|
+
route?: string | undefined;
|
|
1154
|
+
locale?: string | undefined;
|
|
1155
|
+
}, {
|
|
1156
|
+
change: any;
|
|
1157
|
+
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").WiredServices> | import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
1158
|
+
apiUrl?: string | undefined;
|
|
1159
|
+
projectId?: string | undefined;
|
|
1160
|
+
stageId?: string | undefined;
|
|
1161
|
+
branch?: string | undefined;
|
|
1162
|
+
title: string;
|
|
1163
|
+
body?: string | undefined;
|
|
1164
|
+
bodyFile?: string | undefined;
|
|
1165
|
+
route?: string | undefined;
|
|
1166
|
+
locale?: string | undefined;
|
|
1167
|
+
}, {
|
|
1168
|
+
change: any;
|
|
1169
|
+
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown>, undefined, undefined>, import("../../.pikku/middleware/pikku-middleware-types.gen.js").PikkuMiddleware, (services: import("../../types/application-types.js").SingletonServices, data: any, session?: import("../../types/application-types.js").UserSession | undefined) => void | Promise<void>, string>;
|
|
1133
1170
|
claim: import("@pikku/core/cli").CoreCLICommandConfig<import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
1134
1171
|
apiUrl?: string | undefined;
|
|
1135
1172
|
projectId?: string | undefined;
|
|
@@ -45,6 +45,7 @@ import { FabricDomainsRemove } from './functions/domains-remove.function.js';
|
|
|
45
45
|
import { FabricLLMKey, renderLLMKey } from './functions/llm-key.function.js';
|
|
46
46
|
import { FabricChangesList, renderChangesList, } from './functions/changes-list.function.js';
|
|
47
47
|
import { FabricChangesShow, renderChangesShow, } from './functions/changes-show.function.js';
|
|
48
|
+
import { FabricChangesFile, renderChangesFile, } from './functions/changes-file.function.js';
|
|
48
49
|
import { FabricChangesClaim, renderChangesClaim, } from './functions/changes-claim.function.js';
|
|
49
50
|
import { FabricChangesAsk, renderChangesAsk, } from './functions/changes-ask.function.js';
|
|
50
51
|
import { FabricChangesShot, renderChangesShot, } from './functions/changes-shot.function.js';
|
|
@@ -482,7 +483,7 @@ export const fabricCommands = defineCLICommands({
|
|
|
482
483
|
},
|
|
483
484
|
},
|
|
484
485
|
changes: {
|
|
485
|
-
description: 'The todo list filed from inside a deployed stage: read what is open, claim a batch, ask what you need to know, and tick items off',
|
|
486
|
+
description: 'The todo list filed from inside a deployed stage: read what is open, file what was decided elsewhere, claim a batch, ask what you need to know, and tick items off',
|
|
486
487
|
subcommands: {
|
|
487
488
|
list: pikkuCLICommand({
|
|
488
489
|
func: FabricChangesList,
|
|
@@ -524,6 +525,36 @@ export const fabricCommands = defineCLICommands({
|
|
|
524
525
|
apiUrl: { description: 'Override the fabric-api URL for this call' },
|
|
525
526
|
},
|
|
526
527
|
}),
|
|
528
|
+
file: pikkuCLICommand({
|
|
529
|
+
func: FabricChangesFile,
|
|
530
|
+
render: renderChangesFile,
|
|
531
|
+
description: 'File an item from outside the panel — the words, without the screenshot the panel would have attached',
|
|
532
|
+
options: {
|
|
533
|
+
projectId: {
|
|
534
|
+
description: 'Project to file against (defaults to the linked checkout)',
|
|
535
|
+
short: 'p',
|
|
536
|
+
},
|
|
537
|
+
stageId: {
|
|
538
|
+
description: 'Stage to file against (defaults to the only stage)',
|
|
539
|
+
},
|
|
540
|
+
branch: {
|
|
541
|
+
description: 'Resolve the stage from this branch instead',
|
|
542
|
+
},
|
|
543
|
+
title: {
|
|
544
|
+
description: 'The requirement, in one line',
|
|
545
|
+
short: 't',
|
|
546
|
+
},
|
|
547
|
+
body: { description: 'The detail, if a line is not enough' },
|
|
548
|
+
bodyFile: {
|
|
549
|
+
description: 'Read the body from a file — use this when it has newlines',
|
|
550
|
+
},
|
|
551
|
+
route: {
|
|
552
|
+
description: 'The route it is about, e.g. /admin/rota',
|
|
553
|
+
},
|
|
554
|
+
locale: { description: 'Locale it was seen in, e.g. de' },
|
|
555
|
+
apiUrl: { description: 'Override the fabric-api URL for this call' },
|
|
556
|
+
},
|
|
557
|
+
}),
|
|
527
558
|
claim: pikkuCLICommand({
|
|
528
559
|
func: FabricChangesClaim,
|
|
529
560
|
render: renderChangesClaim,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { CreateChangeOutput } from '../sdk/rpc-map.gen.d.js';
|
|
3
|
+
export declare const FabricChangesFileInput: z.ZodObject<{
|
|
4
|
+
apiUrl: z.ZodOptional<z.ZodString>;
|
|
5
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
6
|
+
stageId: z.ZodOptional<z.ZodString>;
|
|
7
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
8
|
+
title: z.ZodString;
|
|
9
|
+
body: z.ZodOptional<z.ZodString>;
|
|
10
|
+
bodyFile: z.ZodOptional<z.ZodString>;
|
|
11
|
+
route: z.ZodOptional<z.ZodString>;
|
|
12
|
+
locale: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
export declare const FabricChangesFileOutput: z.ZodObject<{
|
|
15
|
+
change: z.ZodAny;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
/**
|
|
18
|
+
* An item filed from a terminal carries no screenshot, no circled elements and
|
|
19
|
+
* no build — the panel supplies those and nothing here can invent them. What it
|
|
20
|
+
* does carry is the words, which the skill already treats as the requirement
|
|
21
|
+
* and every other address as evidence, so a written item is a thinner but not a
|
|
22
|
+
* malformed one.
|
|
23
|
+
*
|
|
24
|
+
* `--body-file` because a real item's body is a paragraph with newlines in it,
|
|
25
|
+
* and putting that through shell quoting is where it gets mangled.
|
|
26
|
+
*/
|
|
27
|
+
export declare const FabricChangesFile: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
28
|
+
apiUrl?: string | undefined;
|
|
29
|
+
projectId?: string | undefined;
|
|
30
|
+
stageId?: string | undefined;
|
|
31
|
+
branch?: string | undefined;
|
|
32
|
+
title: string;
|
|
33
|
+
body?: string | undefined;
|
|
34
|
+
bodyFile?: string | undefined;
|
|
35
|
+
route?: string | undefined;
|
|
36
|
+
locale?: string | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
change: any;
|
|
39
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
40
|
+
apiUrl?: string | undefined;
|
|
41
|
+
projectId?: string | undefined;
|
|
42
|
+
stageId?: string | undefined;
|
|
43
|
+
branch?: string | undefined;
|
|
44
|
+
title: string;
|
|
45
|
+
body?: string | undefined;
|
|
46
|
+
bodyFile?: string | undefined;
|
|
47
|
+
route?: string | undefined;
|
|
48
|
+
locale?: string | undefined;
|
|
49
|
+
}, {
|
|
50
|
+
change: any;
|
|
51
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
52
|
+
apiUrl?: string | undefined;
|
|
53
|
+
projectId?: string | undefined;
|
|
54
|
+
stageId?: string | undefined;
|
|
55
|
+
branch?: string | undefined;
|
|
56
|
+
title: string;
|
|
57
|
+
body?: string | undefined;
|
|
58
|
+
bodyFile?: string | undefined;
|
|
59
|
+
route?: string | undefined;
|
|
60
|
+
locale?: string | undefined;
|
|
61
|
+
}, {
|
|
62
|
+
change: any;
|
|
63
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown>, undefined, undefined>;
|
|
64
|
+
export declare const renderChangesFile: (_s: unknown, { change }: CreateChangeOutput) => void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
4
|
+
import { changesContext, requireProjectId } from '../lib/changes.js';
|
|
5
|
+
import { resolveStageId } from '../lib/stage.js';
|
|
6
|
+
import { dim, safe } from '../lib/output.js';
|
|
7
|
+
export const FabricChangesFileInput = z.object({
|
|
8
|
+
apiUrl: z.string().optional(),
|
|
9
|
+
projectId: z.string().optional(),
|
|
10
|
+
stageId: z.string().optional(),
|
|
11
|
+
branch: z.string().optional(),
|
|
12
|
+
title: z.string().trim().min(1, 'Give the item a title.'),
|
|
13
|
+
body: z.string().optional(),
|
|
14
|
+
bodyFile: z.string().optional(),
|
|
15
|
+
route: z.string().optional(),
|
|
16
|
+
locale: z.string().optional(),
|
|
17
|
+
});
|
|
18
|
+
export const FabricChangesFileOutput = z.object({
|
|
19
|
+
change: z.any(),
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* An item filed from a terminal carries no screenshot, no circled elements and
|
|
23
|
+
* no build — the panel supplies those and nothing here can invent them. What it
|
|
24
|
+
* does carry is the words, which the skill already treats as the requirement
|
|
25
|
+
* and every other address as evidence, so a written item is a thinner but not a
|
|
26
|
+
* malformed one.
|
|
27
|
+
*
|
|
28
|
+
* `--body-file` because a real item's body is a paragraph with newlines in it,
|
|
29
|
+
* and putting that through shell quoting is where it gets mangled.
|
|
30
|
+
*/
|
|
31
|
+
export const FabricChangesFile = pikkuSessionlessFunc({
|
|
32
|
+
description: 'File a change against a stage from outside the panel.',
|
|
33
|
+
input: FabricChangesFileInput,
|
|
34
|
+
output: FabricChangesFileOutput,
|
|
35
|
+
func: async (_services, input) => {
|
|
36
|
+
if (input.body && input.bodyFile)
|
|
37
|
+
throw new Error('Pass --body or --body-file, not both.');
|
|
38
|
+
const { rpc, projectId } = await changesContext(input.apiUrl, input.projectId);
|
|
39
|
+
const stageId = input.stageId ??
|
|
40
|
+
(await resolveStageId(rpc, requireProjectId(projectId), input.branch));
|
|
41
|
+
const body = input.bodyFile
|
|
42
|
+
? await readFile(input.bodyFile, 'utf8')
|
|
43
|
+
: input.body;
|
|
44
|
+
return await rpc.invoke('createChange', {
|
|
45
|
+
stageId,
|
|
46
|
+
title: input.title,
|
|
47
|
+
body: body?.trim() || undefined,
|
|
48
|
+
route: input.route,
|
|
49
|
+
locale: input.locale,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
export const renderChangesFile = (_s, { change }) => {
|
|
54
|
+
console.log(`Filed #${safe(change.shortId)} ${safe(change.title)}`);
|
|
55
|
+
console.log(dim(` ${safe(change.changeId)}`));
|
|
56
|
+
};
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
declare const FindingSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
severity: z.ZodEnum<{
|
|
5
|
+
error: "error";
|
|
6
|
+
info: "info";
|
|
7
|
+
warn: "warn";
|
|
8
|
+
}>;
|
|
9
|
+
message: z.ZodString;
|
|
10
|
+
path: z.ZodString;
|
|
11
|
+
fixHint: z.ZodString;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
type Finding = z.infer<typeof FindingSchema>;
|
|
2
14
|
export declare const FabricValidateInput: z.ZodObject<{
|
|
3
15
|
skipTypecheck: z.ZodOptional<z.ZodBoolean>;
|
|
4
16
|
}, z.core.$strip>;
|
|
@@ -17,6 +29,27 @@ export declare const FabricValidateOutput: z.ZodObject<{
|
|
|
17
29
|
fixHint: z.ZodString;
|
|
18
30
|
}, z.core.$strip>>;
|
|
19
31
|
}, z.core.$strip>;
|
|
32
|
+
/** One stage's record of what it has applied, as the control plane holds it. */
|
|
33
|
+
export interface StageLedger {
|
|
34
|
+
stageId: string;
|
|
35
|
+
branch: string;
|
|
36
|
+
migrations: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
hash: string | null;
|
|
39
|
+
appliedAt: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/** Same digest the stage migrator records: sha256 of the file's bytes as UTF-8. */
|
|
43
|
+
export declare function hashMigration(sql: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Compares what each stage applied against the files in the repo now. Split
|
|
46
|
+
* out from the RPC call so the comparison is testable without a session.
|
|
47
|
+
*
|
|
48
|
+
* A row whose `hash` is null was applied before the stage migrator recorded
|
|
49
|
+
* hashes; the file it named is unrecoverable, so it is reported as unverified
|
|
50
|
+
* rather than as clean.
|
|
51
|
+
*/
|
|
52
|
+
export declare function migrationDriftFindings(migrationsDir: string, local: Map<string, string>, stages: StageLedger[]): Finding[];
|
|
20
53
|
export declare function runValidate(startDir?: string, opts?: {
|
|
21
54
|
skipTypecheck?: boolean;
|
|
22
55
|
}): Promise<z.infer<typeof FabricValidateOutput>>;
|
|
@@ -58,3 +91,4 @@ export declare const FabricValidate: import("../../../.pikku/function/pikku-func
|
|
|
58
91
|
}[];
|
|
59
92
|
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown>, undefined, undefined>;
|
|
60
93
|
export declare const renderValidate: (_s: unknown, { ok, root, findings }: z.infer<typeof FabricValidateOutput>) => void;
|
|
94
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { readFile, readdir } from 'node:fs/promises';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
3
4
|
import { existsSync } from 'node:fs';
|
|
4
5
|
import { dirname, join, relative } from 'node:path';
|
|
5
6
|
import { createRequire } from 'node:module';
|
|
@@ -10,6 +11,8 @@ import { readJsonSafe, readTextSafe, runSharedProjectChecks, } from '../../funct
|
|
|
10
11
|
import { runTypeIdentityChecks } from '../../functions/validate/type-identity-checks.js';
|
|
11
12
|
import { migrationCreatesTable } from '../../functions/validate/shared-checks.js';
|
|
12
13
|
import { isGitRepo, isTracked } from '../lib/git.js';
|
|
14
|
+
import { resolveApiContext } from '../lib/config.js';
|
|
15
|
+
import { getFabricRPC } from '../lib/http.js';
|
|
13
16
|
import { blankComments, lineOfOffset } from '../lib/blank-comments.js';
|
|
14
17
|
import { blankScenarioMeta } from '../lib/blank-scenario-meta.js';
|
|
15
18
|
const FindingSchema = z.object({
|
|
@@ -202,6 +205,105 @@ const POSTGRES_SQL_PATTERNS = [
|
|
|
202
205
|
{ re: /\bTSVECTOR\b/i, label: 'TSVECTOR' },
|
|
203
206
|
{ re: /\bARRAY\s*\[/i, label: 'ARRAY[…]' },
|
|
204
207
|
];
|
|
208
|
+
/** Same digest the stage migrator records: sha256 of the file's bytes as UTF-8. */
|
|
209
|
+
export function hashMigration(sql) {
|
|
210
|
+
return createHash('sha256').update(sql, 'utf-8').digest('hex');
|
|
211
|
+
}
|
|
212
|
+
const slug = (s) => s.replace(/[^a-z0-9]/gi, '-');
|
|
213
|
+
/**
|
|
214
|
+
* Compares what each stage applied against the files in the repo now. Split
|
|
215
|
+
* out from the RPC call so the comparison is testable without a session.
|
|
216
|
+
*
|
|
217
|
+
* A row whose `hash` is null was applied before the stage migrator recorded
|
|
218
|
+
* hashes; the file it named is unrecoverable, so it is reported as unverified
|
|
219
|
+
* rather than as clean.
|
|
220
|
+
*/
|
|
221
|
+
export function migrationDriftFindings(migrationsDir, local, stages) {
|
|
222
|
+
const findings = [];
|
|
223
|
+
let unverifiable = 0;
|
|
224
|
+
for (const stage of stages) {
|
|
225
|
+
for (const applied of stage.migrations) {
|
|
226
|
+
const localHash = local.get(applied.name);
|
|
227
|
+
if (localHash === undefined) {
|
|
228
|
+
findings.push({
|
|
229
|
+
id: `migration-applied-file-missing-${slug(stage.branch)}-${slug(applied.name)}`,
|
|
230
|
+
severity: 'error',
|
|
231
|
+
message: `${applied.name} was applied to the "${stage.branch}" stage but no longer exists locally`,
|
|
232
|
+
path: join(migrationsDir, applied.name),
|
|
233
|
+
fixHint: 'Restore the file under its original name. Deleting or renaming an applied migration does not undo it — the stage keeps the schema that file produced, and a fresh database will never reach that shape.',
|
|
234
|
+
});
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (applied.hash === null) {
|
|
238
|
+
unverifiable++;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (applied.hash !== localHash) {
|
|
242
|
+
findings.push({
|
|
243
|
+
id: `migration-drift-${slug(stage.branch)}-${slug(applied.name)}`,
|
|
244
|
+
severity: 'error',
|
|
245
|
+
message: `${applied.name} differs from the copy applied to the "${stage.branch}" stage (applied ${applied.hash.slice(0, 12)}, local ${localHash.slice(0, 12)})`,
|
|
246
|
+
path: join(migrationsDir, applied.name),
|
|
247
|
+
fixHint: [
|
|
248
|
+
'Revert the file to what was applied and put the change in a NEW',
|
|
249
|
+
'numbered migration. A migration is recorded by filename and never',
|
|
250
|
+
're-runs, so this edit will never reach that stage — the next',
|
|
251
|
+
'migration that depends on it fails there instead.',
|
|
252
|
+
].join('\n'),
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (unverifiable > 0) {
|
|
258
|
+
findings.push({
|
|
259
|
+
id: 'migration-drift-partially-unverifiable',
|
|
260
|
+
severity: 'info',
|
|
261
|
+
message: `${unverifiable} applied migration${unverifiable === 1 ? '' : 's'} predate hash recording and cannot be compared`,
|
|
262
|
+
path: migrationsDir,
|
|
263
|
+
fixHint: 'Nothing to do — rows written before the stage migrator recorded hashes carry none. Each deploy records hashes for what it applies.',
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return findings;
|
|
267
|
+
}
|
|
268
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
269
|
+
/**
|
|
270
|
+
* Silent when the project is unlinked or logged out — both already have their
|
|
271
|
+
* own findings — and degrades to an info when the API cannot be reached, so an
|
|
272
|
+
* offline developer still gets the rest of validate.
|
|
273
|
+
*/
|
|
274
|
+
async function checkMigrationDrift(root, migrationsDir) {
|
|
275
|
+
if (!existsSync(migrationsDir))
|
|
276
|
+
return [];
|
|
277
|
+
const ctx = await resolveApiContext({ startDir: root }).catch(() => null);
|
|
278
|
+
if (!ctx?.token || !ctx.projectId || !UUID.test(ctx.projectId))
|
|
279
|
+
return [];
|
|
280
|
+
let stages;
|
|
281
|
+
try {
|
|
282
|
+
const rpc = getFabricRPC({ apiUrl: ctx.apiUrl, token: ctx.token });
|
|
283
|
+
const res = await rpc.invoke('listStageMigrationLedger', {
|
|
284
|
+
projectId: ctx.projectId,
|
|
285
|
+
});
|
|
286
|
+
stages = res.stages;
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
return [
|
|
290
|
+
{
|
|
291
|
+
id: 'migration-drift-unchecked',
|
|
292
|
+
severity: 'info',
|
|
293
|
+
message: `could not read the deployed migration ledger (${err instanceof Error ? err.message : String(err)}) — local migrations were not compared against any stage`,
|
|
294
|
+
path: migrationsDir,
|
|
295
|
+
fixHint: 'Run `pikku fabric login` if the session expired. Offline this check is skipped, and the deploy plan catches drift instead.',
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
}
|
|
299
|
+
const local = new Map();
|
|
300
|
+
for (const file of (await readdir(migrationsDir)).filter((f) => f.endsWith('.sql'))) {
|
|
301
|
+
const sql = await readTextSafe(join(migrationsDir, file));
|
|
302
|
+
if (sql !== null)
|
|
303
|
+
local.set(file, hashMigration(sql));
|
|
304
|
+
}
|
|
305
|
+
return migrationDriftFindings(migrationsDir, local, stages);
|
|
306
|
+
}
|
|
205
307
|
export async function runValidate(startDir = process.cwd(), opts = {}) {
|
|
206
308
|
const root = await findProjectRoot(startDir);
|
|
207
309
|
const findings = [];
|
|
@@ -760,6 +862,22 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
|
|
|
760
862
|
// readdir failure — skip
|
|
761
863
|
}
|
|
762
864
|
}
|
|
865
|
+
// ── migrations already applied to a stage must not be edited ─────────
|
|
866
|
+
// A stage records a migration by filename and never runs it again, so an
|
|
867
|
+
// edit to an applied file silently never reaches that schema: the stage
|
|
868
|
+
// keeps the shape the original file produced while the repo, local dev
|
|
869
|
+
// and CI all agree on the new one. CI cannot catch it — it migrates a
|
|
870
|
+
// throwaway empty database, where every file is pending — and the deploy
|
|
871
|
+
// risk gate only reads the SQL text, never the stage. It surfaces as the
|
|
872
|
+
// NEXT migration failing on a column that exists everywhere but there.
|
|
873
|
+
//
|
|
874
|
+
// The comparison is against the control plane's record of what each stage
|
|
875
|
+
// applied (hash included since @pikkufabric 2026-09), not against the
|
|
876
|
+
// stage database, which may be asleep and cannot be woken just to answer
|
|
877
|
+
// a local lint. Every stage of the project is checked, not just the one
|
|
878
|
+
// you are about to push: the case this is for is merging a branch that
|
|
879
|
+
// edited a migration another stage already ran.
|
|
880
|
+
findings.push(...(await checkMigrationDrift(root, migrationsDir)));
|
|
763
881
|
// ── the coercion map has to reach a Kysely instance ──────────────────
|
|
764
882
|
// `pikku db migrate` generates a CoercionMap from the `kind` entries in
|
|
765
883
|
// db/annotations.ts, and nothing wires it up on the project's behalf. An
|
|
@@ -98,7 +98,7 @@ export async function writeAuthFile(file) {
|
|
|
98
98
|
* Token comes from ~/.fabric/auth.json keyed by the resolved api-url.
|
|
99
99
|
*/
|
|
100
100
|
export async function resolveApiContext(opts = {}) {
|
|
101
|
-
const projectFile = await findProjectConfig();
|
|
101
|
+
const projectFile = await findProjectConfig(opts.startDir);
|
|
102
102
|
const apiUrl = opts.apiUrlOverride ??
|
|
103
103
|
projectFile?.config.apiUrl ??
|
|
104
104
|
process.env.FABRIC_API_URL ??
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a running `pikku dev` says it ended up.
|
|
3
|
+
*
|
|
4
|
+
* The port a dev server announces is not the port it was asked for: `--port 0`
|
|
5
|
+
* asks the OS for one, and a busy 3000 is the ordinary case on a machine that is
|
|
6
|
+
* already running something. Everything downstream — a scenario run, a frontend
|
|
7
|
+
* proxy, a person reading their own terminal — then targets the configured port
|
|
8
|
+
* and gets a connection refused that looks like a broken app.
|
|
9
|
+
*
|
|
10
|
+
* It lives in the runtime directory rather than the generated one because it is
|
|
11
|
+
* state about a process, not an artifact of codegen, and it is meaningless the
|
|
12
|
+
* moment that process is gone.
|
|
13
|
+
*/
|
|
14
|
+
export interface DevAddress {
|
|
15
|
+
apiUrl: string;
|
|
16
|
+
pid: number;
|
|
17
|
+
startedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const writeDevAddress: (runtimeDir: string, apiUrl: string) => void;
|
|
20
|
+
export declare const clearDevAddress: (runtimeDir: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* The address only if the process that wrote it is still alive — a dev server
|
|
23
|
+
* killed with SIGKILL, or one whose machine rebooted, never got to clear it, and
|
|
24
|
+
* a stale address is worse than none. Signal 0 checks liveness without sending
|
|
25
|
+
* anything; EPERM means a process owns that id, so it counts as alive.
|
|
26
|
+
*/
|
|
27
|
+
export declare const readDevAddress: (runtimeDir: string) => DevAddress | null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
const addressPath = (runtimeDir) => join(runtimeDir, 'dev-address.json');
|
|
4
|
+
export const writeDevAddress = (runtimeDir, apiUrl) => {
|
|
5
|
+
const path = addressPath(runtimeDir);
|
|
6
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
7
|
+
const address = {
|
|
8
|
+
apiUrl,
|
|
9
|
+
pid: process.pid,
|
|
10
|
+
startedAt: new Date().toISOString(),
|
|
11
|
+
};
|
|
12
|
+
writeFileSync(path, `${JSON.stringify(address, null, 2)}\n`, 'utf8');
|
|
13
|
+
};
|
|
14
|
+
export const clearDevAddress = (runtimeDir) => {
|
|
15
|
+
rmSync(addressPath(runtimeDir), { force: true });
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The address only if the process that wrote it is still alive — a dev server
|
|
19
|
+
* killed with SIGKILL, or one whose machine rebooted, never got to clear it, and
|
|
20
|
+
* a stale address is worse than none. Signal 0 checks liveness without sending
|
|
21
|
+
* anything; EPERM means a process owns that id, so it counts as alive.
|
|
22
|
+
*/
|
|
23
|
+
export const readDevAddress = (runtimeDir) => {
|
|
24
|
+
const path = addressPath(runtimeDir);
|
|
25
|
+
if (!existsSync(path))
|
|
26
|
+
return null;
|
|
27
|
+
let address;
|
|
28
|
+
try {
|
|
29
|
+
address = JSON.parse(readFileSync(path, 'utf8'));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (typeof address?.apiUrl !== 'string' || typeof address?.pid !== 'number') {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
process.kill(address.pid, 0);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error.code !== 'EPERM')
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return address;
|
|
45
|
+
};
|
|
@@ -25,6 +25,7 @@ import { resolveDevEnvironmentName } from './environment.js';
|
|
|
25
25
|
import { createDevAgentRunner } from './dev-agent-runner.js';
|
|
26
26
|
import { resolveConsoleMount } from './serve-console.js';
|
|
27
27
|
import { serverReadyLine } from '../../server/server-ready.js';
|
|
28
|
+
import { clearDevAddress, writeDevAddress } from './dev-address.js';
|
|
28
29
|
import { createEphemeralContentSigningJWT } from '../../server/content-signing-jwt.js';
|
|
29
30
|
import { enableDevActorSignIn } from '../../server/actor-sign-in.js';
|
|
30
31
|
import { resolvePersonas } from '../../utils/resolve-personas.js';
|
|
@@ -364,6 +365,10 @@ export const dev = pikkuSessionlessFunc({
|
|
|
364
365
|
logger.info(`Frontend not served in dev — run your frontend dev server and proxy its API calls to http://${hostname}:${boundPort}`);
|
|
365
366
|
}
|
|
366
367
|
logger.info(serverReadyLine(hostname, boundPort));
|
|
368
|
+
// Written from the bound port, so anything that has to find this server later
|
|
369
|
+
// reads where it actually is rather than where it was asked to be.
|
|
370
|
+
writeDevAddress(resolvedRuntimeDir, `http://${hostname}:${boundPort}`);
|
|
371
|
+
process.once('exit', () => clearDevAddress(resolvedRuntimeDir));
|
|
367
372
|
let watcher;
|
|
368
373
|
process.once('SIGINT', async () => {
|
|
369
374
|
logger.info('Stopping dev server...');
|
|
@@ -375,6 +380,7 @@ export const dev = pikkuSessionlessFunc({
|
|
|
375
380
|
await lifecycle?.afterStop?.(resolvedServices);
|
|
376
381
|
}
|
|
377
382
|
finally {
|
|
383
|
+
clearDevAddress(resolvedRuntimeDir);
|
|
378
384
|
process.exit(0);
|
|
379
385
|
}
|
|
380
386
|
});
|
|
@@ -44,6 +44,14 @@ export interface ResolveEnvironmentOptions {
|
|
|
44
44
|
/** `--spawn`, which is only coherent against a local `apiUrl`. */
|
|
45
45
|
spawn?: boolean;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Whether a resolved URL names a server on this machine.
|
|
49
|
+
*
|
|
50
|
+
* The gate for anything the runner does to a target directly rather than
|
|
51
|
+
* through its API — reaching into its database, for one. A remote host is
|
|
52
|
+
* somebody else's data whatever the config asked for.
|
|
53
|
+
*/
|
|
54
|
+
export declare const isLocalUrl: (value: string) => boolean;
|
|
47
55
|
/**
|
|
48
56
|
* Applied once, so actors, step env, the browser driver and the spawned server
|
|
49
57
|
* all see the same target. The environment is still looked up by name: the
|
|
@@ -14,6 +14,21 @@ const LOCAL_HOSTNAMES = new Set([
|
|
|
14
14
|
'::1',
|
|
15
15
|
'[::1]',
|
|
16
16
|
]);
|
|
17
|
+
/**
|
|
18
|
+
* Whether a resolved URL names a server on this machine.
|
|
19
|
+
*
|
|
20
|
+
* The gate for anything the runner does to a target directly rather than
|
|
21
|
+
* through its API — reaching into its database, for one. A remote host is
|
|
22
|
+
* somebody else's data whatever the config asked for.
|
|
23
|
+
*/
|
|
24
|
+
export const isLocalUrl = (value) => {
|
|
25
|
+
try {
|
|
26
|
+
return LOCAL_HOSTNAMES.has(new URL(value).hostname);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
17
32
|
/**
|
|
18
33
|
* Absolute URLs only: the value is concatenated with paths (`${apiUrl}/rpc`)
|
|
19
34
|
* and parsed by the spawn path, so a relative one fails far from its cause.
|