• English
  • VextJS Adoption

    VextJS is the first intended consumer of commflow, while commflow core remains framework-agnostic. Adoption moves communication orchestration into commflow without losing VextJS request context, logging, hooks, or proxy behavior.

    Current release: commflow@0.0.2 only provides the manifest API; it has no request runtime or VextJS adapter. VextJS does not expose a public app.setFetch() API, so a plugin cannot directly replace built-in app.fetch.

    Available in VextJS today: create a dedicated subclient with app.fetch.create() and mount it with app.extend(). This does not replace app.fetch and does not depend on the unreleased commflow runtime.

    Use A Dedicated VextJS Client Today

    This is a runnable shape using published VextJS APIs to create an isolated client for one downstream service:

    // src/plugins/service-clients.ts
    import { definePlugin } from 'vextjs';
    
    export default definePlugin({
      name: 'service-clients',
      setup(app) {
        app.extend('userClient', app.fetch.create({
          baseURL: process.env.USER_SERVICE_URL ?? 'http://user-service:3001',
          timeout: 5000,
          retry: 2
        }));
      }
    });

    This subclient is a dedicated instance of current VextJS app.fetch, not a commflow client. It does not replace app.fetch. Use this or built-in app.fetch for an outbound call you need today; use Current Release Quick Start to inspect the current commflow package.

    Inventory Existing Behavior First

    VextJS app.fetch already owns the behaviors below. Adoption must preserve each behavior rather than only replacing the call function.

    app.fetch capabilitycommflow responsibilityCompatibility requirement
    Native fetch plus GET/POST/PUT/PATCH/DELETErequest clientKeep native Response semantics
    create({ baseURL, headers, timeout, retry })client / target defaultsPreserve option precedence and header merging
    timeoutrequest timeoutBoth user and timeout signals can abort the call
    idempotent retryretry policyGET/HEAD/OPTIONS/PUT/DELETE may retry; POST/PATCH do not by default
    requestId and selected header propagationVextJS contextProviderRead current request context without business-code plumbing
    outbound hooks and structured logshooks / adapterPreserve method, URL, status, duration, requestId, and error fields
    app.fetch.proxyVextJS adapterPreserve response passthrough, header allowlists, explicit Authorization forwarding, and client-disconnect handling

    Planned commflow Adoption Path (Not A Current Import)

    Stage 1: Mount In Parallel

    After commflow publishes a request runtime, create a request client in a VextJS plugin and mount a separate entry with app.extend(). Keep app.fetch in place and migrate one low-risk downstream service first.

    import { createCommflowRequestClient } from 'commflow';
    import { definePlugin, requestContext } from 'vextjs';
    
    declare module 'vextjs' {
      interface VextConfig {
        services: {
          user: string;
        };
      }
    
      interface VextApp {
        commflow: ReturnType<typeof createCommflowRequestClient>;
      }
    }
    
    export default definePlugin({
      name: 'commflow',
      setup(app) {
        app.extend('commflow', createCommflowRequestClient({
          baseURL: app.config.services.user,
          timeout: 5000,
          retry: 1,
          contextProvider: () => ({
            requestId: requestContext.getStore()?.requestId
          })
        }));
      }
    });

    This is the planned-contract adoption shape, not a runnable commflow@0.0.2 import. Parallel mounting lets you verify the future request core without changing framework internals.

    The application config must define where services.user comes from:

    export default {
      services: {
        user: 'https://user-service.internal'
      }
    };

    app.extend() only mounts outbound clients or helper capabilities. It does not register business routes. Inbound RPC/SSE/socket paths should mount handlers through src/routes/** and defineRoutes().

    Stage 2: Migrate By Call Shape

    Use this order so failure semantics do not all change at once:

    1. Idempotent GET calls without proxy or custom hooks.
    2. Service clients currently created with create().
    3. Calls with context and header propagation.
    4. Non-idempotent writes and custom retry behavior.
    5. Proxy and streamed responses.

    For each group, compare status handling, thrown errors, retry counts, log fields, and requestId propagation.

    Stage 3: Replace The Built-In Path

    Only switch the underlying app.fetch implementation after VextJS provides a stable injection point and every compatibility check passes. Keep the business-facing call signature stable. VextJS-specific request context, logger, hook, and proxy bridges belong in the adapter, not the framework-agnostic core.

    Configuration Mapping

    VextJS optioncommflow optionMigration note
    config.fetch.timeoutclient timeoutPer-call override remains highest priority
    config.fetch.retryclient retryPreserve whether the number means extra attempts
    config.fetch.retryDelayretry delay / backoffPreserve function attempt numbering
    config.fetch.propagateHeaderscontextProvider / adapter headersPropagate allowlisted fields only
    config.fetch.proxy[]adapter targetsProxy response passthrough differs from normal request returns

    Compatibility Checklist

    ScenarioRequired result
    2xx / 3xx / 4xxReturn Response; do not turn 4xx into a transport error
    Final 5xxReturn the final Response after retries are exhausted
    Network failureThrow a network error after retries are exhausted
    TimeoutAbort and throw a timeout error without automatic retry
    Non-idempotent methodsDo not replay POST/PATCH by default
    requestId / trace headersPropagate from the current VextJS request context
    ProxyPass through upstream status and body; map only local failures to VextJS errors
    AuthorizationForward only when both allowlisted and explicitly enabled
    Client disconnectCancel the active upstream proxy request and release streams

    Other Communication Styles

    After request adoption is stable, add the capabilities you need:

    • RPC: mount the RPC handler through a VextJS route and mount the typed client on app context.
    • SSE: reuse request context and error semantics while managing subscription close and reconnect separately.
    • Socket: reuse metadata and error normalization while keeping connection, heartbeat, and reconnect lifecycles independent.

    Using The Current Release

    When you use commflow@0.0.2, do not import the request client from this page's planned section. Run Current Release Quick Start to verify the manifest; for a VextJS outbound client today, use the app.fetch.create() + app.extend() path above.