Registry System
How defineRegistry works, and why it's consumer-owned rather than global.
defineRegistry
function defineRegistry<const TRegistry extends FieldRegistry>(
entries: TRegistry,
): Readonly<TRegistry>;A registry maps a field-type name to the field component that renders it:
import { defineRegistry } from '@prismrepo/forms';
import { TextField } from './text-field';
import { NumberField } from './number-field';
export const registry = defineRegistry({
text: TextField,
number: NumberField,
});defineRegistry is a plain identity function: it returns the same value you passed in, as
Readonly, with no module-level registration side effect. There's no global registry anywhere
in Prism to import from, you create your own and pass it where it's needed.
Why consumer-owned, not global
Two registries created from two separate defineRegistry calls are fully independent, they
never share configuration, and a const TRegistry built from one is never interchangeable
with one from the other, even if they happen to declare the same key names. This matters for:
- Multiple apps or test suites in one process never observing each other's field configuration through shared module state.
- Compile-time type safety.
const TRegistry extends FieldRegistrypreserves each registered field-type name as its own literal string type, not widened tostring, which is what letscreateFormBuilderreject invalid or typo'd field-type names at compile time.
How a registered type gets resolved
resolveFieldComponent(registry, type) resolves a configured field type to its component at
the point of use, never via a static import. <PrismField> calls this internally. If type
isn't a key in registry, it throws PrismConfigurationError naming the field and the
registry's known types, rather than silently rendering nothing, this is the runtime half of a
check the type system already makes a compile-time error for literal configuration (relevant
when a field's type came from data the type checker couldn't see, for example parsed JSON).
Extending a registry as your app grows
A registry is just an object literal. Add a new field type by adding a new key:
export const registry = defineRegistry({
text: TextField,
number: NumberField,
rating: RatingField, // a custom, consumer-authored field component
});There is no distinction the type system enforces between a field component Prism's CLI installed and one you wrote yourself, see Custom Fields.