Skip to content

WIP refactor(pactflow): break pactflow client.ts into smaller components#420

Draft
kevinrvaz wants to merge 1 commit intomainfrom
refactor_pactflow_client_implementation
Draft

WIP refactor(pactflow): break pactflow client.ts into smaller components#420
kevinrvaz wants to merge 1 commit intomainfrom
refactor_pactflow_client_implementation

Conversation

@kevinrvaz
Copy link
Copy Markdown
Member

@kevinrvaz kevinrvaz commented Apr 10, 2026

Goal

The client.ts and tests for it had grown very large, this pr breaks it down into smaller components

new client.ts architecture:-

graph TB
      subgraph Entry["Entry Point"]
          CLIENT["PactflowClient\nclient.ts"]
      end

      subgraph Composition["Mixin Composition (applyMixins)"]
          AI_M["PactflowAiMethods\ngenerate · review · checkAIEntitlements"]
          PAC_M["PactflowPacticipantMethods\npacticipants · branches · versions"]
          ENV_M["PactflowEnvironmentMethods\nenvironments · deployments · releases"]
          CON_M["PactflowContractMethods\npacts · verifications · BDCT · matrix"]
          SET_M["PactflowSettingsMethods\nsecrets · tokens · preferences · audit"]
          ADM_M["PactflowAdminMethods\nusers · teams · roles · system accounts"]
      end

      subgraph Core["Core Engine"]
          BASE["PactflowBaseClient\nbase-client.ts\n─────────────────\nfetchJson()\nconfigure()\npollForCompletion()\nsubmitHttpCallback()\ngetStatus() · getResult()"]
      end

      subgraph Definitions["Static Definitions"]
          TOOLS["tools.ts\nMCP tool metadata\n+ handler names"]
          PROMPTS["prompts.ts\nMCP prompt templates"]
          BASE_TYPES["base.ts\nZod schemas + TS types\nfor all API inputs/outputs"]
          AI_TYPES["ai.ts\nAI-specific schemas\nGenerationInput · RefineInput"]
      end

      subgraph Helpers["Helpers"]
          UTILS["utils.ts\nOpenAPI spec fetch\n+ YAML/JSON parse"]
          PROMPT_UTILS["prompt-utils.ts\nsampling recommendations\nelicitation flow"]
      end

      subgraph Auth["Auth (configure)"]
          BEARER["Bearer token\nPactFlow SaaS"]
          BASIC["Basic auth\nPact Broker"]
      end

      subgraph Transport["HTTP Transport"]
          FETCH["fetch()"]
          AI_API["/api/ai/generate\n/api/ai/review\n/api/ai/entitlement"]
          BROKER_API["/pacticipants\n/environments\n/can-i-deploy\n/admin/users\n..."]
      end

      CLIENT -->|"extends"| BASE
      CLIENT -->|"applyMixins() at startup"| AI_M
      CLIENT -->|"applyMixins() at startup"| PAC_M
      CLIENT -->|"applyMixins() at startup"| ENV_M
      CLIENT -->|"applyMixins() at startup"| CON_M
      CLIENT -->|"applyMixins() at startup"| SET_M
      CLIENT -->|"applyMixins() at startup"| ADM_M

      AI_M -->|"extends"| BASE
      PAC_M -->|"extends"| BASE
      ENV_M -->|"extends"| BASE
      CON_M -->|"extends"| BASE
      SET_M -->|"extends"| BASE
      ADM_M -->|"extends"| BASE

      CLIENT -->|"reads"| TOOLS
      CLIENT -->|"reads"| PROMPTS

      AI_M -->|"uses"| PROMPT_UTILS
      AI_M -->|"uses"| AI_TYPES
      CON_M -->|"uses"| UTILS

      BASE -->|"Bearer / Basic"| BEARER
      BASE -->|"Bearer / Basic"| BASIC
      BASE -->|"fetch()"| FETCH

      FETCH --> AI_API
      FETCH --> BROKER_API

      TOOLS -->|"references schemas from"| BASE_TYPES
      TOOLS -->|"references schemas from"| AI_TYPES

      style CLIENT fill:#4a90d9,color:#fff
      style BASE fill:#2c5f8a,color:#fff
      style AI_M fill:#5b8a3c,color:#fff
      style PAC_M fill:#5b8a3c,color:#fff
      style ENV_M fill:#5b8a3c,color:#fff
      style CON_M fill:#5b8a3c,color:#fff
      style SET_M fill:#5b8a3c,color:#fff
      style ADM_M fill:#5b8a3c,color:#fff
Loading

Request flow:-

 sequenceDiagram
      participant MCP as MCP Client
      participant RT as registerTools()
      participant MG as Method Group
      participant BC as fetchJson()
      participant API as PactFlow / Broker API

      MCP->>RT: tool call (args)
      RT->>RT: filter by clientType + AI tags
      RT->>MG: this[handler](args, ?getInput)
      MG->>BC: fetchJson(url, { method, body })
      BC->>API: fetch() + Bearer/Basic headers

      alt 204 No Content
          API-->>BC: 204
          BC-->>MG: undefined
      else Success
          API-->>BC: 200 + JSON
          BC-->>MG: parsed response
      else Error
          API-->>BC: 4xx/5xx
          BC-->>MG: throw ToolError(status)
      end

      MG-->>RT: result
      RT->>RT: formatResponse() if defined
      RT-->>MCP: { content: [{ type: "text", text: JSON }] }
Loading

AI async polling flow:-

 sequenceDiagram
     participant MG as ai-methods.ts
     participant BC as base-client.ts
     participant API as /api/ai

     MG->>BC: submitHttpCallback("/generate", body)
     BC->>API: POST /api/ai/generate
     API-->>BC: { status_url, result_url }
     BC-->>MG: StatusResponse

     loop every 1s (max 120s)
         MG->>BC: pollForCompletion()
         BC->>API: HEAD status_url
         alt still processing
             API-->>BC: 202
         else done
             API-->>BC: 200
             BC->>API: GET result_url
             API-->>BC: GenerationResponse
             BC-->>MG: result
         end
     end
Loading

Changeset

No new functional change is being added just code structure change.

Testing

in progress not yet ready

@kevinrvaz kevinrvaz requested a review from a team as a code owner April 10, 2026 15:21
@kevinrvaz kevinrvaz marked this pull request as draft April 10, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant