VVibeFlui

Transformers

Transformers modify values before submission or after responses.

Use transformers for UI-level value normalization, request shaping, and response shaping. Do not use transformers to hide backend validation or authorization requirements.

Field transformer

schemas/users/user-form.schema.ts

TS
export const userFormSchema = {
  version: "1.0.0",
  resource: "users",
  form: {
    fields: [
      {
        name: "name",
        label: "Name",
        type: "text",
        transformer: "strings.trim"
      }
    ]
  },
  registry: {
    transformers: ["strings.trim"]
  }
} as const;

Request transformer

schemas/users/users.schema.ts

TS
export const usersSchema = {
  version: "1.0.0",
  resource: "users",
  transform: {
    request: "users.requestPayload"
  },
  registry: {
    transformers: ["users.requestPayload"]
  }
} as const;

Before-submit pipeline

schemas/users/users.schema.ts

TS
export const usersSchema = {
  version: "1.0.0",
  resource: "users",
  transform: {
    beforeSubmit: [
      { runtime: "client", transformer: "strings.trimAll" },
      { runtime: "client", handler: "users.preparePayload" },
      { runtime: "server", endpoint: { url: "/api/users/validate", method: "POST" } }
    ]
  },
  registry: {
    transformers: ["strings.trimAll"],
    actionHandlers: ["users.preparePayload"]
  }
} as const;

Runtime registry

lib/vibeflui/registry.ts

TS
import { createRegistry } from "@vibeflui/core";

export const registry = createRegistry({
  transformers: {
    "strings.trim": (value) => {
      return typeof value === "string" ? value.trim() : value;
    },
    "strings.trimAll": (value) => {
      if (!value || typeof value !== "object") return value;

      return Object.fromEntries(
        Object.entries(value).map(([key, entry]) => [
          key,
          typeof entry === "string" ? entry.trim() : entry
        ])
      );
    },
    "users.requestPayload": (value) => {
      if (!value || typeof value !== "object") return value;

      return {
        user: value
      };
    }
  },
  actionHandlers: {
    "users.preparePayload": async ({ values }) => {
      return {
        ...values,
        preparedAt: new Date().toISOString()
      };
    }
  }
});

Response transformer

schemas/users/users.schema.ts

TS
export const usersSchema = {
  version: "1.0.0",
  resource: "users",
  transform: {
    response: "users.response"
  },
  registry: {
    transformers: ["users.response"]
  }
} as const;

Backend responsibility

Transformers can shape data for UI convenience. The backend still owns final validation, workflows, and persistence.