payload
Version:
Node, React and MongoDB Headless CMS and Application Framework
546 lines • 21.1 kB
TypeScript
import type { EditorProps } from '@monaco-editor/react';
import type { TFunction } from 'i18next';
import type { CSSProperties } from 'react';
import type React from 'react';
import type { ConditionalDateProps } from '../../admin/components/elements/DatePicker/types';
import type { Props as ErrorProps } from '../../admin/components/forms/Error/types';
import type { Description } from '../../admin/components/forms/FieldDescription/types';
import type { Props as LabelProps } from '../../admin/components/forms/Label/types';
import type { RowLabel } from '../../admin/components/forms/RowLabel/types';
import type { RichTextAdapter } from '../../admin/components/forms/field-types/RichText/types';
import type { User } from '../../auth';
import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types';
import type { SanitizedConfig } from '../../config/types';
import type { PayloadRequest, RequestContext } from '../../express/types';
import type { SanitizedGlobalConfig } from '../../globals/config/types';
import type { Payload } from '../../payload';
import type { Operation, Where } from '../../types';
export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = {
/** The collection which the field belongs to. If the field belongs to a global, this will be null. */
collection: SanitizedCollectionConfig | null;
context: RequestContext;
/** The data passed to update the document within create and update operations, and the full document itself in the afterRead hook. */
data?: Partial<T>;
/** The field which the hook is running against. */
field: FieldAffectingData;
/** Boolean to denote if this hook is running against finding one, or finding many within the afterRead hook. */
findMany?: boolean;
/** The global which the field belongs to. If the field belongs to a collection, this will be null. */
global: SanitizedGlobalConfig | null;
/** A string relating to which operation the field type is currently executing within. Useful within beforeValidate, beforeChange, and afterChange hooks to differentiate between create and update operations. */
operation?: 'create' | 'delete' | 'read' | 'update';
/** The full original document in `update` operations. In the `afterChange` hook, this is the resulting document of the operation. */
originalDoc?: T;
/** The document before changes were applied, only in `afterChange` hooks. */
previousDoc?: T;
/** The sibling data of the document before changes being applied, only in `beforeChange` and `afterChange` hook. */
previousSiblingDoc?: T;
/** The previous value of the field, before changes, only in `beforeChange` and `afterChange` hooks. */
previousValue?: P;
/** The Express request object. It is mocked for Local API operations. */
req: PayloadRequest;
/** The sibling data passed to a field that the hook is running against. */
siblingData: Partial<S>;
/** The value of the field. */
value?: P;
};
export type FieldHook<T extends TypeWithID = any, P = any, S = any> = (args: FieldHookArgs<T, P, S>) => P | Promise<P>;
export type FieldAccess<T extends TypeWithID = any, P = any, U = any> = (args: {
/**
* The incoming data used to `create` or `update` the document with. `data` is undefined during the `read` operation.
*/
data?: Partial<T>;
/**
* The original data of the document before the `update` is applied. `doc` is undefined during the `create` operation.
*/
doc?: T;
/**
* The `id` of the current document being read or updated. `id` is undefined during the `create` operation.
*/
id?: number | string;
/** The `Express` request object containing the currently authenticated `user` */
req: PayloadRequest<U>;
/**
* Immediately adjacent data to this field. For example, if this is a `group` field, then `siblingData` will be the other fields within the group.
*/
siblingData?: Partial<P>;
}) => Promise<boolean> | boolean;
export type Condition<T extends TypeWithID = any, P = any> = (data: Partial<T>, siblingData: Partial<P>, { user }: {
user: User;
}) => boolean;
export type FilterOptionsProps<T = any> = {
data: T;
id: number | string;
relationTo: string;
siblingData: unknown;
user: Partial<User>;
};
export type FilterOptions<T = any> = ((options: FilterOptionsProps<T>) => Promise<Where | boolean> | Where | boolean) | Where | null;
type Admin = {
className?: string;
components?: {
Cell?: React.ComponentType<any>;
Field?: React.ComponentType<any>;
Filter?: React.ComponentType<any>;
};
/**
* You can programmatically show / hide fields based on what other fields are doing.
* This is also run on the server, to determine if the field should be validated.
*/
condition?: Condition;
description?: Description;
disableBulkEdit?: boolean;
disabled?: boolean;
hidden?: boolean;
position?: 'sidebar';
readOnly?: boolean;
style?: CSSProperties;
width?: string;
};
export type Labels = {
plural: Record<string, string> | string;
singular: Record<string, string> | string;
};
export type ValidateOptions<TData, TSiblingData, TFieldConfig> = {
config: SanitizedConfig;
data: Partial<TData>;
id?: number | string;
operation?: Operation;
payload?: Payload;
req?: PayloadRequest;
siblingData: Partial<TSiblingData>;
t: TFunction;
user?: Partial<User>;
} & TFieldConfig;
export type Validate<TValue = any, TData = any, TSiblingData = any, TFieldConfig = any> = (value: TValue, options: ValidateOptions<TData, TSiblingData, TFieldConfig>) => Promise<string | true> | string | true;
export type OptionObject = {
label: Record<string, string> | string;
value: string;
};
export type Option = OptionObject | string;
export interface FieldBase {
access?: {
create?: FieldAccess;
read?: FieldAccess;
update?: FieldAccess;
};
admin?: Admin;
/** Extension point to add your custom data. */
custom?: Record<string, any>;
defaultValue?: any;
hidden?: boolean;
hooks?: {
afterChange?: FieldHook[];
afterRead?: FieldHook[];
beforeChange?: FieldHook[];
beforeValidate?: FieldHook[];
};
index?: boolean;
label?: Record<string, string> | false | string;
localized?: boolean;
name: string;
required?: boolean;
saveToJWT?: boolean | string;
unique?: boolean;
validate?: Validate;
}
export type NumberField = FieldBase & {
admin?: Admin & {
/** Set this property to a string that will be used for browser autocomplete. */
autoComplete?: string;
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
afterInput?: React.ComponentType<any>[];
beforeInput?: React.ComponentType<any>[];
};
/** Set this property to define a placeholder string for the field. */
placeholder?: Record<string, string> | string;
/** Set a value for the number field to increment / decrement using browser controls. */
step?: number;
};
/** Maximum value accepted. Used in the default `validation` function. */
max?: number;
/** Minimum value accepted. Used in the default `validation` function. */
min?: number;
type: 'number';
} & ({
/** Makes this field an ordered array of numbers instead of just a single number. */
hasMany: true;
/** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */
maxRows?: number;
/** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */
minRows?: number;
} | {
/** Makes this field an ordered array of numbers instead of just a single number. */
hasMany?: false | undefined;
/** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */
maxRows?: undefined;
/** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */
minRows?: undefined;
});
export type TextField = FieldBase & {
admin?: Admin & {
autoComplete?: string;
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
afterInput?: React.ComponentType<any>[];
beforeInput?: React.ComponentType<any>[];
};
placeholder?: Record<string, string> | string;
rtl?: boolean;
};
maxLength?: number;
minLength?: number;
type: 'text';
} & ({
/** Makes this field an ordered array of strings instead of just a single string. */
hasMany: true;
/** Maximum number of strings in the strings array, if `hasMany` is set to true. */
maxRows?: number;
/** Minimum number of strings in the strings array, if `hasMany` is set to true. */
minRows?: number;
} | {
/** Makes this field an ordered array of strings instead of just a single string. */
hasMany?: false | undefined;
/** Maximum number of strings in the strings array, if `hasMany` is set to true. */
maxRows?: undefined;
/** Minimum number of strings in the strings array, if `hasMany` is set to true. */
minRows?: undefined;
});
export type EmailField = FieldBase & {
admin?: Admin & {
autoComplete?: string;
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
afterInput?: React.ComponentType<any>[];
beforeInput?: React.ComponentType<any>[];
};
placeholder?: Record<string, string> | string;
};
type: 'email';
};
export type TextareaField = FieldBase & {
admin?: Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
afterInput?: React.ComponentType<any>[];
beforeInput?: React.ComponentType<any>[];
};
placeholder?: Record<string, string> | string;
rows?: number;
rtl?: boolean;
};
maxLength?: number;
minLength?: number;
type: 'textarea';
};
export type CheckboxField = FieldBase & {
admin?: Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
afterInput?: React.ComponentType<any>[];
beforeInput?: React.ComponentType<any>[];
};
};
type: 'checkbox';
};
export type DateField = FieldBase & {
admin?: Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
afterInput?: React.ComponentType<any>[];
beforeInput?: React.ComponentType<any>[];
};
date?: ConditionalDateProps;
placeholder?: Record<string, string> | string;
};
type: 'date';
};
export type GroupField = Omit<FieldBase, 'required' | 'validation'> & {
admin?: Admin & {
hideGutter?: boolean;
};
fields: Field[];
/** Customize generated GraphQL and Typescript schema names.
* By default it is bound to the collection.
*
* This is useful if you would like to generate a top level type to share amongst collections/fields.
* **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs.
*/
interfaceName?: string;
type: 'group';
};
export type RowAdmin = Omit<Admin, 'description'>;
export type RowField = Omit<FieldBase, 'admin' | 'label' | 'name'> & {
admin?: RowAdmin;
fields: Field[];
type: 'row';
};
export type CollapsibleField = Omit<FieldBase, 'label' | 'name'> & {
admin?: Admin & {
initCollapsed?: boolean | false;
};
fields: Field[];
label: RowLabel;
type: 'collapsible';
};
export type TabsAdmin = Omit<Admin, 'description'>;
type TabBase = Omit<FieldBase, 'required' | 'validation'> & {
description?: Description;
fields: Field[];
interfaceName?: string;
saveToJWT?: boolean | string;
};
export type NamedTab = TabBase & {
/** Customize generated GraphQL and Typescript schema names.
* The slug is used by default.
*
* This is useful if you would like to generate a top level type to share amongst collections/fields.
* **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs.
*/
interfaceName?: string;
};
export type UnnamedTab = Omit<TabBase, 'name'> & {
interfaceName?: never;
label: Record<string, string> | string;
localized?: never;
};
export type Tab = NamedTab | UnnamedTab;
export type TabsField = Omit<FieldBase, 'admin' | 'localized' | 'name' | 'saveToJWT'> & {
admin?: TabsAdmin;
tabs: Tab[];
type: 'tabs';
};
export type TabAsField = Tab & {
name?: string;
type: 'tab';
};
export type UIField = {
admin: {
components?: {
Cell?: React.ComponentType<any>;
Field: React.ComponentType<any>;
Filter?: React.ComponentType<any>;
};
condition?: Condition;
disableBulkEdit?: boolean;
position?: string;
width?: string;
};
/** Extension point to add your custom data. */
custom?: Record<string, any>;
label?: Record<string, string> | string;
name: string;
type: 'ui';
};
export type UploadField = FieldBase & {
admin?: {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
};
};
filterOptions?: FilterOptions;
maxDepth?: number;
relationTo: string;
type: 'upload';
};
type CodeAdmin = Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
};
editorOptions?: EditorProps['options'];
language?: string;
};
export type CodeField = Omit<FieldBase, 'admin'> & {
admin?: CodeAdmin;
maxLength?: number;
minLength?: number;
type: 'code';
};
type JSONAdmin = Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
};
editorOptions?: EditorProps['options'];
};
export type JSONField = Omit<FieldBase, 'admin'> & {
admin?: JSONAdmin;
type: 'json';
};
export type SelectField = FieldBase & {
admin?: Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
};
isClearable?: boolean;
isSortable?: boolean;
};
hasMany?: boolean;
options: Option[];
type: 'select';
};
type SharedRelationshipProperties = FieldBase & {
filterOptions?: FilterOptions;
hasMany?: boolean;
maxDepth?: number;
type: 'relationship';
} & ({
hasMany: true;
/**
* @deprecated Use 'maxRows' instead
*/
max?: number;
maxRows?: number;
/**
* @deprecated Use 'minRows' instead
*/
min?: number;
minRows?: number;
} | {
hasMany?: false | undefined;
/**
* @deprecated Use 'maxRows' instead
*/
max?: undefined;
maxRows?: undefined;
/**
* @deprecated Use 'minRows' instead
*/
min?: undefined;
minRows?: undefined;
});
type RelationshipAdmin = Admin & {
allowCreate?: boolean;
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
};
isSortable?: boolean;
};
export type PolymorphicRelationshipField = SharedRelationshipProperties & {
admin?: RelationshipAdmin & {
sortOptions?: {
[collectionSlug: string]: string;
};
};
relationTo: string[];
};
export type SingleRelationshipField = SharedRelationshipProperties & {
admin?: RelationshipAdmin & {
sortOptions?: string;
};
relationTo: string;
};
export type RelationshipField = PolymorphicRelationshipField | SingleRelationshipField;
export type ValueWithRelation = {
relationTo: string;
value: number | string;
};
export declare function valueIsValueWithRelation(value: unknown): value is ValueWithRelation;
export type RelationshipValue = (number | string)[] | ValueWithRelation | ValueWithRelation[] | (number | string);
export type RichTextField<Value extends object = any, AdapterProps = any, ExtraProperties = {}> = FieldBase & {
admin?: Admin;
editor?: RichTextAdapter<Value, AdapterProps, AdapterProps>;
type: 'richText';
} & ExtraProperties;
export type ArrayField = FieldBase & {
admin?: Admin & {
components?: {
RowLabel?: RowLabel;
} & Admin['components'];
initCollapsed?: boolean | false;
};
fields: Field[];
/** Customize generated GraphQL and Typescript schema names.
* By default it is bound to the collection.
*
* This is useful if you would like to generate a top level type to share amongst collections/fields.
* **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs.
*/
interfaceName?: string;
labels?: Labels;
maxRows?: number;
minRows?: number;
type: 'array';
};
export type RadioField = FieldBase & {
admin?: Admin & {
components?: {
Error?: React.ComponentType<ErrorProps>;
Label?: React.ComponentType<LabelProps>;
};
layout?: 'horizontal' | 'vertical';
};
options: Option[];
type: 'radio';
};
export type Block = {
fields: Field[];
/** @deprecated - please migrate to the interfaceName property instead. */
graphQL?: {
singularName?: string;
};
imageAltText?: string;
imageURL?: string;
/** Customize generated GraphQL and Typescript schema names.
* The slug is used by default.
*
* This is useful if you would like to generate a top level type to share amongst collections/fields.
* **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs.
*/
interfaceName?: string;
labels?: Labels;
slug: string;
/** Extension point to add your custom data. */
custom?: Record<string, any>;
};
export type BlockField = FieldBase & {
admin?: Admin & {
initCollapsed?: boolean | false;
};
blocks: Block[];
defaultValue?: unknown;
labels?: Labels;
maxRows?: number;
minRows?: number;
type: 'blocks';
};
export type PointField = FieldBase & {
type: 'point';
};
export type Field = ArrayField | BlockField | CheckboxField | CodeField | CollapsibleField | DateField | EmailField | GroupField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | RowField | SelectField | TabsField | TextField | TextareaField | UIField | UploadField;
export type FieldAffectingData = ArrayField | BlockField | CheckboxField | CodeField | DateField | EmailField | GroupField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | SelectField | TabAsField | TextField | TextareaField | UploadField;
export type NonPresentationalField = ArrayField | BlockField | CheckboxField | CodeField | CollapsibleField | DateField | EmailField | GroupField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | RowField | SelectField | TabsField | TextField | TextareaField | UploadField;
export type FieldWithPath = Field & {
path?: string;
};
export type FieldWithSubFields = ArrayField | CollapsibleField | GroupField | RowField;
export type FieldPresentationalOnly = UIField;
export type FieldWithMany = RelationshipField | SelectField;
export type FieldWithMaxDepth = RelationshipField | UploadField;
export declare function fieldHasSubFields(field: Field): field is FieldWithSubFields;
export declare function fieldIsArrayType(field: Field): field is ArrayField;
export declare function fieldIsBlockType(field: Field): field is BlockField;
export declare function fieldIsGroupType(field: Field): field is GroupField;
export declare function optionIsObject(option: Option): option is OptionObject;
export declare function optionsAreObjects(options: Option[]): options is OptionObject[];
export declare function optionIsValue(option: Option): option is string;
export declare function fieldSupportsMany(field: Field): field is FieldWithMany;
export declare function fieldHasMaxDepth(field: Field): field is FieldWithMaxDepth;
export declare function fieldIsPresentationalOnly(field: Field | TabAsField): field is UIField;
export declare function fieldAffectsData(field: Field | TabAsField): field is FieldAffectingData;
export declare function tabHasName(tab: Tab): tab is NamedTab;
export declare function fieldIsLocalized(field: Field | Tab): boolean;
export type HookName = 'afterChange' | 'afterRead' | 'beforeChange' | 'beforeRead' | 'beforeValidate';
export {};
//# sourceMappingURL=types.d.ts.map