Skip to content

Validation – fluent-wp-client

fluent-wp-client keeps request validation aligned with WordPress itself. The client sends normal REST payloads, and WordPress remains the source of truth for what is valid.

When you want local validation in your app, use one of these schema sources:

NeedBest tool
Validate one resource or ability at runtime.describe() + zodFromJsonSchema()
Validate many resources with one runtime fetch.explore() + zodSchemasFromDescription()
Check in schema files for Astro, CI, or shared app codeCLI schemas command

Convert any discovered JSON Schema to a Zod validator on the fly:

import { zodFromJsonSchema } from 'fluent-wp-client/zod';
const desc = await wp.content('posts').describe();
const createSchema = zodFromJsonSchema(desc.schemas.create!);
const validated = createSchema!.parse({
title: { raw: 'Validated' },
status: 'draft',
});
const created = await wp.content('posts').create(validated);

Bulk runtime validation with zodSchemasFromDescription

Section titled “Bulk runtime validation with zodSchemasFromDescription”

Convert all operation schemas for a resource or ability at once:

import { zodSchemasFromDescription } from 'fluent-wp-client/zod';
const catalog = await wp.explore();
const postSchemas = zodSchemasFromDescription(catalog.content.posts);
const validated = postSchemas.create!.parse({
title: { raw: 'From catalog' },
status: 'draft',
});
await wp.content('posts').create(validated);

For abilities:

import { zodSchemasFromDescription } from 'fluent-wp-client/zod';
const catalog = await wp.explore();
const schemas = zodSchemasFromDescription(catalog.abilities['acme/calculate']);
const input = schemas.input!.parse({ amount: 100, currency: 'USD' });
const result = await wp.ability('acme/calculate').run(input);
Generate schema files
npx fluent-wp-client schemas \
--url https://example.com \
--zod-out src/lib/wp-schemas.ts \
--json-out src/lib/wp-schemas.json
Use the generated validator
import { postsCreateSchema } from '../lib/wp-schemas';
const validatedInput = postsCreateSchema.parse({
title: { raw: 'From generated schema' },
status: 'draft',
});
await wp.content('posts').create(validatedInput);

If you already know the shape ahead of time, you can use the native Zod entrypoint for static schemas:

import { z } from 'zod';
import { postSchema } from 'fluent-wp-client/zod';
const extendedPostSchema = postSchema.extend({
acf: z.object({
acf_subtitle: z.string().optional(),
}).optional(),
});
const post = extendedPostSchema.parse(await wp.content('posts').item('hello-world'));

Any validator that can consume JSON Schema works:

import * as v from 'valibot';
const postValidator = v.object({
id: v.number(),
slug: v.string(),
status: v.string(),
});
const post = v.parse(postValidator, await wp.content('posts').item('hello-world'));
import { defineAction } from 'astro:actions';
import { WordPressClient } from 'fluent-wp-client';
import { postsCreateSchema } from '../lib/wp-schemas';
const wp = new WordPressClient({
baseUrl: import.meta.env.WP_URL,
auth: {
username: import.meta.env.WP_USER,
password: import.meta.env.WP_APP_PASSWORD,
},
});
export const server = {
createPost: defineAction({
input: postsCreateSchema,
handler: async (input) => wp.content('posts').create(input),
}),
};

Use runtime discovery when the AI model should adapt to the connected WordPress instance:

import { generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { WordPressClient } from 'fluent-wp-client';
import { zodFromJsonSchema } from 'fluent-wp-client/zod';
const wp = new WordPressClient({
baseUrl: process.env.WP_URL!,
auth: {
username: process.env.WP_USER!,
password: process.env.WP_APP_PASSWORD!,
},
});
const desc = await wp.content('posts').describe();
const createSchema = zodFromJsonSchema(desc.schemas.create!);
const { object } = await generateObject({
model: openai('gpt-4o-mini'),
schema: createSchema!,
prompt: 'Draft a short changelog post.',
});
await wp.content('posts').create(object);
import { postSchema } from 'fluent-wp-client';
const result = await postSchema['~standard'].validate(payload);
if (result.issues) throw new Error('Validation failed');
const post = result.value;
  • TypeScript92%
  • PHP6%
  • JavaScript2%