SchemaExtension
A feature from another package that reads keys of its own on fields, and on the layout's steps and sections, like affects().
Definition
SchemaExtensionnamestring: names it in messagesfieldPropsAnyObjectSchema: optional, the keys it adds to every field and every display element of the layoutlayoutPropsAnyObjectSchema: optional, the keys it adds to steps and sectionsdefinitionsReadonly<Record<string, AnySchema>>: optional, named schemas its props refer to, fortoJsonSchema()check(ctx: ExtensionContext) => ReadonlyMap<ExtensionTarget, TargetConditions>: checks its keys and gives the conditions of each target
Explanation
See extensions.
ExtensionContext
ExtensionContexttargetsreadonly ExtensionTarget[]: every field, and every step, section and display element of the layout, in document orderresolve(dotPath: string, from: ExtensionTarget) => ResolvedField | string | null: the field a path names, a message when there is none, ornullwhen it has issues of its ownissue(code: DefinitionIssueCode, path: DefinitionPath, message: string) => void: adds an issue
ExtensionTarget
ts
type ExtensionTarget = FieldTarget | LayoutTargetFieldTargetkind'field'fieldWalkedFieldjsonReadonly<Record<string, unknown>>: the field as writtendefinitionPathDefinitionPath
LayoutTargetkind'step' | 'section' | 'display'jsonReadonly<Record<string, unknown>>: the node as writtendefinitionPathDefinitionPathdataPathreadonly (string | number)[]: where the values of the fields around it are
ResolvedField
ResolvedFieldfieldWalkedFieldkindValueKind, andkindDefKindDefschemaAnySchema: the values it accepts, without any conditionitem{ kind: ValueKind; schema: AnySchema } | undefined: for a list whose items have a value
TargetConditions
TargetConditionsreadsreadonly { field: ResolvedField; at: DefinitionPath }[]: the fields they read, and whereevaluate(read: (i: number) => unknown) => { hidden: boolean; clear: boolean }: whether they hide and clear the target, whereread(i)is the input ofreads[i]
Example
ts
const locked: SchemaExtension = {
name: 'locked',
// The key it adds to every field. defineForm() and toJsonSchema() read its type from here.
fieldProps: v.object({ lockedBy: v.optional(v.string()) }),
check(ctx) {
const found = new Map<ExtensionTarget, TargetConditions>()
for (const target of ctx.targets) {
const path = target.json['lockedBy']
if (typeof path !== 'string') continue
const at = [...target.definitionPath, 'lockedBy']
// The field it reads, found the way form rules find theirs.
const field = ctx.resolve(path, target)
if (typeof field === 'string') ctx.issue('unknown_field', at, field)
if (typeof field === 'string' || field === null) continue
found.set(target, {
reads: [{ field, at }],
// read(0) is that field's input, or undefined while it is hidden.
evaluate: (read) => ({ hidden: read(0) === true, clear: false }),
})
}
return found
},
}
const builder = createSchemaBuilder({ extensions: [locked] })