UNPKG

@league-of-foundry-developers/foundry-vtt-types

Version:
1,245 lines (1,092 loc) 188 kB
import type { RemoveIndexSignatures, SimpleMerge, AnyObject, EmptyObject, NullishProps, InexactPartial, FixedInstanceType, Identity, PrettifyType, InterfaceToObject, AnyArray, } from "#utils"; import type { DataModel } from "../abstract/data.mts"; import type Document from "../abstract/document.mts"; import type { EmbeddedCollection, EmbeddedCollectionDelta, TypeDataModel } from "../abstract/module.d.mts"; import type { DOCUMENT_OWNERSHIP_LEVELS } from "../constants.d.mts"; import type { CONST } from "../../client-esm/client.d.mts"; import type { DataModelValidationFailure } from "./validation-failure.mts"; import type { FormGroupConfig, FormInputConfig, FormSelectOption, MultiSelectInputConfig, SelectInputConfig, TextAreaInputConfig, } from "../../client-esm/applications/forms/fields.d.mts"; export type DataSchema = Record<string, DataField.Any>; /** * An abstract class that defines the base pattern for a data field within a data schema. * @typeParam Options - the options of the DataField instance * @typeParam AssignmentType - the type of the allowed assignment values of the DataField * @typeParam InitializedType - the type of the initialized values of the DataField * @typeParam PersistedType - the type of the persisted values of the DataField * @remarks * Defaults: * - AssignmentType: `unknown | null | undefined` * - InitializedType: `unknown | undefined` * - PersistedType: `unknown | undefined` * - InitialValue: `undefined` */ declare abstract class DataField< const Options extends DataField.Options.Any = DataField.DefaultOptions, const AssignmentType = DataField.AssignmentType<Options>, const InitializedType = DataField.InitializedType<Options>, const PersistedType = InitializedType, > { // Prevent from being bivariant. #assignmentType: AssignmentType; /** * @param options - Options which configure the behavior of the field * @param context - Additional context which describes the field */ // options: not null (unchecked `in` operation), context: not null (destructured) constructor(options?: Options, context?: DataField.ConstructionContext); /** @internal */ " __fvtt_types_internal_source_data": PersistedType; /** @internal */ " __fvtt_types_internal_assignment_data": AssignmentType; /** @internal */ " __fvtt_types_internal_initialized_data": InitializedType; /** The initially provided options which configure the data field */ options: Options; /** * Is this field required to be populated? * @defaultValue `false` */ required: boolean; /** * Can this field have null values? * @defaultValue `false` */ nullable: boolean; /** * Can this field only be modified by a gamemaster or assistant gamemaster? * @defaultValue `false` */ gmOnly: boolean; /** * The initial value of a field, or a function which assigns that initial value. * @defaultValue `undefined` */ initial: DataField.Options.InitialType<InitializedType>; /** * Should the prepared value of the field be read-only, preventing it from being * changed unless a change to the _source data is applied. * @defaultValue `false` */ readonly: boolean; /** * A localizable label displayed on forms which render this field. * @defaultValue `""` */ label: string; /** * Localizable help text displayed on forms which render this field. * @defaultValue `""` */ hint: string; /** * A custom validation error string. When displayed will be prepended with the * document name, field name, and candidate value. This error string is only * used when the return type of the validate function is a boolean. If an Error * is thrown in the validate function, the string message of that Error is used. * @defaultValue `"is not a valid value"` */ validationError: string; /** * The name of this data field within the schema that contains it * * The field name of this DataField instance. * This is assigned by SchemaField#initialize. * @remarks Foundry marked `@internal` */ name: string | undefined; /** * A reference to the parent schema to which this DataField belongs. * This is assigned by SchemaField#initialize. * @remarks Foundry marked `@internal` */ parent: DataField.Any | undefined; /** * Whether this field defines part of a Document/Embedded Document hierarchy. * @defaultValue `false` */ static hierarchical: boolean; /** * Does this field type contain other fields in a recursive structure? * Examples of recursive fields are SchemaField, ArrayField, or TypeDataField * Examples of non-recursive fields are StringField, NumberField, or ObjectField * @defaultValue `false` */ static recursive: boolean; /** * Default parameters for this field type * @remarks This is not entirely type-safe, overrides should specify a more concrete return type. */ protected static get _defaults(): DataField.Options.Any; /** * A dot-separated string representation of the field path within the parent schema. * @remarks Returns `""` if both `this.parent?.fieldPath` and `this.name` are falsey */ get fieldPath(): string; /** * Apply a function to this DataField which propagates through recursively to any contained data schema. * @param fn - The function to apply * @param value - The current value of this field * @param options - Additional options passed to the applied function (default `{}`) * @returns The results object */ // TODO: Determine `value` based upon the field metadata in fields-v2 (while allowing subclasses to narrow allowed values) // options: not null (could be forwarded somewhere destructured, parameter default only) apply<Options, Return>( fn: keyof this | ((this: this, value: unknown, options: Options) => Return), value?: unknown, options?: Options, ): Return; /** * Coerce source data to ensure that it conforms to the correct data type for the field. * Data coercion operations should be simple and synchronous as these are applied whenever a DataModel is constructed. * For one-off cleaning of user-provided input the sanitize method should be used. * @param value - The initial value * @param options - Additional options for how the field is cleaned * @returns The cast value */ // options: not null (parameter default only, property access) clean(value: AssignmentType, options?: DataField.CleanOptions): InitializedType; /** * Apply any cleaning logic specific to this DataField type. * @param value - The appropriately coerced value. * @param options - Additional options for how the field is cleaned. * @returns The cleaned value. * @remarks Simply returns `value` in `DataField`. `options` is unused in `DataField` */ protected _cleanType(value: InitializedType, options?: DataField.CleanOptions | null): InitializedType; /** * Cast a non-default value to ensure it is the correct type for the field * @param value - The provided non-default value * @returns The standardized value */ protected abstract _cast(value: AssignmentType): InitializedType; /** * Attempt to retrieve a valid initial value for the DataField. * @param data - The source data object for which an initial value is required * @returns A valid initial value * @throws An error if there is no valid initial value defined * @remarks The `@throws` is Foundry's, and is wrong, as all fields will at a minimum inherit `initial: undefined` from DataField. * * `data` is unused if the field's `initial` is not a function. */ // TODO: the @throws is omitted in v13, clean up remarks getInitialValue(data?: unknown): InitializedType; /** * Validate a candidate input for this field, ensuring it meets the field requirements. * A validation failure can be provided as a raised Error (with a string message), by returning false, or by returning * a DataModelValidationFailure instance. * A validator which returns true denotes that the result is certainly valid and further validations are unnecessary. * @param value - The initial value * @param options - Options which affect validation behavior * (default: `{}`) * @returns Returns a ModelValidationError if a validation failure occurred */ // options: not null (parameter default only, property access) validate(value: AssignmentType, options?: DataField.ValidateOptions<this>): DataModelValidationFailure | void; /** * Special validation rules which supersede regular field validation. * This validator screens for certain values which are otherwise incompatible with this field like null or undefined. * @param value - The candidate value * @returns A boolean to indicate with certainty whether the value is valid. * Otherwise, return void. * @throws May throw a specific error if the value is not valid */ protected _validateSpecial(value: AssignmentType): boolean | void; /** * A default type-specific validator that can be overridden by child classes * @param value - The candidate value * @param options - Options which affect validation behavior * @returns A boolean to indicate with certainty whether the value is * valid, or specific DataModelValidationFailure information, * otherwise void. * @throws May throw a specific error if the value is not valid */ // options: not null (parameter default only, property access in subclasses) protected _validateType( value: InitializedType, options?: DataField.ValidateOptions<this>, ): boolean | DataModelValidationFailure | void; /** * Certain fields may declare joint data validation criteria. * This method will only be called if the field is designated as recursive. * @param data - Candidate data for joint model validation * @param options - Options which modify joint model validation * @throws An error if joint model validation fails * @remarks Foundry marked `@internal` * * The only place core checks the `options` for any property is in {@link TypeDataField._validateModel | `TypeDataField#_validateModel`}, * where it checks `options.source?.type` * * {@link SchemaField._validateModel | `SchemaField._validateModel`} enforces `source`'s existence for subsidiary calls * * The only place core *calls* this at a top level, it does not pass anything for `options`, relying on SchemaField above * to make TypeDataField work */ protected _validateModel(data: AnyObject, options?: DataField.ValidateModelOptions | null): void; // TODO: Type further. /** * Initialize the original source data into a mutable copy for the DataModel instance. * @param value - The source value of the field * @param model - The DataModel instance that this field belongs to * @param options - Initialization options * @returns An initialized copy of the source data * @remarks Core fields that return a function: * - {@link ForeignDocumentField | `ForeignDocumentField`} * - `ActorDeltaField` (exported in the BaseToken file but not re-exported by the relevant `_module`, so unlinkable) */ // TODO: investigate narrowing return to just `InitializedType` on inheritance lines that don't possibly return one // TODO: (everything except SchemaField and ObjectField and their descendants) // options: not null (parameter default only) initialize( value: PersistedType, model: DataModel.Any, options?: DataField.InitializeOptions, ): InitializedType | (() => InitializedType | null); /** * Export the current value of the field into a serializable object. * @param value - The initialized value of the field * @returns An exported representation of the field */ toObject(value: InitializedType): PersistedType; /** * Recursively traverse a schema and retrieve a field specification by a given path * @param path - The field path as an array of strings */ protected _getField(path: string[]): DataField.Any | undefined; /** * Does this form field class have defined form support? */ static get hasFormSupport(): boolean; /** * Render this DataField as an HTML element. * @param config - Form element configuration parameters * @throws An Error if this DataField subclass does not support input rendering * @returns A rendered HTMLElement for the field */ toInput(config?: DataField.ToInputConfig<InitializedType>): HTMLElement | HTMLCollection; /** * Render this DataField as an HTML element. * Subclasses should implement this method rather than the public toInput method which wraps it. * @param config - Form element configuration parameters * @throws An Error if this DataField subclass does not support input rendering * @returns A rendered HTMLElement for the field */ protected _toInput(config: DataField.ToInputConfig<InitializedType>): HTMLElement | HTMLCollection; /** * Render this DataField as a standardized form-group element. * @param groupConfig - Configuration options passed to the wrapping form-group * @param inputConfig - Input element configuration options passed to DataField#toInput * @returns The rendered form group element */ toFormGroup( groupConfig?: DataField.GroupConfig, inputConfig?: DataField.ToInputConfig<InitializedType>, ): HTMLDivElement; /** * Apply an ActiveEffectChange to this field. * @param value - The field's current value. * @param model - The model instance. * @param change - The change to apply. * @returns The updated value. */ applyChange(value: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData): InitializedType; /** * Cast a change delta into an appropriate type to be applied to this field. * @param delta - The change delta. * @internal */ // Note(LukeAbby): Technically since this defers to `_cast` it should take whatever `_cast` can. // But it always must be able to take a `string` because that's how `applyChange` calls it. protected _castChangeDelta(delta: string): InitializedType; /** * Apply an ADD change to this field. * @param value - The field's current value. * @param delta - The change delta. * @param model - The model instance. * @param change - The original change data. * @returns - The updated value. * * @remarks Returns `value + delta`. `model` and `change` are unused in `DataField` */ protected _applyChangeAdd( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType; /** * Apply a MULTIPLY change to this field. * @param value - The field's current value. * @param delta - The change delta. * @param model - The model instance. * @param change - The original change data. * @returns The updated value. * * @remarks No-op in `DataField`, returns `undefined` unless overridden */ protected _applyChangeMultiply( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType | undefined; /** * Apply an OVERRIDE change to this field. * @param value - The field's current value. * @param delta - The change delta. * @param model - The model instance. * @param change - The original change data. * @returns The updated value. * * @returns Simply returns `delta`. `value`, `model`, and `change` are unused in `DataField` */ protected _applyChangeOverride( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType; /** * Apply an UPGRADE change to this field. * @param value - The field's current value. * @param delta - The change delta. * @param model - The model instance. * @param change - The original change data. * @returns - The updated value. * * @remarks No-op in `DataField`, returns `undefined` unless overridden */ protected _applyChangeUpgrade( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType | undefined; /** * Apply a DOWNGRADE change to this field. * @param value - The field's current value. * @param delta - The change delta. * @param model - The model instance. * @param change - The original change data. * @returns The updated value. * * @remarks No-op in `DataField`, returns `undefined` unless overridden */ protected _applyChangeDowngrade( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType | undefined; /** * Apply a CUSTOM change to this field. * @param value - The field's current value. * @param delta - The change delta. * @param model - The model instance. * @param change - The original change data. * @returns - The updated value. * @remarks Only returns a value if the target value of the change actually changed */ protected _applyChangeCustom( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType | undefined; } declare namespace DataField { /** Any DataField. */ interface Any extends AnyDataField {} interface AnyConstructor extends Identity<typeof AnyDataField> {} /** A DataField with unknown inner types. */ type Unknown = DataField<any, unknown, unknown, unknown>; type AssignmentTypeFor<ConcreteDataField extends Any> = ConcreteDataField extends DataField<any, infer AssignmentType, any, any> ? AssignmentType : never; type InitializedTypeFor<ConcreteDataField extends Any> = ConcreteDataField extends DataField<any, any, infer InitializedType, any> ? InitializedType : never; type PersistedTypeFor<ConcreteDataField extends Any> = ConcreteDataField extends DataField<any, any, any, infer PersistedType> ? PersistedType : never; /** The type of the default options for the {@link DataField | `DataField`} class. */ interface DefaultOptions { required: false; nullable: false; initial: undefined; readonly: false; gmOnly: false; label: ""; hint: ""; validationError: "is not a valid value"; } interface Options<BaseAssignmentType> { /** * Is this field required to be populated? * @defaultValue `false` */ required?: boolean | undefined; /** * Can this field have null values? * @defaultValue `false` */ nullable?: boolean | undefined; /** * Can this field only be modified by a gamemaster or assistant gamemaster? * @defaultValue `false` */ gmOnly?: boolean | undefined; /** The initial value of a field, or a function which assigns that initial value. */ initial?: | DataField.Options.InitialType< // TODO(LukeAbby): Add a `ValidateOptions` type or something of that sort in order to // catch incorrect initial types. DataField.Options.InitialReturnType<BaseAssignmentType, boolean, boolean> > | undefined; /** A data validation function which accepts one argument with the current value. */ validate?: DataField.Validator<DataField.Any, BaseAssignmentType> | undefined; /** A localizable label displayed on forms which render this field. */ label?: string | undefined; /** Localizable help text displayed on forms which render this field. */ hint?: string | undefined; /** * A custom validation error string. When displayed will be prepended with the * document name, field name, and candidate value. This error string is only * used when the return type of the validate function is a boolean. If an Error * is thrown in the validate function, the string message of that Error is used. */ validationError?: string | undefined; } namespace Options { /** Any DataField.Options. */ // Note(LukeAbby): This `& object` is intentional. Its purpose is to allow options like `{ integer: true }` to be assigned. // This is an issue because `{ integer: true }` does not extend `{ required?: boolean }` because they have no properties in common. // Even though `{ integer: true, required: undefined }` would extend `{ required?: boolean }` following the regular rules of surplus properties being allowed. // `object` was chosen over `AnyObject` so that people may pass in interfaces. interface Any extends DataField.Options<any>, Identity<object> {} /** * A helper type for the {@link DataField.Options.initial | `DataField.Options.initial`} option. * @typeParam ReturnType - the return type of the option */ type InitialType<ReturnType> = ReturnType | ((initialData: unknown) => ReturnType); /** * The decorated return type for the {@link DataField.Options.initial | `DataField.Options.initial`} option. * @typeParam BaseAssignmentType - the base assignment type for a DataField * @typeParam NullableOption - the value of the nullable option * @typeParam RequiredOption - the value of the required option */ type InitialReturnType<BaseAssignmentType, NullableOption, RequiredOption> = | Exclude<BaseAssignmentType, null | undefined> | (NullableOption extends true ? null : never) | (RequiredOption extends true ? never : undefined); } /** * A helper type for the given options type merged into the default options of the DataField class. * @typeParam Options - the options that override the default options */ type MergedOptions<Options extends DataField.Options.Any> = SimpleMerge<DefaultOptions, Options>; /** * A type to decorate the base assignment type to a DataField, based on the options of the field. * @typeParam BaseAssignmentType - the base assignment type of the DataField, without null or undefined * @typeParam Options - the options of the DataField */ type DerivedAssignmentType<BaseAssignmentType, Options extends DataField.Options.Any> = | Exclude<BaseAssignmentType, null | undefined> // Always include the base type | (Options["nullable"] extends true // determine whether null is in the union ? // when nullable, null is always allowed null : // otherwise, it depends on required Options["required"] extends true ? // when required and not nullable, null can only be passed when initial is present "initial" extends keyof Options ? // when initial is present, null can be passed null : // when initial is not in the options, then null can not be passed never : // when not required, null can safely be passed null) | (Options["required"] extends true // determine whether undefined is in the union ? // when required, it depends on initial "initial" extends keyof Options ? // when initial is in the options, undefined is allowed undefined : // when initial is not in the options, then undefined is not allowed never : // when not required, undefined can safely be passed undefined); /** * A type to decorate the base initialized type of a DataField, based on the options of the field. * @typeParam BaseInitializedType - the base initialized type of the DataField, without null or undefined * @typeParam Options - the options of the DataField */ type DerivedInitializedType<BaseInitializedType, Options extends DataField.Options.Any> = | Exclude<BaseInitializedType, null | undefined> | (Options["nullable"] extends true ? null : never) | (Options["required"] extends true ? never : undefined); /** * A shorthand for the assignment type of a DataField class. * @typeParam Options - the options overriding the defaults */ type AssignmentType<Options extends DataField.Options.Any> = DerivedAssignmentType<any, MergedOptions<Options>>; /** * A shorthand for the initialized type of a DataField class. * @typeParam Options - the options overriding the defaults */ type InitializedType<Options extends DataField.Options.Any> = DerivedInitializedType<any, MergedOptions<Options>>; /** @internal */ type _ConstructionContext = NullishProps<{ /** A field name to assign to the constructed field */ name?: string; }> & InexactPartial<{ /** * Another data field which is a hierarchical parent of this one * @remarks Can't be `null` as there's a `!== undefined` check in {@link SchemaField._initialize | `SchemaField#_initialize`} */ parent?: DataField.Any; }>; interface ConstructionContext extends _ConstructionContext {} /** @internal */ type _ValidationOptions = NullishProps<{ /** Whether this is a partial schema validation, or a complete one. */ partial: boolean; /** Whether to allow replacing invalid values with valid fallbacks. */ fallback: boolean; /** * If true, invalid embedded documents will emit a warning and be placed in the invalidDocuments * collection rather than causing the parent to be considered invalid. */ dropInvalidEmbedded?: boolean; }> & InexactPartial<{ /** * The full source object being evaluated. * @privateRemarks Disallowing `null` as this value gets passed to provided `initial` functions, * and users shouldn't have to expect `null` */ source: AnyObject; }>; /** * @remarks This is the type for the options for `#validate` and associate methods *without* the * possible inclusion of a `validator` function. * * If you are looking for the type with a generic formerly under this name, see {@link ValidateOptions | `DataField.ValidateOptions`} */ interface ValidationOptions extends _ValidationOptions {} /** * @deprecated Use {@link ValidateOptions | `DataField.ValidationOptions`} instead if you need a direct replacement, * or {@link ValidateOptions | `DataField.ValidateOptions`} if you're typing the options of `#validate` or an associated * method. */ interface DataValidationOptions extends ValidationOptions {} /** @internal */ type _CleanOptions = NullishProps<{ /** Whether to perform partial cleaning? */ partial: boolean; /** The root data model being cleaned */ source: AnyObject; }>; /** An interface for the options of {@link DataField.clean | `DataField#clean`} and {@link DataField._cleanType | `DataField#_cleanType`}. */ interface CleanOptions extends _CleanOptions {} /** * @remarks The only place core checks the `options` for any property is in {@link TypeDataField._validateModel | `TypeDataField#_validateModel`}, * where it checks `options.source?.type` * * {@link SchemaField._validateModel | `SchemaField._validateModel`} enforces `source`'s existence for subsidiary calls * * The only place core *calls* this at a top level, it does not pass anything for `options`, relying on SchemaField above * to make TypeDataField work */ interface ValidateModelOptions extends Pick<ValidationOptions, "source"> {} /** * A Custom DataField validator function. * * A boolean return value indicates that the value is valid (true) or invalid (false) with certainty. With an explicit * boolean return value no further validation functions will be evaluated. * * An undefined return indicates that the value may be valid but further validation functions should be performed, * if defined. * * An Error may be thrown which provides a custom error message explaining the reason the value is invalid. */ type Validator<CurrentField extends DataField.Any, BaseAssignmentType> = | { validate( this: CurrentField, value: unknown, options: ValidateOptions<CurrentField>, ): value is BaseAssignmentType; }["validate"] | { validate( this: CurrentField, value: unknown, options: ValidateOptions<CurrentField>, ): asserts value is BaseAssignmentType; }["validate"] | { validate( this: CurrentField, value: unknown, options: ValidateOptions<CurrentField>, ): DataModelValidationFailure | boolean | void; }["validate"]; /** * An interface for the options of the {@link DataField | `DataField`} validation functions. * @typeParam CurrentField - the type of the DataField, which is the receiver of the validate function */ interface ValidateOptions<CurrentField extends DataField.Any> extends ValidationOptions { /** * @remarks If {@link DataField.validate | `DataField#validate`} is called with a `validate: someFunc` in its `options`, * it will then pass that `options` object on to that function when it calls it, without alteration. * Nothing in core makes use of the fact that a reference to the function is available, this seems incidental. */ validate?: Validator<CurrentField, DataField.AssignmentTypeFor<CurrentField>>; } /** * @remarks The `options` passed to {@link DataField.initialize | `DataField#initialize`} exclusively (in core) come from * {@link DataModel._initialize | `DataModel#_initialize`} or an override (meaning `parent` has been stripped from the * interface), and eventually hits one of: * 1. Document construction, in all cases with `parent` already provided * 2. Gets fed back {@link DataModel._initialize | `DataModel#_initialize`} or an override * 3. {@link Document.get | `Document.get`}, but the one place this happens, `pack` is already provided, and that's the only * option that method cares about. * * This extends the `Document` interface because several core fields use the `pack` property, which isn't available on the * `DataModel` interface */ interface InitializeOptions extends Document.InitializeOptions {} interface ToInputConfig<InitializedType> extends FormInputConfig<InitializedType> {} interface ToInputConfigWithOptions<InitializedType> extends FormInputConfig<InitializedType>, SelectInputConfig {} type AnyChoices = StringField.Choices | NumberField.Choices; type ToInputConfigWithChoices<InitializedType, Choices extends AnyChoices | undefined> = SimpleMerge< Omit<ToInputConfigWithOptions<InitializedType>, "options">, Choices extends undefined ? StringField.GetChoicesOptions : NullishProps<StringField.GetChoicesOptions, "choices"> >; type SelectableToInputConfig<InitializedType, Choices extends StringField.Choices | undefined> = | ToInputConfig<InitializedType> | ToInputConfigWithOptions<InitializedType> | ToInputConfigWithChoices<InitializedType, Choices>; // `DataField#toFormGroup` provides default values for these by way of `??=`. interface GroupConfig extends NullishProps<FormGroupConfig, "label" | "hint" | "input"> {} } declare abstract class AnyDataField extends DataField<any, any, any, any> { constructor(...args: never); } /** * A special class of {@link DataField | `DataField`} which defines a data schema. * @typeParam Fields - the DataSchema fields of the SchemaField * @typeParam Options - the options of the SchemaField instance * @typeParam AssignmentType - the type of the allowed assignment values of the SchemaField * @typeParam InitializedType - the type of the initialized values of the SchemaField * @typeParam PersistedType - the type of the persisted values of the SchemaField * @remarks * Defaults: * - AssignmentType: `SchemaField.AssignmentType<Fields> | null | undefined` * - InitializedType: `SchemaField.InitializedType<Fields>` * - PersistedType: `SchemaField.PersistedType<Fields>` */ declare class SchemaField< Fields extends DataSchema, Options extends SchemaField.Options<Fields> = SchemaField.DefaultOptions, AssignmentType = SchemaField.Internal.AssignmentType<Fields, SimpleMerge<Options, SchemaField.DefaultOptions>>, InitializedType = SchemaField.Internal.InitializedType<Fields, SimpleMerge<Options, SchemaField.DefaultOptions>>, PersistedType extends AnyObject | null | undefined = SchemaField.Internal.PersistedType< Fields, SimpleMerge<Options, SchemaField.DefaultOptions> >, > extends DataField<Options, AssignmentType, InitializedType, PersistedType> { /** * @param fields - The contained field definitions * @param options - Options which configure the behavior of the field * @param context - Additional context which describes the field */ // Saying `fields: Fields` here causes the inference for the fields to be unnecessarily widened. This might effectively be a no-op but it fixes the inference. // options: not null (unchecked `in` operation in super), context: not null (destructured in super) constructor(fields: { [K in keyof Fields]: Fields[K] }, options?: Options, context?: DataField.ConstructionContext); /** @defaultValue `true` */ override required: boolean; /** @defaultValue `false` */ override nullable: boolean; /** @defaultValue `() => this.clean({})` */ override initial: DataField.Options.InitialType<InitializedType>; protected static override get _defaults(): SchemaField.Options<DataSchema>; /** @defaultValue `true` */ static override recursive: boolean; /** * The contained field definitions. */ fields: Fields; /** * Initialize and validate the structure of the provided field definitions. * @param fields - The provided field definitions * @returns The validated schema */ protected _initialize(fields: Fields): Fields; /** * Iterate over a SchemaField by iterating over its fields. */ [Symbol.iterator](): Generator<DataField.Unknown>; // TODO: see if its viable to narrow keys, values, entries, has, and get's types via the schema /** * An array of field names which are present in the schema. */ keys(): string[]; /** * An array of DataField instances which are present in the schema. */ values(): DataField.Unknown[]; /** * An array of [name, DataField] tuples which define the schema. */ entries(): [name: string, dataField: DataField.Unknown][]; /** * Test whether a certain field name belongs to this schema definition. * @param fieldName - The field name * @returns Does the named field exist in this schema? */ has(fieldName: string): boolean; /** * Get a DataField instance from the schema by name * @param fieldName - The field name * @returns The DataField instance or undefined */ get(fieldName: string): DataField.Unknown | undefined; /** * Traverse the schema, obtaining the DataField definition for a particular field. * @param fieldName - A field path like ["abilities", "strength"] or "abilities.strength" * @returns The corresponding DataField definition for that field, or undefined */ getField(fieldName: string | string[]): DataField.Unknown | undefined; protected override _getField(path: string[]): DataField.Any; protected override _cast(value: AssignmentType): InitializedType; /** * @remarks Ensures `options.source` is set via effectively `||= data`, then forwards to each field's `#clean` * * Deletes any keys from `value` not in the schema */ // options: not null (parameter default only, property access) protected override _cleanType(value: InitializedType, options?: DataField.CleanOptions): InitializedType; // options: not null (parameter default only) override initialize( value: PersistedType, model: DataModel.Any, options?: DataField.InitializeOptions, ): InitializedType | (() => InitializedType | null); // options: not null (parameter default only, property access) protected override _validateType( value: InitializedType, options?: DataField.ValidateOptions<this>, ): boolean | DataModelValidationFailure | void; // options: not null (parameter default only, property access) protected override _validateModel(data: AnyObject, options?: DataField.ValidateModelOptions): void; override toObject(value: InitializedType): PersistedType; // options: not null (could be forwarded somewhere destructured, parameter default only) override apply<Options, Return>( fn: keyof this | ((this: this, value: AnyObject, options: Options) => Return), value?: AnyObject, options?: Options, ): Return; /** * Migrate this field's candidate source data. * @param sourceData - Candidate source data of the root model * @param fieldData - The value of this field within the source data */ migrateSource(sourceData: AnyObject, fieldData: unknown): unknown; } // FIXME(LukeAbby): This is a quick patch that avoids issues with the fact that the `initial` in `SchemaField` is not actually assignable to its assignment type etc. // This will be superseded once proper field treatment is applied. declare const __SchemaFieldInitialSymbol: unique symbol; type __SchemaFieldInitial = typeof __SchemaFieldInitialSymbol; declare namespace SchemaField { /** * A shorthand for the options of a SchemaField class. * @typeParam Fields - the DataSchema fields of the SchemaField */ type Options<Fields extends DataSchema> = DataField.Options<AssignmentData<Fields> | __SchemaFieldInitial>; /** Any SchemaField. */ interface Any extends SchemaField<any, any, any, any, any> {} /** * Get the constructor type for the given DataSchema. * @typeParam Fields - the DataSchema fields of the SchemaField */ // Note(LukeAbby): Currently this is identical to the assignment type. The intent is to make this // More accurate in the future, e.g. requiring some requisite properties. type CreateData<Fields extends DataSchema> = AssignmentData<Fields>; /** * Get the inner assignment type for the given DataSchema. * @typeParam Fields - the DataSchema fields of the SchemaField */ type AssignmentData<Fields extends DataSchema> = PrettifyType< RemoveIndexSignatures<{ [Key in keyof Fields]?: Fields[Key] extends EmbeddedDataField<any, any, infer AssignmentType, any, any> ? AssignmentType : Fields[Key] extends SchemaField<infer SubSchema, any, any, any, any> ? // FIXME(LukeAbby): This is a quick hack into AssignmentData that assumes that the `initial` of `SchemaField` is not changed from the default of `{}` // This will be fixed with the refactoring of the types EmptyObject extends AssignmentData<SubSchema> ? AssignmentData<SubSchema> | undefined | null : AssignmentData<SubSchema> : Fields[Key] extends DataField<any, infer AssignType, any, any> ? AssignType : never; }> >; /** * The required type of data used when updating a document. * @typeParam Fields - the DataSchema fields of the SchemaField */ // Note(LukeAbby): Currently this is identical to `AssignmentData` but the intent is to make it // more accurate in the future. type UpdateData<Fields extends DataSchema> = AssignmentData<Fields>; /** * Gets the initialized version of a schema. This means a * @typeParam Fields - the DataSchema fields of the SchemaField */ type InitializedData<Fields extends DataSchema> = PrettifyType< RemoveIndexSignatures<{ [Key in keyof Fields]: Fields[Key] extends EmbeddedDataField<infer Model, any, any, any, any> ? FixedInstanceType<Model> : Fields[Key] extends SchemaField<infer SubSchema, any, any, any, any> ? InitializedData<SubSchema> : Fields[Key] extends DataField<any, any, infer InitType, any> ? InitType : never; }> >; /** * @deprecated {@link SourceData | `SourceData`} */ type PersistedData<Fields extends DataSchema> = SourceData<Fields>; /** * Get the persisted type for the given DataSchema. This is the type used for source. * @typeParam Fields - the DataSchema fields of the SchemaField */ type SourceData<Fields extends DataSchema> = PrettifyType< RemoveIndexSignatures<{ [Key in keyof Fields]: Fields[Key] extends EmbeddedDataField<any, any, any, any, infer PersistType> ? PersistType : Fields[Key] extends SchemaField<infer SubSchema, any, any, any, any> ? SourceData<SubSchema> : Fields[Key] extends DataField<any, any, any, infer PersistType> ? PersistType : never; }> >; type UpdateSourceData<Fields extends DataSchema> = PrettifyType< RemoveIndexSignatures<{ [Key in keyof Fields]: Fields[Key] extends EmbeddedDataField<any, any, any, any, infer PersistType> ? PersistType : Fields[Key] extends SchemaField<infer SubSchema, any, any, any, any> ? SourceData<SubSchema> : Fields[Key] extends DataField<any, any, any, infer PersistType> ? PersistType : never; }> >; /** The type of the default options for the {@link SchemaField | `SchemaField`} class. */ type DefaultOptions = SimpleMerge< DataField.DefaultOptions, { required: true; nullable: false; initial: __SchemaFieldInitial; } >; /** * A helper type for the given options type merged into the default options of the SchemaField class. * @typeParam Fields - the DataSchema fields of the SchemaField * @typeParam Opts - the options that override the default options */ type MergedOptions<Fields extends DataSchema, Opts extends Options<Fields>> = SimpleMerge<DefaultOptions, Opts>; // These exist for calculating the type of schema field with options. // This will be deleted once fields are refactored. // The names are also confusing. Hence these it's put into `Internal. namespace Internal { // FIXME: null or undefined should be permissible, cast as the initialized type /** * A shorthand for the assignment type of a SchemaField class. * @typeParam Fields - the DataSchema fields of the SchemaField * @typeParam Opts - the options that override the default options */ type AssignmentType< Fields extends DataSchema, Opts extends Options<Fields> = DefaultOptions, > = DataField.DerivedAssignmentType<AssignmentData<Fields>, MergedOptions<Fields, Opts>>; /** * A shorthand for the assignment type of a SchemaField class. * @typeParam Fields - the DataSchema fields of the SchemaField * @typeParam Opts - the options that override the default options */ type InitializedType< Fields extends DataSchema, Opts extends Options<Fields> = DefaultOptions, > = DataField.DerivedInitializedType<InitializedData<Fields>, MergedOptions<Fields, Opts>>; /** * A shorthand for the assignment type of a SchemaField class. * @typeParam Fields - the DataSchema fields of the SchemaField * @typeParam Opts - the options that override the default options */ type PersistedType< Fields extends DataSchema, Opts extends Options<Fields> = DefaultOptions, > = DataField.DerivedInitializedType<SourceData<Fields>, MergedOptions<Fields, Opts>>; } /** * This is deprecated because of likely confusion between `SchemaField.AssignmentData` and `SchemaField.AssignmentType`. * @deprecated {@link SchemaField.Internal.AssignmentType | `SchemaField.Internal.AssignmentType`} */ type AssignmentType< Fields extends DataSchema, Opts extends Options<Fields> = DefaultOptions, > = Internal.AssignmentType<Fields, Opts>; /** * This is deprecated because of likely confusion between `SchemaField.InitializedData` and `SchemaField.InitializedType`. * @deprecated {@link SchemaField.Internal.InitializedType | `SchemaField.Internal.InitializedType`} */ type InitializedType< Fields extends DataSchema, Opts extends Options<Fields> = DefaultOptions, > = Internal.InitializedType<Fields, Opts>; /** * This is deprecated because of likely confusion between `SchemaField.PersistedData` and `SchemaField.PersistedType`. * @deprecated {@link SchemaField.Internal.PersistedType | `SchemaField.Internal.PersistedType`} */ type PersistedType<Fields extends DataSchema, Opts extends Options<Fields> = DefaultOptions> = Internal.PersistedType< Fields, Opts >; /** * @deprecated {@link SchemaField.CreateData | `SchemaField.CreateData`} */ type InnerConstructorType<Fields extends DataSchema> = CreateData<Fields>; /** * @deprecated {@link SchemaField.AssignmentData | `SchemaField.AssignmentData`} */ type InnerAssignmentType<Fields extends DataSchema> = AssignmentData<Fields>; /** * @deprecated {@link SchemaField.InitializedData | `SchemaField.InitializedData`} */ type InnerInitializedType<Fields extends DataSchema> = InitializedData<Fields>; /** * @deprecated {@link SchemaField.UpdateData | `SchemaField.UpdateData`} */ type InnerUpdateData<Fields extends DataSchema> = UpdateData<Fields>; /** * @deprecated {@link SchemaField.SourceData | `SchemaField.SourceData`} */ type InnerPersistedType<Fields extends DataSchema> = SourceData<Fields>; } /** * A subclass of {@link DataField | `DataField`} which deals with boolean-typed data. * @typeParam Options - the options of the BooleanField instance * @typeParam AssignmentType - the type of the allowed assignment values of the BooleanField * @typeParam InitializedType - the type of the initialized values of the BooleanField * @typeParam PersistedType - the type of the persisted values of the BooleanField * @remarks * Defaults: * - AssignmentType: `boolean | null | undefined` * - InitializedType: `boolean` * - PersistedType: `boolean` * - InitialValue: `false` */ declare class BooleanField< const Options extends BooleanField.Options = BooleanField.DefaultOptions, const AssignmentType = BooleanField.AssignmentType<SimpleMerge<Options, BooleanField.DefaultOptions>>, const InitializedType = BooleanField.InitializedType<SimpleMerge<Options, BooleanField.DefaultOptions>>, const PersistedType extends boolean | null | undefined = BooleanField.InitializedType< SimpleMerge<Options, BooleanField.DefaultOptions> >, > extends DataField<Options, AssignmentType, InitializedType, PersistedType> { /** @defaultValue `true` */ override required: boolean; /** @defaultValue `false` */ override nullable: boolean; /** @defaultValue `false` */ override initial: DataField.Options.InitialType<InitializedType>; protected static override get _defaults(): BooleanField.Options; protected override _cast(value: AssignmentType): InitializedType; /** @remarks `options` is unused in `BooleanField` */ protected override _validateType( value: InitializedType, options?: DataField.ValidateOptions<this> | null, ): boolean | DataModelValidationFailure | void; protected override _toInput(config: DataField.ToInputConfig<InitializedType>): HTMLElement | HTMLCollection; /** @remarks Returns `value || delta`. `model` and `change` are unused in `BooleanField` */ protected override _applyChangeAdd( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType; /** @remarks Returns `value && delta`. `model` and `change` are unused in `BooleanField` */ protected override _applyChangeMultiply( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType; /** @remarks Returns `delta > value ? delta : value`. `model` and `change` are unused in `BooleanField` */ protected override _applyChangeUpgrade( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType; /** @remarks Returns `delta < value ? delta : value`. `model` and `change` are unused in `BooleanField` */ protected override _applyChangeDowngrade( value: InitializedType, delta: InitializedType, model: DataModel.Any, change: ActiveEffect.EffectChangeData, ): InitializedType; } declare namespace BooleanField { /** A shorthand for the options of a BooleanField class. */ type Options = DataField.Options<boolean>; /** The type of the default options for the {@link BooleanField | `BooleanField`} class. */ type DefaultOptions = SimpleMerge< DataField.DefaultOptions, { required: true; nullable: false; initial: boolean; } >; /** * A helper type for the given options type merged into the default options of the BooleanField class. * @typeParam Opts - the options that override the default options */ type MergedOptions<Opts extends Options> = SimpleMerge<DefaultOptions, Opts>; /** * A shorthand for the assignment type of a BooleanField class. * @typeParam Opts - the options that override the default options */ type AssignmentType<Opts extends Options> = DataField.DerivedAssignmentType<boolean, MergedOptions<Opts>>; /** * A shorthand for the initialized type of a BooleanField class. * @typeParam Opts - the options that override the default options */ type InitializedType<Opts extends Options> = DataField.DerivedInitializedType<boolean, MergedOptions<Opts>>; } /** * A subclass of {@link DataField | `DataField`} which deals with number-typed data. * @typeParam Options - the options of the NumberField instance * @typeParam AssignmentType - the type of the allowed assignment values of the NumberField * @type