Views

A view is a schema class created from an entity:

/** What an author may write. */
export class PostDraft extends Post.pick('slug', 'title', 'summary', 'body') {}

/** What the public index shows — no body. */
export class PostCard extends Post.pick('id', 'slug', 'title', 'summary', 'publishedAt') {}

/** Input of a custom read operation. */
export class BySlugInput extends Post.pick('slug') {}

A view is a full schema class: it has getFields(), validate(), and is usable as a TypeScript type. Views chain: Post.pick(…).partial().

The four derivations

DerivationProduces
Post.pick('a', 'b')only those fields
Post.omit('a')all fields but those
Post.partial()every field optional: an absent field is not updated
Post.extend({ extra: text() })entity plus new fields (how User extends AuthUser)

The partial mode is retained when the view is used as an operation input.

Where views plug in

  • Handler inputs — declare the view as the parameter type; the façade validates the wire body against it before your code runs (Handlers).
  • Handler outputsCrud(Post, { list: PostCard }) names one op's view; Crud(Post, PostPublic) scopes the whole handler (Handlers).
  • FormsuseFormFor(PostDraft) derives its fields from the view (Forms).

The io projections

The boundary axis derives two field sets used by every surface:

inputFields(Post.getFields())    // fields a client may WRITE  — readOnly excluded
outputFields(Post.getFields())   // fields a client may READ   — writeOnly excluded

This is why a form built on Post does not show status or publishedAt inputs, without additional per-form configuration.

Choosing between a field and a view

readOnly / writeOnly and pick / omit can all remove a field from a surface, but their scope differs.

  • boundary (on the field) defines a global rule. With writeOnly(password), the password is excluded from every output.
  • pick / omit (on a view) selects fields for a specific use. For example, Post.pick('id', 'title') defines the public index response.

The two mechanisms are complementary.

  • Without writeOnly on the field, every output view would need to omit password. The global rule prevents that omission.
  • A public response (id, title) and an admin response (+ authorEmail) instead need different views: authorEmail is included or excluded depending on the use.

Choose based on the rule's scope: global or specific to one use.

The fact is…It lives…Example
true everywhere (invariant)on the field — readOnly / writeOnlya password never leaves
true for one use (local)in a derivation — pick / omitthis endpoint returns only id + title

A boundary rule is serialized in the card under x-fougere.boundary, so a consumer in another language can apply it. A view derived in TypeScript is not serialized.

Next: The identity card — the schema's portable form.

Built with Fougere — this site runs on the framework it documents.