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.