@pikku/cli 0.12.143 → 0.12.145
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/CHANGELOG.md +41 -0
- package/console-app/assets/HelpPanel-BJQaz5Ah.css +1 -0
- package/console-app/assets/HelpPanel-nYO2hRY5.js +1 -0
- package/console-app/assets/{abnfDiagram-N423BO3Z-CG60mMUd.js → abnfDiagram-N423BO3Z-BIPJyOId.js} +1 -1
- package/console-app/assets/architecture-TIHT7OUA-B-c05-x5.js +1 -0
- package/console-app/assets/{architectureDiagram-T3A2C74G-Ch6qWsLf.js → architectureDiagram-T3A2C74G-BAH1O4B7.js} +1 -1
- package/console-app/assets/{blockDiagram-VBNYF7ZC-yRgqjgqW.js → blockDiagram-VBNYF7ZC-T3kmcPgj.js} +1 -1
- package/console-app/assets/{c4Diagram-5PPSVZJV-NvawOgnU.js → c4Diagram-5PPSVZJV-DRva89Br.js} +1 -1
- package/console-app/assets/channel-DJ3jfSNX.js +1 -0
- package/console-app/assets/{chunk-2GRJ4B5K-BJ9-Roz7.js → chunk-2GRJ4B5K-pBREt5-Y.js} +1 -1
- package/console-app/assets/{chunk-4I5QYGJK-DZwmcj48.js → chunk-4I5QYGJK-SmJ1Rqsn.js} +1 -1
- package/console-app/assets/{chunk-5RXB4S5H-BTBwIEIt.js → chunk-5RXB4S5H-wo8Xtqiv.js} +1 -1
- package/console-app/assets/{chunk-6Q2QTUOP-C55aqlA-.js → chunk-6Q2QTUOP-B6uqaxr0.js} +1 -1
- package/console-app/assets/{chunk-7Z6QIM7H-DRmYZ-SZ.js → chunk-7Z6QIM7H-uxzNGOHh.js} +1 -1
- package/console-app/assets/{chunk-GF5L2VYU-InZeM4Hr.js → chunk-GF5L2VYU-Cw7tsTe6.js} +1 -1
- package/console-app/assets/{chunk-I66GZJ75-BNvijc65.js → chunk-I66GZJ75-DksrbEtn.js} +1 -1
- package/console-app/assets/{chunk-JQJVKLGR-CIMXqmif.js → chunk-JQJVKLGR-BnRvPhDK.js} +1 -1
- package/console-app/assets/{chunk-KBJHAD2P-C9h3FBoE.js → chunk-KBJHAD2P-PiPaopal.js} +1 -1
- package/console-app/assets/{chunk-NSK5VX7P-lz8xBTRo.js → chunk-NSK5VX7P-VK0slsok.js} +1 -1
- package/console-app/assets/{chunk-QR6OTTB3-CjOfjLMq.js → chunk-QR6OTTB3-CgQotuzQ.js} +1 -1
- package/console-app/assets/{chunk-RYQCIY6F-CV3667Qm.js → chunk-RYQCIY6F-Cei0abOq.js} +1 -1
- package/console-app/assets/{chunk-UBXNYLIW-CBN7usxw.js → chunk-UBXNYLIW-B55XJk4O.js} +1 -1
- package/console-app/assets/{chunk-W5SLKNZC-5TkpffRm.js → chunk-W5SLKNZC-gFa01tuI.js} +1 -1
- package/console-app/assets/{chunk-WRU74C26-GBek0Nby.js → chunk-WRU74C26-C3ESZQ-F.js} +1 -1
- package/console-app/assets/chunk-XXDRQBXY-D0tL6SVk.js +1 -0
- package/console-app/assets/classDiagram-JCYQIIEL-BqEwCDi8.js +1 -0
- package/console-app/assets/classDiagram-v2-OCEON4UE-BqEwCDi8.js +1 -0
- package/console-app/assets/{cose-bilkent-JH36ORCC-BkGyb7Kn.js → cose-bilkent-JH36ORCC-CUxqwjs-.js} +1 -1
- package/console-app/assets/{cynefin-VYW2F7L2-qMmeyMja.js → cynefin-VYW2F7L2-Dh1yOBBs.js} +1 -1
- package/console-app/assets/{cynefinDiagram-MW4NZA55-7MuIYiO4.js → cynefinDiagram-MW4NZA55-BzFWEf8Y.js} +1 -1
- package/console-app/assets/{dagre-BbESpUs5.js → dagre-DKjebq_c.js} +1 -1
- package/console-app/assets/{dagre-VZM6K2ZE-I6YsMazW.js → dagre-VZM6K2ZE-BllFBMe9.js} +1 -1
- package/console-app/assets/{diagram-7IWD3JNH-CJPB2T6d.js → diagram-7IWD3JNH-C58VaHJt.js} +1 -1
- package/console-app/assets/{diagram-B4RE2ZJO-CmFGMFPx.js → diagram-B4RE2ZJO-B3w3TcXn.js} +1 -1
- package/console-app/assets/{diagram-LBJQPF4R-BMzRMe8g.js → diagram-LBJQPF4R-L1ZkDsab.js} +1 -1
- package/console-app/assets/{diagram-Q27KOJAE-CeJb7xQ2.js → diagram-Q27KOJAE-7oaP3D-d.js} +1 -1
- package/console-app/assets/{diagram-UB23O5K3-BQkhJgYU.js → diagram-UB23O5K3-CmRNd5vm.js} +1 -1
- package/console-app/assets/{ebnfDiagram-BXEA7PRR-C1F_8089.js → ebnfDiagram-BXEA7PRR-D0rxzLaa.js} +1 -1
- package/console-app/assets/{erDiagram-JOGREHBK-DRwpdW4v.js → erDiagram-JOGREHBK-Bg0FPLS0.js} +1 -1
- package/console-app/assets/eventmodeling-45OFAUF4-CVovwmpS.js +1 -0
- package/console-app/assets/flowDiagram-UKHOOZJN-DwRgEyXD.js +1 -0
- package/console-app/assets/ganttDiagram-PKOTCBZU-BBxxHrPG.js +292 -0
- package/console-app/assets/{gitGraph-TEB2WS4Q-BBt9AGD3.js → gitGraph-TEB2WS4Q-Cn1MjFvM.js} +1 -1
- package/console-app/assets/{gitGraphDiagram-DS77QQ5N-y5WPOR-G.js → gitGraphDiagram-DS77QQ5N-JaW7OYCY.js} +1 -1
- package/console-app/assets/{index-BmvyL35Z.js → index-Deds7K2I.js} +178 -178
- package/console-app/assets/{info-DKCQHKI2-mYDlDDyA.js → info-DKCQHKI2-C2R7hV-y.js} +1 -1
- package/console-app/assets/{infoDiagram-6WML65LV-uOP7AjEu.js → infoDiagram-6WML65LV-DIbMcTbW.js} +1 -1
- package/console-app/assets/{ishikawaDiagram-WSZJBQD7-BUMKV94t.js → ishikawaDiagram-WSZJBQD7-mozqgfxi.js} +1 -1
- package/console-app/assets/{journeyDiagram-NVQOT4AX-C8_km86P.js → journeyDiagram-NVQOT4AX-CKDrjPz5.js} +1 -1
- package/console-app/assets/{kanban-definition-27J2QSJJ-Ce5oUBPR.js → kanban-definition-27J2QSJJ-B9shPbST.js} +1 -1
- package/console-app/assets/{line-D-6c8Gxs.js → line-DLrnl2PN.js} +1 -1
- package/console-app/assets/{linear-CyrGkJOO.js → linear-BQOZezXu.js} +1 -1
- package/console-app/assets/{mermaid-parser.core-CYuFKArA.js → mermaid-parser.core-ElI_yw4f.js} +3 -3
- package/console-app/assets/{mermaid.core-CXQhu3yO.js → mermaid.core-B02bSmuz.js} +4 -4
- package/console-app/assets/{mindmap-definition-FAOFIHXS-CTMHna5d.js → mindmap-definition-FAOFIHXS-BTvmLZE7.js} +1 -1
- package/console-app/assets/{packet-7NZHBO7P-Bu7Wxek6.js → packet-7NZHBO7P-CkYMF0Cd.js} +1 -1
- package/console-app/assets/{pegDiagram-VL7TDLO6-CQOikBgW.js → pegDiagram-VL7TDLO6-1hBiUSmO.js} +1 -1
- package/console-app/assets/{pie-RZYD4A2V-Co7qIvyZ.js → pie-RZYD4A2V-BFMvieVM.js} +1 -1
- package/console-app/assets/{pieDiagram-7S7Q4E2Y-Dh6jYgnj.js → pieDiagram-7S7Q4E2Y-vvgYfdFq.js} +1 -1
- package/console-app/assets/{quadrantDiagram-CIZ2JOQS-Boongjy-.js → quadrantDiagram-CIZ2JOQS-B_emxK6O.js} +1 -1
- package/console-app/assets/{radar-I7S5WNFK-CSJyAKYA.js → radar-I7S5WNFK-C_2tp7_w.js} +1 -1
- package/console-app/assets/{railroad-3IZDKUUU-DklknXem.js → railroad-3IZDKUUU-DwlFJLv5.js} +1 -1
- package/console-app/assets/railroad-abnf-AHOZXSZD-Cyu_rpdZ.js +1 -0
- package/console-app/assets/railroad-ebnf-EBAXGLYW-BLiwK-H7.js +1 -0
- package/console-app/assets/railroad-peg-LSFZ7HO6-BUDTDYmP.js +1 -0
- package/console-app/assets/{railroadDiagram-AXF67PYL-DEapZRM_.js → railroadDiagram-AXF67PYL-IXXj_KlB.js} +1 -1
- package/console-app/assets/{requirementDiagram-LRYGKXZP-CqFLtnyL.js → requirementDiagram-LRYGKXZP-B15ZEbec.js} +1 -1
- package/console-app/assets/{sankeyDiagram-W5VNT64P-CNu-G1MH.js → sankeyDiagram-W5VNT64P-w-sj_WN8.js} +1 -1
- package/console-app/assets/{sequenceDiagram-SI44F4Z6-CoEKUR3G.js → sequenceDiagram-SI44F4Z6-BP1UgEbX.js} +1 -1
- package/console-app/assets/{src-C1UIZ0TF.js → src-BI35UZf8.js} +1 -1
- package/console-app/assets/{stateDiagram-OKZ733FA-CJka40EH.js → stateDiagram-OKZ733FA-DE4L-y3n.js} +1 -1
- package/console-app/assets/stateDiagram-v2-UEYNNEHI-BsP8TwKV.js +1 -0
- package/console-app/assets/{swimlanes-SLNWSIFB-Dv3MGmvW.js → swimlanes-SLNWSIFB-DvAJxCGQ.js} +1 -1
- package/console-app/assets/swimlanesDiagram-ULZ7WXOC-BAXO3Id2.js +8 -0
- package/console-app/assets/{timeline-definition-Z64GVDOM-CO8etJHi.js → timeline-definition-Z64GVDOM-Cc8M2qee.js} +1 -1
- package/console-app/assets/{treeView-QDETBFTQ-BjLcvY-V.js → treeView-QDETBFTQ-DnlS0s0_.js} +1 -1
- package/console-app/assets/{treemap-6X3UGDF4-xC9XqGfS.js → treemap-6X3UGDF4-CiUoxlJe.js} +1 -1
- package/console-app/assets/{vennDiagram-T6HMQDX7-CJGsYvlQ.js → vennDiagram-T6HMQDX7-dpGyGzMg.js} +1 -1
- package/console-app/assets/{wardley-OPB4EBWU-DkMc876g.js → wardley-OPB4EBWU-DrTySJtR.js} +1 -1
- package/console-app/assets/{wardleyDiagram-T6FBY63Y-CTe7zAVZ.js → wardleyDiagram-T6FBY63Y-CBvRf8GJ.js} +1 -1
- package/console-app/assets/{xychartDiagram-ELKLHX3M-CABg-MLE.js → xychartDiagram-ELKLHX3M-UlPqx-ve.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/auth/index.d.ts +1 -1
- package/dist/.pikku/auth/index.js +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.d.ts +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.js +1 -1
- package/dist/.pikku/channel/index.d.ts +1 -1
- package/dist/.pikku/channel/index.js +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/index.d.ts +1 -1
- package/dist/.pikku/cli/index.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/error/index.d.ts +1 -1
- package/dist/.pikku/error/index.js +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.d.ts +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.js +1 -1
- package/dist/.pikku/function/index.d.ts +1 -1
- package/dist/.pikku/function/index.js +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +2 -2
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/gateway/index.d.ts +1 -1
- package/dist/.pikku/gateway/index.js +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.d.ts +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.js +1 -1
- package/dist/.pikku/http/index.d.ts +1 -1
- package/dist/.pikku/http/index.js +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/mcp/index.d.ts +1 -1
- package/dist/.pikku/mcp/index.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/middleware/index.d.ts +1 -1
- package/dist/.pikku/middleware/index.js +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.d.ts +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/queue/index.d.ts +1 -1
- package/dist/.pikku/queue/index.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/scenarios/index.d.ts +1 -1
- package/dist/.pikku/scenarios/index.js +1 -1
- package/dist/.pikku/scenarios/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-types.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
- package/dist/.pikku/scheduler/index.d.ts +1 -1
- package/dist/.pikku/scheduler/index.js +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +1 -1
- package/dist/.pikku/scopes/index.d.ts +1 -1
- package/dist/.pikku/scopes/index.js +1 -1
- package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/index.d.ts +1 -1
- package/dist/.pikku/secrets/index.js +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/setup/index.d.ts +1 -1
- package/dist/.pikku/setup/index.js +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
- package/dist/.pikku/trigger/index.d.ts +1 -1
- package/dist/.pikku/trigger/index.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/index.d.ts +1 -1
- package/dist/.pikku/variables/index.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/index.d.ts +1 -1
- package/dist/.pikku/workflow/index.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/deploy/analyzer/analyzer.d.ts +8 -1
- package/dist/src/deploy/analyzer/analyzer.js +237 -49
- package/dist/src/deploy/analyzer/grouping.d.ts +23 -0
- package/dist/src/deploy/analyzer/grouping.js +74 -0
- package/dist/src/deploy/analyzer/index.d.ts +1 -0
- package/dist/src/deploy/analyzer/naming.d.ts +1 -0
- package/dist/src/deploy/analyzer/naming.js +9 -0
- package/dist/src/deploy/build-pipeline.d.ts +2 -0
- package/dist/src/deploy/build-pipeline.js +20 -0
- package/dist/src/deploy/codegen/per-unit-codegen.js +8 -2
- package/dist/src/functions/commands/deploy-apply.js +1 -0
- package/dist/src/functions/commands/deploy-plan.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/surface.json +1 -1
- package/console-app/assets/architecture-TIHT7OUA-DSzfLiV3.js +0 -1
- package/console-app/assets/channel-DYUdcfEK.js +0 -1
- package/console-app/assets/chunk-XXDRQBXY-B3U_w_pW.js +0 -1
- package/console-app/assets/classDiagram-JCYQIIEL-Mg8_8GSE.js +0 -1
- package/console-app/assets/classDiagram-v2-OCEON4UE-Mg8_8GSE.js +0 -1
- package/console-app/assets/eventmodeling-45OFAUF4-C5L7A6YY.js +0 -1
- package/console-app/assets/flowDiagram-UKHOOZJN-D6GmsM3x.js +0 -1
- package/console-app/assets/ganttDiagram-PKOTCBZU-CfsGz3Lj.js +0 -292
- package/console-app/assets/railroad-abnf-AHOZXSZD-D-2EAJOD.js +0 -1
- package/console-app/assets/railroad-ebnf-EBAXGLYW-C5XxxCx7.js +0 -1
- package/console-app/assets/railroad-peg-LSFZ7HO6-D8fXoMuX.js +0 -1
- package/console-app/assets/stateDiagram-v2-UEYNNEHI-Bfuo66an.js +0 -1
- package/console-app/assets/swimlanesDiagram-ULZ7WXOC-CyQmsXKP.js +0 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.145
|
|
3
3
|
*/
|
|
4
4
|
import { WorkflowCancelledException } from '@pikku/core/workflow';
|
|
5
5
|
import type { PikkuWorkflowGraphConfig, PikkuWorkflowGraphResult } from '@pikku/core/workflow';
|
package/dist/bin/pikku-bin.mjs
CHANGED
|
@@ -11,8 +11,8 @@ async function checkForUpdate() {
|
|
|
11
11
|
})
|
|
12
12
|
if (!res.ok) return
|
|
13
13
|
const { version: latest } = await res.json()
|
|
14
|
-
if (latest !== '0.12.
|
|
15
|
-
process.stderr.write(`\n Update available 0.12.
|
|
14
|
+
if (latest !== '0.12.145') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.145 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
|
|
16
16
|
}
|
|
17
17
|
} catch {}
|
|
18
18
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Workflow orchestrators dispatch to step units via queue or RPC (inline).
|
|
8
8
|
*/
|
|
9
9
|
import { type InspectorState } from '@pikku/inspector';
|
|
10
|
+
import { type GroupingConfig } from './grouping.js';
|
|
10
11
|
import type { DeploymentManifest } from '@pikku/deploy';
|
|
11
12
|
export interface AnalyzerOptions {
|
|
12
13
|
projectId: string;
|
|
@@ -34,6 +35,12 @@ export interface AnalyzerOptions {
|
|
|
34
35
|
*/
|
|
35
36
|
workflowQueues?: boolean;
|
|
36
37
|
globalHTTPPrefix?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Sourced from `pikku.config.json` → `deploy.grouping`. Decides how many
|
|
40
|
+
* deployment units the `role: 'function'` units collapse into. Omitted
|
|
41
|
+
* means one unit per function.
|
|
42
|
+
*/
|
|
43
|
+
grouping?: GroupingConfig;
|
|
37
44
|
}
|
|
38
45
|
export declare function analyzeDeployment(state: InspectorState, options: AnalyzerOptions): DeploymentManifest;
|
|
39
|
-
export
|
|
46
|
+
export { toSafeKebab } from './naming.js';
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { resolveDeployTarget, } from '@pikku/inspector';
|
|
10
10
|
import { relative } from 'node:path';
|
|
11
11
|
import { isScenarioFunction, withoutScenarios, withoutScenarioWorkflows, } from '../../functions/wirings/scenarios/scenario-partition.js';
|
|
12
|
+
import { toSafeKebab } from './naming.js';
|
|
13
|
+
import { createUnitResolver } from './grouping.js';
|
|
12
14
|
export function analyzeDeployment(state, options) {
|
|
13
15
|
const serverlessIncompatible = new Set(options.serverlessIncompatible ?? []);
|
|
14
16
|
const defaultTarget = options.defaultTarget ?? 'serverless';
|
|
@@ -30,6 +32,86 @@ export function analyzeDeployment(state, options) {
|
|
|
30
32
|
const functionsMeta = withoutScenarios(state.functions.meta);
|
|
31
33
|
const graphMeta = withoutScenarioWorkflows(state.workflows.graphMeta);
|
|
32
34
|
const httpMeta = state.http.meta;
|
|
35
|
+
const tagIndex = buildFunctionTagIndex(state, functionsMeta);
|
|
36
|
+
const tagsFor = (funcId) => tagIndex.get(funcId) ?? [];
|
|
37
|
+
const resolver = createUnitResolver(options.grouping, {
|
|
38
|
+
routesForFunction: (funcId) => collectHttpRoutes(httpMeta, funcId).flatMap((r) => [
|
|
39
|
+
r.route,
|
|
40
|
+
prefixed(r.route),
|
|
41
|
+
]),
|
|
42
|
+
tagsForFunction: tagsFor,
|
|
43
|
+
});
|
|
44
|
+
const addFunctionUnit = (unit) => {
|
|
45
|
+
const existing = units.find((u) => u.name === unit.name);
|
|
46
|
+
if (!existing) {
|
|
47
|
+
units.push(unit);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (existing.target !== unit.target) {
|
|
51
|
+
const rule = resolver.ruleForUnit(unit.name);
|
|
52
|
+
throw new Error(`deploy.grouping: unit "${unit.name}" would hold both serverless and server functions ` +
|
|
53
|
+
`(${existing.functionIds.join(', ')} vs ${unit.functionIds.join(', ')}). ` +
|
|
54
|
+
(rule
|
|
55
|
+
? `Give the server-target functions their own rule, or drop them from "${unit.name}".`
|
|
56
|
+
: `A grouping rule cannot change a function's target.`));
|
|
57
|
+
}
|
|
58
|
+
for (const id of unit.functionIds) {
|
|
59
|
+
if (!existing.functionIds.includes(id)) {
|
|
60
|
+
existing.functionIds.push(id);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const service of unit.services) {
|
|
64
|
+
if (!existing.services.some((s) => s.capability === service.capability &&
|
|
65
|
+
s.sourceServiceName === service.sourceServiceName)) {
|
|
66
|
+
existing.services.push(service);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const dep of unit.dependsOn) {
|
|
70
|
+
if (dep !== existing.name && !existing.dependsOn.includes(dep)) {
|
|
71
|
+
existing.dependsOn.push(dep);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const tag of unit.tags) {
|
|
75
|
+
if (!existing.tags.includes(tag)) {
|
|
76
|
+
existing.tags.push(tag);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const handler of unit.handlers) {
|
|
80
|
+
if (handler.type === 'fetch') {
|
|
81
|
+
const fetchHandler = existing.handlers.find((h) => h.type === 'fetch');
|
|
82
|
+
if (fetchHandler) {
|
|
83
|
+
fetchHandler.routes.push(...handler.routes);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
existing.handlers.push(handler);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
existing.handlers.push(handler);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (unit.invokedAgents?.length) {
|
|
94
|
+
const merged = new Set([
|
|
95
|
+
...(existing.invokedAgents ?? []),
|
|
96
|
+
...unit.invokedAgents,
|
|
97
|
+
]);
|
|
98
|
+
existing.invokedAgents = [...merged];
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const unitFunctionIds = new Map();
|
|
102
|
+
const unitFor = (funcId) => {
|
|
103
|
+
const name = resolver.forFunction(funcId);
|
|
104
|
+
const existing = unitFunctionIds.get(name);
|
|
105
|
+
if (existing) {
|
|
106
|
+
if (!existing.includes(funcId)) {
|
|
107
|
+
existing.push(funcId);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
unitFunctionIds.set(name, [funcId]);
|
|
112
|
+
}
|
|
113
|
+
return name;
|
|
114
|
+
};
|
|
33
115
|
// ── Step 1: Create function units ──────────────────────────────────
|
|
34
116
|
// Each function gets one unit. Collect all its triggers.
|
|
35
117
|
for (const [funcId, funcMeta] of entries(functionsMeta)) {
|
|
@@ -70,7 +152,7 @@ export function analyzeDeployment(state, options) {
|
|
|
70
152
|
handlers.push({ type: 'queue', queueName: queueMeta.name ?? queueName });
|
|
71
153
|
queues.push({
|
|
72
154
|
name: queueMeta.name ?? queueName,
|
|
73
|
-
consumerUnit:
|
|
155
|
+
consumerUnit: unitFor(funcId),
|
|
74
156
|
consumerFunctionId: funcId,
|
|
75
157
|
});
|
|
76
158
|
}
|
|
@@ -86,7 +168,7 @@ export function analyzeDeployment(state, options) {
|
|
|
86
168
|
scheduledTasks.push({
|
|
87
169
|
name: schedMeta.name,
|
|
88
170
|
schedule: schedMeta.schedule,
|
|
89
|
-
unitName:
|
|
171
|
+
unitName: unitFor(funcId),
|
|
90
172
|
functionId: funcId,
|
|
91
173
|
});
|
|
92
174
|
}
|
|
@@ -128,25 +210,72 @@ export function analyzeDeployment(state, options) {
|
|
|
128
210
|
continue;
|
|
129
211
|
}
|
|
130
212
|
const invokedAgents = collectInvokedAgents(state, funcId);
|
|
131
|
-
|
|
132
|
-
name:
|
|
213
|
+
addFunctionUnit({
|
|
214
|
+
name: unitFor(funcId),
|
|
133
215
|
role: 'function',
|
|
134
216
|
target: resolveDeployTarget(funcMeta, serverlessIncompatible, funcId, defaultTarget),
|
|
135
217
|
functionIds: [funcId],
|
|
136
218
|
services: withAgentServices(collectServicesForFunction(funcMeta), invokedAgents),
|
|
137
219
|
dependsOn: [],
|
|
138
220
|
handlers,
|
|
139
|
-
tags:
|
|
221
|
+
tags: tagsFor(funcId),
|
|
140
222
|
...(invokedAgents.length > 0 && { invokedAgents }),
|
|
141
223
|
});
|
|
142
224
|
}
|
|
225
|
+
// ── Step 1b: Addon units ───────────────────────────────────────────
|
|
226
|
+
const addonUnitByRpcName = new Map();
|
|
227
|
+
for (const [namespace, addonMeta] of entries(state.addonFunctions ?? {})) {
|
|
228
|
+
const exposed = entries(addonMeta).filter(([, meta]) => meta.expose);
|
|
229
|
+
if (exposed.length === 0) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const unitName = resolver.forAddon(namespace);
|
|
233
|
+
const addonIncompatible = new Set(state.addonServerlessIncompatible?.get(namespace) ?? []);
|
|
234
|
+
const routes = [];
|
|
235
|
+
const functionIds = [];
|
|
236
|
+
const services = [];
|
|
237
|
+
let target = defaultTarget;
|
|
238
|
+
for (const [funcName, funcMeta] of exposed) {
|
|
239
|
+
const rpcName = `${namespace}:${funcName}`;
|
|
240
|
+
functionIds.push(rpcName);
|
|
241
|
+
addonUnitByRpcName.set(rpcName, unitName);
|
|
242
|
+
routes.push({
|
|
243
|
+
method: 'post',
|
|
244
|
+
route: prefixed(`/rpc/${rpcName}`),
|
|
245
|
+
pikkuFuncId: rpcName,
|
|
246
|
+
});
|
|
247
|
+
routes.push({
|
|
248
|
+
method: 'post',
|
|
249
|
+
route: prefixed(`/remote/rpc/${rpcName}`),
|
|
250
|
+
pikkuFuncId: rpcName,
|
|
251
|
+
});
|
|
252
|
+
for (const service of collectServicesForFunction(funcMeta)) {
|
|
253
|
+
if (!services.some((s) => s.sourceServiceName === service.sourceServiceName)) {
|
|
254
|
+
services.push(service);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (resolveDeployTarget(funcMeta, addonIncompatible, rpcName, defaultTarget) === 'server') {
|
|
258
|
+
target = 'server';
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
addFunctionUnit({
|
|
262
|
+
name: unitName,
|
|
263
|
+
role: 'function',
|
|
264
|
+
target,
|
|
265
|
+
functionIds,
|
|
266
|
+
services,
|
|
267
|
+
dependsOn: [],
|
|
268
|
+
handlers: [{ type: 'fetch', routes }],
|
|
269
|
+
tags: [],
|
|
270
|
+
});
|
|
271
|
+
}
|
|
143
272
|
// ── Step 2: Agent gateways ─────────────────────────────────────────
|
|
144
273
|
for (const [agentName, agentMeta] of entries(state.agents.agentsMeta)) {
|
|
145
274
|
const toolIds = agentMeta.tools ?? [];
|
|
146
275
|
const subAgentNames = agentMeta.agents ?? [];
|
|
147
276
|
const unitName = `agent-${toSafeKebab(agentName)}`;
|
|
148
277
|
// Agent gateway depends on its tool function units
|
|
149
|
-
const toolUnitNames = toolIds.map((id) =>
|
|
278
|
+
const toolUnitNames = toolIds.map((id) => unitFor(id));
|
|
150
279
|
const subAgentUnitNames = subAgentNames.map((sa) => `agent-${toSafeKebab(sa)}`);
|
|
151
280
|
// Agent needs AI services
|
|
152
281
|
const agentServices = agentServiceRequirements();
|
|
@@ -224,7 +353,7 @@ export function analyzeDeployment(state, options) {
|
|
|
224
353
|
const allMcpIds = [...mcpToolIds, ...mcpResourceIds, ...mcpPromptIds];
|
|
225
354
|
if (allMcpIds.length > 0) {
|
|
226
355
|
const unitName = 'mcp-server';
|
|
227
|
-
const mcpFuncUnitNames = allMcpIds.map((id) =>
|
|
356
|
+
const mcpFuncUnitNames = allMcpIds.map((id) => unitFor(id));
|
|
228
357
|
units.push({
|
|
229
358
|
name: unitName,
|
|
230
359
|
role: 'mcp',
|
|
@@ -233,7 +362,7 @@ export function analyzeDeployment(state, options) {
|
|
|
233
362
|
services: [],
|
|
234
363
|
dependsOn: mcpFuncUnitNames,
|
|
235
364
|
handlers: [{ type: 'fetch', routes: [] }],
|
|
236
|
-
tags: collectTags(allMcpIds,
|
|
365
|
+
tags: collectTags(allMcpIds, tagsFor),
|
|
237
366
|
});
|
|
238
367
|
mcpEndpoints.push({
|
|
239
368
|
unitName,
|
|
@@ -248,7 +377,7 @@ export function analyzeDeployment(state, options) {
|
|
|
248
377
|
if (funcIds.length === 0)
|
|
249
378
|
continue;
|
|
250
379
|
const unitName = `channel-${toSafeKebab(channelName)}`;
|
|
251
|
-
const funcUnitNames = funcIds.map((id) =>
|
|
380
|
+
const funcUnitNames = funcIds.map((id) => unitFor(id));
|
|
252
381
|
units.push({
|
|
253
382
|
name: unitName,
|
|
254
383
|
role: 'channel',
|
|
@@ -267,34 +396,35 @@ export function analyzeDeployment(state, options) {
|
|
|
267
396
|
});
|
|
268
397
|
}
|
|
269
398
|
// ── Step 5: Workflows ──────────────────────────────────────────────
|
|
270
|
-
buildWorkflows(graphMeta, functionsMeta, { ...state.rpc?.exposedMeta, ...state.rpc?.internalMeta }, httpMeta, units, workflows, queues, workflowQueues);
|
|
399
|
+
buildWorkflows(graphMeta, functionsMeta, { ...state.rpc?.exposedMeta, ...state.rpc?.internalMeta }, httpMeta, units, workflows, queues, workflowQueues, unitFor);
|
|
271
400
|
// ── Step 6: Ensure function units exist for gateway dependencies ───
|
|
272
401
|
// Gateways depend on function units. If a function is only used via
|
|
273
402
|
// a gateway (not directly wired to HTTP/queue/cron), it still needs
|
|
274
403
|
// a unit with a fetch handler for RPC access.
|
|
275
|
-
const existingUnitNames = new Set(units.map((u) => u.name));
|
|
276
404
|
const unitsSnapshot = Array.from(units);
|
|
277
405
|
for (const unit of unitsSnapshot) {
|
|
278
406
|
for (const dep of unit.dependsOn) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
407
|
+
for (const funcId of unitFunctionIds.get(dep) ?? []) {
|
|
408
|
+
const existing = units.find((u) => u.name === dep);
|
|
409
|
+
if (existing?.functionIds.includes(funcId)) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
282
412
|
const funcMeta = functionsMeta[funcId];
|
|
283
|
-
if (funcMeta) {
|
|
284
|
-
|
|
285
|
-
units.push({
|
|
286
|
-
name: dep,
|
|
287
|
-
role: 'function',
|
|
288
|
-
target: resolveDeployTarget(funcMeta, serverlessIncompatible, funcId, defaultTarget),
|
|
289
|
-
functionIds: [funcId],
|
|
290
|
-
services: withAgentServices(collectServicesForFunction(funcMeta), invokedAgents),
|
|
291
|
-
dependsOn: [],
|
|
292
|
-
handlers: [{ type: 'fetch', routes: [] }],
|
|
293
|
-
tags: funcMeta.tags ?? [],
|
|
294
|
-
...(invokedAgents.length > 0 && { invokedAgents }),
|
|
295
|
-
});
|
|
296
|
-
existingUnitNames.add(dep);
|
|
413
|
+
if (!funcMeta) {
|
|
414
|
+
continue;
|
|
297
415
|
}
|
|
416
|
+
const invokedAgents = collectInvokedAgents(state, funcId);
|
|
417
|
+
addFunctionUnit({
|
|
418
|
+
name: dep,
|
|
419
|
+
role: 'function',
|
|
420
|
+
target: resolveDeployTarget(funcMeta, serverlessIncompatible, funcId, defaultTarget),
|
|
421
|
+
functionIds: [funcId],
|
|
422
|
+
services: withAgentServices(collectServicesForFunction(funcMeta), invokedAgents),
|
|
423
|
+
dependsOn: [],
|
|
424
|
+
handlers: [{ type: 'fetch', routes: [] }],
|
|
425
|
+
tags: tagsFor(funcId),
|
|
426
|
+
...(invokedAgents.length > 0 && { invokedAgents }),
|
|
427
|
+
});
|
|
298
428
|
}
|
|
299
429
|
}
|
|
300
430
|
}
|
|
@@ -457,6 +587,25 @@ export function analyzeDeployment(state, options) {
|
|
|
457
587
|
}
|
|
458
588
|
}
|
|
459
589
|
}
|
|
590
|
+
if (addonUnitByRpcName.size > 0) {
|
|
591
|
+
const catchAll = prefixed('/rpc/:rpcName');
|
|
592
|
+
for (const unit of units) {
|
|
593
|
+
if (addonUnitByRpcName.has(unit.functionIds[0] ?? ''))
|
|
594
|
+
continue;
|
|
595
|
+
const servesCatchAll = unit.handlers.some((handler) => handler.type === 'fetch' &&
|
|
596
|
+
handler.routes.some((route) => route.route === catchAll));
|
|
597
|
+
if (!servesCatchAll)
|
|
598
|
+
continue;
|
|
599
|
+
const dispatch = { ...(unit.dispatch ?? {}) };
|
|
600
|
+
for (const [rpcName, unitName] of addonUnitByRpcName) {
|
|
601
|
+
dispatch[rpcName] = unitName;
|
|
602
|
+
if (!unit.dependsOn.includes(unitName)) {
|
|
603
|
+
unit.dependsOn.push(unitName);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
unit.dispatch = dispatch;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
460
609
|
const byNamespace = (a, b) => a.namespace.localeCompare(b.namespace);
|
|
461
610
|
const variablesById = new Map();
|
|
462
611
|
for (const v of state.variables.definitions) {
|
|
@@ -491,7 +640,7 @@ export function analyzeDeployment(state, options) {
|
|
|
491
640
|
// ---------------------------------------------------------------------------
|
|
492
641
|
// Workflow builder
|
|
493
642
|
// ---------------------------------------------------------------------------
|
|
494
|
-
function buildWorkflows(graphMeta, functionsMeta, rpcMeta, _httpMeta, units, workflows, queues, workflowQueues) {
|
|
643
|
+
function buildWorkflows(graphMeta, functionsMeta, rpcMeta, _httpMeta, units, workflows, queues, workflowQueues, unitFor) {
|
|
495
644
|
for (const [_wfName, graph] of entries(graphMeta)) {
|
|
496
645
|
const steps = [];
|
|
497
646
|
const stepUnitNames = [];
|
|
@@ -500,7 +649,7 @@ function buildWorkflows(graphMeta, functionsMeta, rpcMeta, _httpMeta, units, wor
|
|
|
500
649
|
continue;
|
|
501
650
|
if (!('rpcName' in node))
|
|
502
651
|
continue;
|
|
503
|
-
const stepUnitName =
|
|
652
|
+
const stepUnitName = unitFor(node.rpcName);
|
|
504
653
|
// Step dispatch is decided per-function: a step runs inline unless its
|
|
505
654
|
// function is marked `workflowQueued: true` (then it dispatches via queue).
|
|
506
655
|
const stepFuncId = rpcMeta[node.rpcName] ?? node.rpcName;
|
|
@@ -588,7 +737,7 @@ function buildWorkflows(graphMeta, functionsMeta, rpcMeta, _httpMeta, units, wor
|
|
|
588
737
|
const stepQueueName = `wf-step-${toSafeKebab(step.functionId)}`;
|
|
589
738
|
queues.push({
|
|
590
739
|
name: stepQueueName,
|
|
591
|
-
consumerUnit:
|
|
740
|
+
consumerUnit: unitFor(step.functionId),
|
|
592
741
|
consumerFunctionId: `pikkuWorkflowWorker:${step.functionId}`,
|
|
593
742
|
});
|
|
594
743
|
}
|
|
@@ -731,32 +880,71 @@ function collectChannelFunctionIds(channelMeta) {
|
|
|
731
880
|
// ---------------------------------------------------------------------------
|
|
732
881
|
// Naming helpers
|
|
733
882
|
// ---------------------------------------------------------------------------
|
|
734
|
-
export
|
|
735
|
-
return str
|
|
736
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
737
|
-
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
738
|
-
.replace(/[:/\\]/g, '-')
|
|
739
|
-
.replace(/--+/g, '-')
|
|
740
|
-
.replace(/^-|-$/g, '')
|
|
741
|
-
.toLowerCase();
|
|
742
|
-
}
|
|
743
|
-
function fromKebab(str) {
|
|
744
|
-
return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
745
|
-
}
|
|
883
|
+
export { toSafeKebab } from './naming.js';
|
|
746
884
|
// ---------------------------------------------------------------------------
|
|
747
885
|
// Tag helpers
|
|
748
886
|
// ---------------------------------------------------------------------------
|
|
749
|
-
function collectTags(funcIds,
|
|
887
|
+
function collectTags(funcIds, tagsFor) {
|
|
750
888
|
const tags = new Set();
|
|
751
889
|
for (const id of funcIds) {
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
for (const tag of meta.tags)
|
|
755
|
-
tags.add(tag);
|
|
756
|
-
}
|
|
890
|
+
for (const tag of tagsFor(id))
|
|
891
|
+
tags.add(tag);
|
|
757
892
|
}
|
|
758
893
|
return [...tags];
|
|
759
894
|
}
|
|
895
|
+
/**
|
|
896
|
+
* Every tag that applies to a function, from the function itself and from every
|
|
897
|
+
* wiring that reaches it.
|
|
898
|
+
*
|
|
899
|
+
* Tags are almost always written on the wiring — `wireHTTP({ tags: ['todos'] })`
|
|
900
|
+
* — not on the `pikkuFunc`, so reading `FunctionMeta.tags` alone sees nothing in
|
|
901
|
+
* a typical project. `deploy.grouping` matches on the tags a user actually
|
|
902
|
+
* wrote, which means the union.
|
|
903
|
+
*/
|
|
904
|
+
function buildFunctionTagIndex(state, functionsMeta) {
|
|
905
|
+
const index = new Map();
|
|
906
|
+
const add = (funcId, tags) => {
|
|
907
|
+
if (!funcId || !tags?.length)
|
|
908
|
+
return;
|
|
909
|
+
let set = index.get(funcId);
|
|
910
|
+
if (!set) {
|
|
911
|
+
set = new Set();
|
|
912
|
+
index.set(funcId, set);
|
|
913
|
+
}
|
|
914
|
+
for (const tag of tags)
|
|
915
|
+
set.add(tag);
|
|
916
|
+
};
|
|
917
|
+
for (const [funcId, meta] of entries(functionsMeta)) {
|
|
918
|
+
add(funcId, meta.tags);
|
|
919
|
+
}
|
|
920
|
+
for (const method of HTTP_METHODS) {
|
|
921
|
+
const methodRoutes = state.http?.meta?.[method];
|
|
922
|
+
if (!methodRoutes)
|
|
923
|
+
continue;
|
|
924
|
+
for (const routeMeta of values(methodRoutes)) {
|
|
925
|
+
add(routeMeta.pikkuFuncId, routeMeta.tags);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
for (const meta of values(state.queueWorkers?.meta ?? {})) {
|
|
929
|
+
add(meta.pikkuFuncId, meta.tags);
|
|
930
|
+
}
|
|
931
|
+
for (const meta of values(state.scheduledTasks?.meta ?? {})) {
|
|
932
|
+
add(meta.pikkuFuncId, meta.tags);
|
|
933
|
+
}
|
|
934
|
+
for (const meta of [
|
|
935
|
+
...values(state.mcpEndpoints?.toolsMeta ?? {}),
|
|
936
|
+
...values(state.mcpEndpoints?.resourcesMeta ?? {}),
|
|
937
|
+
...values(state.mcpEndpoints?.promptsMeta ?? {}),
|
|
938
|
+
]) {
|
|
939
|
+
add(meta.pikkuFuncId, meta.tags);
|
|
940
|
+
}
|
|
941
|
+
for (const channelMeta of values(state.channels?.meta ?? {})) {
|
|
942
|
+
for (const funcId of collectChannelFunctionIds(channelMeta)) {
|
|
943
|
+
add(funcId, channelMeta.tags);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return new Map([...index].map(([funcId, tags]) => [funcId, [...tags]]));
|
|
947
|
+
}
|
|
760
948
|
// ---------------------------------------------------------------------------
|
|
761
949
|
// Typed iteration helpers
|
|
762
950
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type GroupingStrategy = 'function' | 'single';
|
|
2
|
+
export interface GroupingRule {
|
|
3
|
+
unit: string;
|
|
4
|
+
tags?: string[];
|
|
5
|
+
addon?: string;
|
|
6
|
+
routes?: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface GroupingConfig {
|
|
9
|
+
strategy?: GroupingStrategy;
|
|
10
|
+
rules?: GroupingRule[];
|
|
11
|
+
}
|
|
12
|
+
export interface UnitResolverInput {
|
|
13
|
+
routesForFunction: (funcId: string) => string[];
|
|
14
|
+
tagsForFunction: (funcId: string) => string[];
|
|
15
|
+
}
|
|
16
|
+
export interface UnitResolver {
|
|
17
|
+
forFunction: (funcId: string) => string;
|
|
18
|
+
forAddon: (namespace: string) => string;
|
|
19
|
+
isGrouped: boolean;
|
|
20
|
+
ruleForUnit: (unitName: string) => GroupingRule | undefined;
|
|
21
|
+
}
|
|
22
|
+
export declare const validateGrouping: (config: GroupingConfig) => void;
|
|
23
|
+
export declare const createUnitResolver: (config: GroupingConfig | undefined, input: UnitResolverInput) => UnitResolver;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { toSafeKebab } from './naming.js';
|
|
2
|
+
const SINGLE_UNIT_NAME = 'app';
|
|
3
|
+
const routeMatcher = (pattern) => {
|
|
4
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
5
|
+
return new RegExp(`^${escaped.replace(/\*/g, '.*')}$`);
|
|
6
|
+
};
|
|
7
|
+
export const validateGrouping = (config) => {
|
|
8
|
+
const rules = config.rules ?? [];
|
|
9
|
+
const seen = new Set();
|
|
10
|
+
for (const rule of rules) {
|
|
11
|
+
if (!rule.unit) {
|
|
12
|
+
throw new Error(`deploy.grouping: every rule needs a "unit" name (offending rule: ${JSON.stringify(rule)})`);
|
|
13
|
+
}
|
|
14
|
+
if (seen.has(rule.unit)) {
|
|
15
|
+
throw new Error(`deploy.grouping: two rules both name the unit "${rule.unit}". Merge them into one rule.`);
|
|
16
|
+
}
|
|
17
|
+
seen.add(rule.unit);
|
|
18
|
+
if (!rule.tags?.length && !rule.addon && !rule.routes?.length) {
|
|
19
|
+
throw new Error(`deploy.grouping: rule "${rule.unit}" matches nothing. Give it at least one of "tags", "addon" or "routes".`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const createUnitResolver = (config, input) => {
|
|
24
|
+
const strategy = config?.strategy ?? 'function';
|
|
25
|
+
const rules = config?.rules ?? [];
|
|
26
|
+
if (config) {
|
|
27
|
+
validateGrouping(config);
|
|
28
|
+
}
|
|
29
|
+
const compiled = rules.map((rule) => ({
|
|
30
|
+
rule,
|
|
31
|
+
unit: toSafeKebab(rule.unit),
|
|
32
|
+
tags: rule.tags,
|
|
33
|
+
addon: rule.addon,
|
|
34
|
+
routes: rule.routes?.map(routeMatcher),
|
|
35
|
+
}));
|
|
36
|
+
const byUnitName = new Map(compiled.map((c) => [c.unit, c.rule]));
|
|
37
|
+
const matches = (c, tags, routes, addon) => {
|
|
38
|
+
if (c.tags && !c.tags.some((tag) => tags.includes(tag))) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (c.addon && c.addon !== addon) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (c.routes && !c.routes.some((re) => routes.some((r) => re.test(r)))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
const fallback = (funcId) => strategy === 'single' ? SINGLE_UNIT_NAME : toSafeKebab(funcId);
|
|
50
|
+
return {
|
|
51
|
+
isGrouped: strategy !== 'function' || compiled.length > 0,
|
|
52
|
+
ruleForUnit: (unitName) => byUnitName.get(unitName),
|
|
53
|
+
forFunction: (funcId) => {
|
|
54
|
+
if (compiled.length > 0) {
|
|
55
|
+
const tags = input.tagsForFunction(funcId);
|
|
56
|
+
const routes = input.routesForFunction(funcId);
|
|
57
|
+
for (const c of compiled) {
|
|
58
|
+
if (matches(c, tags, routes, undefined)) {
|
|
59
|
+
return c.unit;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return fallback(funcId);
|
|
64
|
+
},
|
|
65
|
+
forAddon: (namespace) => {
|
|
66
|
+
for (const c of compiled) {
|
|
67
|
+
if (c.addon === namespace && !c.tags && !c.routes) {
|
|
68
|
+
return c.unit;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return `addon-${toSafeKebab(namespace)}`;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function toSafeKebab(str: string): string;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { InspectorState } from '@pikku/inspector';
|
|
8
8
|
import { PikkuError } from '@pikku/core/errors';
|
|
9
|
+
import type { GroupingConfig } from './analyzer/index.js';
|
|
9
10
|
import type { DeploymentManifest } from '@pikku/deploy';
|
|
10
11
|
import type { Bundler } from './bundler/bundler.interface.js';
|
|
11
12
|
import type { BundleResult } from './bundler/types.js';
|
|
@@ -50,6 +51,7 @@ export declare function runBuildPipeline(options: {
|
|
|
50
51
|
inspectorState: InspectorState;
|
|
51
52
|
serverlessIncompatible?: string[];
|
|
52
53
|
defaultTarget?: 'serverless' | 'server';
|
|
54
|
+
grouping?: GroupingConfig;
|
|
53
55
|
globalHTTPPrefix?: string;
|
|
54
56
|
getEntryContext: (unitDir: string, pikkuDir: string, unit: DeploymentManifest['units'][0], state: InspectorState) => unknown;
|
|
55
57
|
/**
|
|
@@ -153,6 +153,7 @@ export async function runBuildPipeline(options) {
|
|
|
153
153
|
projectId,
|
|
154
154
|
serverlessIncompatible: options.serverlessIncompatible,
|
|
155
155
|
defaultTarget: options.defaultTarget,
|
|
156
|
+
grouping: options.grouping,
|
|
156
157
|
globalHTTPPrefix: options.globalHTTPPrefix,
|
|
157
158
|
workflowQueues,
|
|
158
159
|
});
|
|
@@ -299,7 +300,26 @@ export async function runBuildPipeline(options) {
|
|
|
299
300
|
unitPikkuDirs.set(k, v);
|
|
300
301
|
codegenErrors.push(...serverCodegenErrors);
|
|
301
302
|
// Replace individual server units with the merged one in the manifest
|
|
303
|
+
const mergedNames = new Set(serverUnits.map((u) => u.name));
|
|
302
304
|
manifest.units = [...serverlessUnits, mergedServerUnit];
|
|
305
|
+
// Anything that named one of the units just folded away has to follow it,
|
|
306
|
+
// or the manifest ships a queue consumer and a cron pointing at a unit
|
|
307
|
+
// that no longer exists.
|
|
308
|
+
for (const queue of manifest.queues) {
|
|
309
|
+
if (mergedNames.has(queue.consumerUnit)) {
|
|
310
|
+
queue.consumerUnit = serverUnitName;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
for (const task of manifest.scheduledTasks) {
|
|
314
|
+
if (mergedNames.has(task.unitName)) {
|
|
315
|
+
task.unitName = serverUnitName;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
for (const unit of manifest.units) {
|
|
319
|
+
unit.dependsOn = [
|
|
320
|
+
...new Set(unit.dependsOn.map((dep) => mergedNames.has(dep) ? serverUnitName : dep)),
|
|
321
|
+
].filter((dep) => dep !== unit.name);
|
|
322
|
+
}
|
|
303
323
|
logger.info(` Server container: ${serverUnits.length} functions merged into one unit`);
|
|
304
324
|
}
|
|
305
325
|
logger.info(`Codegen complete: ${unitPikkuDirs.size} units`);
|