UNPKG

fvtt-types

Version:
630 lines (519 loc) 25.4 kB
import type { ConfiguredMacro } from "#configuration"; import type { Identity, InexactPartial, Merge, NullishProps } from "#utils"; import type { documents } from "#client/client.d.mts"; import type Document from "#common/abstract/document.d.mts"; import type { DataSchema } from "#common/data/fields.d.mts"; import type BaseMacro from "#common/documents/macro.d.mts"; import type { Token } from "#client/canvas/placeables/_module.d.mts"; import fields = foundry.data.fields; declare namespace Macro { /** * The document's name. */ type Name = "Macro"; /** * The context used to create a `Macro`. */ interface ConstructionContext extends Document.ConstructionContext<Parent> {} /** * The documents embedded within `Macro`. */ type Hierarchy = Readonly<Document.HierarchyOf<Schema>>; /** * The implementation of the `Macro` document instance configured through `CONFIG.Macro.documentClass` in Foundry and * {@linkcode DocumentClassConfig} or {@link ConfiguredMacro | `fvtt-types/configuration/ConfiguredMacro`} in fvtt-types. */ type Implementation = Document.ImplementationFor<Name>; /** * The implementation of the `Macro` document configured through `CONFIG.Macro.documentClass` in Foundry and * {@linkcode DocumentClassConfig} in fvtt-types. */ type ImplementationClass = Document.ImplementationClassFor<Name>; /** * A document's metadata is special information about the document ranging anywhere from its name, * whether it's indexed, or to the permissions a user has over it. */ interface Metadata extends Merge< Document.Metadata.Default, Readonly<{ name: "Macro"; collection: "macros"; indexed: true; compendiumIndexFields: ["_id", "name", "img", "sort", "folder"]; label: string; labelPlural: string; coreTypes: ["script", "chat"]; // This isn't `CONST.MACRO_TYPES[]` due to the semantics of `Merge`. permissions: Metadata.Permissions; schemaVersion: string; }> > {} namespace Metadata { /** * The permissions for whether a certain user can create, update, or delete this document. */ interface Permissions { create(user: User.Internal.Implementation, doc: Implementation): boolean; update(user: User.Internal.Implementation, doc: Implementation): boolean; delete: "OWNER"; } } /** * The subtypes of `Macro` that Foundry provides. `Macro` does not have `system` and therefore * there is no way for a user to configure custom subtypes. Nevertheless Foundry has a number of * built in subtypes usable for `Macro`. * * `Macro` has two subtypes `"chat"` and `"script"`. A `Macro` with type `"chat"` will create a * `ChatMessage` whereas a `"script"` allows executing arbitrary JavaScript code */ type SubType = foundry.Game.Model.TypeNames<Name>; /** * @deprecated `Macro` does not have `system` and therefore there is no way for a user to * configure custom subtypes. * * This type exists only to be informative. */ type ConfiguredSubType = never; /** * @deprecated `Macro` does not have `system` and therefore there is no way for a user to * configure custom subtypes. This means `Known` as a concept does not apply to it. * * This type exists only to be informative. */ type Known = never; /** * `OfType` returns an instance of `Macro` with the corresponding type. This works with both the * builtin `Macro` class or a custom subclass if that is set up in * {@link ConfiguredMacro | `fvtt-types/configuration/ConfiguredMacro`}. * * Note that `Macro` does not have a `system` property and therefore there is no way for a user * to configure custom subtypes. See {@linkcode Macro.SubType} for more information. */ // Note(LukeAbby): The lack of a `system` is why `Document.Internal.DiscriminateSystem` isn't applied. type OfType<Type extends SubType> = _OfType[Type]; /** @internal */ interface _OfType extends Identity<{ [Type in SubType]: Type extends unknown ? ConfiguredMacro<Type> extends { document: infer Document } ? Document : // eslint-disable-next-line @typescript-eslint/no-restricted-types Macro<Type> : never; }> {} /** * A document's parent is something that can contain it. * For example an `Item` can be contained by an `Actor` which makes `Actor` one of its possible parents. */ type Parent = null; /** * A document's descendants are any child documents, grandchild documents, etc. * This is a union of all instances, or never if the document doesn't have any descendants. */ type Descendant = never; /** * A document's descendants are any child documents, grandchild documents, etc. * This is a union of all classes, or never if the document doesn't have any descendants. */ type DescendantClass = never; /** * Types of `CompendiumCollection` this document might be contained in. * Note that `this.pack` will always return a string; this is the type for `game.packs.get(this.pack)` * * Will be `never` if cannot be contained in a `CompendiumCollection`. */ // Note: Takes any document in the heritage chain (i.e. itself or any parent, transitive or not) that can be contained in a compendium. type Pack = foundry.documents.collections.CompendiumCollection.ForDocument<"Scene">; /** * An embedded document is a document contained in another. * For example an `Item` can be contained by an `Actor` which means `Item` can be embedded in `Actor`. * * If this is `never` it is because there are no embeddable documents (or there's a bug!). */ type Embedded = never; /** * The name of the world or embedded collection this document can find itself in. * For example an `Item` is always going to be inside a collection with a key of `items`. * This is a fixed string per document type and is primarily useful for {@link ClientDocumentMixin | `Descendant Document Events`}. */ type ParentCollectionName = Metadata["collection"]; /** * The world collection that contains `Macro`s. Will be `never` if none exists. */ type CollectionClass = foundry.documents.collections.Macros.ImplementationClass; /** * The world collection that contains `Folder`s. Will be `never` if none exists. */ type Collection = foundry.documents.collections.Macros.Implementation; /** * An instance of `Macro` that comes from the database but failed validation meaning that * its `system` and `_source` could theoretically be anything. */ type Invalid = Document.Internal.Invalid<OfType<SubType>>; /** * An instance of `Macro` that comes from the database. */ type Stored<SubType extends Macro.SubType = Macro.SubType> = Document.Internal.Stored<OfType<SubType>>; /** * The data put in {@link Macro._source | `Macro#_source`}. This data is what was * persisted to the database and therefore it must be valid JSON. * * For example a {@link fields.SetField | `SetField`} is persisted to the database as an array * but initialized as a {@linkcode Set}. */ interface Source extends fields.SchemaField.SourceData<Schema> {} /** * The data necessary to create a document. Used in places like {@linkcode Macro.create} * and {@link Macro | `new Macro(...)`}. * * For example a {@link fields.SetField | `SetField`} can accept any {@linkcode Iterable} * with the right values. This means you can pass a `Set` instance, an array of values, * a generator, or any other iterable. */ interface CreateData extends fields.SchemaField.CreateData<Schema> {} /** * The data after a {@link foundry.abstract.Document | `Document`} has been initialized, for example * {@link Macro.name | `Macro#name`}. * * This is data transformed from {@linkcode Macro.Source} and turned into more * convenient runtime data structures. For example a {@link fields.SetField | `SetField`} is * persisted to the database as an array of values but at runtime it is a `Set` instance. */ interface InitializedData extends fields.SchemaField.InitializedData<Schema> {} /** * The data used to update a document, for example {@link Macro.update | `Macro#update`}. * It is a distinct type from {@link Macro.CreateData | `DeepPartial<Macro.CreateData>`} because * it has different rules for `null` and `undefined`. */ interface UpdateData extends fields.SchemaField.UpdateData<Schema> {} /** * The schema for {@linkcode Macro}. This is the source of truth for how an Macro document * must be structured. * * Foundry uses this schema to validate the structure of the {@linkcode Macro}. For example * a {@link fields.StringField | `StringField`} will enforce that the value is a string. More * complex fields like {@link fields.SetField | `SetField`} goes through various conversions * starting as an array in the database, initialized as a set, and allows updates with any * iterable. */ interface Schema extends DataSchema { /** * The _id which uniquely identifies this Macro document * @defaultValue `null` */ _id: fields.DocumentIdField; /** * The name of this Macro * @defaultValue `""` */ name: fields.StringField<{ required: true; blank: false; textSearch: true }>; /** * A Macro subtype from CONST.MACRO_TYPES * @defaultValue `CONST.MACRO_TYPES.CHAT` */ type: fields.DocumentTypeField<typeof BaseMacro, { initial: typeof CONST.MACRO_TYPES.CHAT }>; /** * The _id of a User document which created this Macro * * @defaultValue `game.user?.id` */ author: fields.DocumentAuthorField<typeof documents.BaseUser>; /** * An image file path which provides the thumbnail artwork for this Macro * @defaultValue `BaseMacro.DEFAULT_ICON` */ img: fields.FilePathField<{ categories: ["IMAGE"]; initial: () => typeof BaseMacro.DEFAULT_ICON; }>; /** * The scope of this Macro application from CONST.MACRO_SCOPES * @defaultValue `"global"` * @privateRemarks This field (and `CONST.MACRO_SCOPES`) is entirely vestigial, it's never checked anywhere, * and its `<select>` in MacroConfig has been unconditionally disabled since at least 11.315 */ scope: fields.StringField<{ required: true; choices: CONST.MACRO_SCOPES[]; initial: (typeof CONST.MACRO_SCOPES)[0]; validationError: "must be a value in CONST.MACRO_SCOPES"; }>; /** * The string content of the macro command * @defaultValue `""` */ command: fields.StringField<{ required: true; blank: true; }>; /** * The _id of a Folder which contains this Macro * @defaultValue `null` */ folder: fields.ForeignDocumentField<typeof documents.BaseFolder>; /** * The numeric sort value which orders this Macro relative to its siblings * @defaultValue `0` */ sort: fields.IntegerSortField; /** * An object which configures ownership of this Macro * @defaultValue see {@linkcode fields.DocumentOwnershipField} */ ownership: fields.DocumentOwnershipField; /** * An object of optional key/value flags * @defaultValue `{}` */ flags: fields.DocumentFlagsField<Name>; /** * An object of creation and access information * @defaultValue see {@linkcode fields.DocumentStatsField} */ _stats: fields.DocumentStatsField; } namespace Database { /** Options passed along in Get operations for Macros */ interface Get extends foundry.abstract.types.DatabaseGetOperation<Macro.Parent> {} /** Options passed along in Create operations for Macros */ interface Create<Temporary extends boolean | undefined = boolean | undefined> extends foundry.abstract.types.DatabaseCreateOperation<Macro.CreateData, Macro.Parent, Temporary> {} /** Options passed along in Delete operations for Macros */ interface Delete extends foundry.abstract.types.DatabaseDeleteOperation<Macro.Parent> {} /** Options passed along in Update operations for Macros */ interface Update extends foundry.abstract.types.DatabaseUpdateOperation<Macro.UpdateData, Macro.Parent> {} /** Operation for {@linkcode Macro.createDocuments} */ interface CreateDocumentsOperation<Temporary extends boolean | undefined> extends Document.Database.CreateOperation<Macro.Database.Create<Temporary>> {} /** Operation for {@linkcode Macro.updateDocuments} */ interface UpdateDocumentsOperation extends Document.Database.UpdateDocumentsOperation<Macro.Database.Update> {} /** Operation for {@linkcode Macro.deleteDocuments} */ interface DeleteDocumentsOperation extends Document.Database.DeleteDocumentsOperation<Macro.Database.Delete> {} /** Operation for {@linkcode Macro.create} */ interface CreateOperation<Temporary extends boolean | undefined> extends Document.Database.CreateOperation<Macro.Database.Create<Temporary>> {} /** Operation for {@link Macro.update | `Macro#update`} */ interface UpdateOperation extends Document.Database.UpdateOperation<Update> {} interface DeleteOperation extends Document.Database.DeleteOperation<Delete> {} /** Options for {@linkcode Macro.get} */ interface GetOptions extends Document.Database.GetOptions {} /** Options for {@link Macro._preCreate | `Macro#_preCreate`} */ interface PreCreateOptions extends Document.Database.PreCreateOptions<Create> {} /** Options for {@link Macro._onCreate | `Macro#_onCreate`} */ interface OnCreateOptions extends Document.Database.CreateOptions<Create> {} /** Operation for {@linkcode Macro._preCreateOperation} */ interface PreCreateOperation extends Document.Database.PreCreateOperationStatic<Macro.Database.Create> {} /** Operation for {@link Macro._onCreateOperation | `Macro#_onCreateOperation`} */ interface OnCreateOperation extends Macro.Database.Create {} /** Options for {@link Macro._preUpdate | `Macro#_preUpdate`} */ interface PreUpdateOptions extends Document.Database.PreUpdateOptions<Update> {} /** Options for {@link Macro._onUpdate | `Macro#_onUpdate`} */ interface OnUpdateOptions extends Document.Database.UpdateOptions<Update> {} /** Operation for {@linkcode Macro._preUpdateOperation} */ interface PreUpdateOperation extends Macro.Database.Update {} /** Operation for {@link Macro._onUpdateOperation | `Macro._preUpdateOperation`} */ interface OnUpdateOperation extends Macro.Database.Update {} /** Options for {@link Macro._preDelete | `Macro#_preDelete`} */ interface PreDeleteOptions extends Document.Database.PreDeleteOperationInstance<Delete> {} /** Options for {@link Macro._onDelete | `Macro#_onDelete`} */ interface OnDeleteOptions extends Document.Database.DeleteOptions<Delete> {} /** Options for {@link Macro._preDeleteOperation | `Macro#_preDeleteOperation`} */ interface PreDeleteOperation extends Macro.Database.Delete {} /** Options for {@link Macro._onDeleteOperation | `Macro#_onDeleteOperation`} */ interface OnDeleteOperation extends Macro.Database.Delete {} /** Context for {@linkcode Macro._onDeleteOperation} */ interface OnDeleteDocumentsContext extends Document.ModificationContext<Macro.Parent> {} /** Context for {@linkcode Macro._onCreateDocuments} */ interface OnCreateDocumentsContext extends Document.ModificationContext<Macro.Parent> {} /** Context for {@linkcode Macro._onUpdateDocuments} */ interface OnUpdateDocumentsContext extends Document.ModificationContext<Macro.Parent> {} /** * Options for {@link Macro._preCreateDescendantDocuments | `Macro#_preCreateDescendantDocuments`} * and {@link Macro._onCreateDescendantDocuments | `Macro#_onCreateDescendantDocuments`} */ interface CreateOptions extends Document.Database.CreateOptions<Macro.Database.Create> {} /** * Options for {@link Macro._preUpdateDescendantDocuments | `Macro#_preUpdateDescendantDocuments`} * and {@link Macro._onUpdateDescendantDocuments | `Macro#_onUpdateDescendantDocuments`} */ interface UpdateOptions extends Document.Database.UpdateOptions<Macro.Database.Update> {} /** * Options for {@link Macro._preDeleteDescendantDocuments | `Macro#_preDeleteDescendantDocuments`} * and {@link Macro._onDeleteDescendantDocuments | `Macro#_onDeleteDescendantDocuments`} */ interface DeleteOptions extends Document.Database.DeleteOptions<Macro.Database.Delete> {} /** * Create options for {@linkcode Macro.createDialog}. */ interface DialogCreateOptions extends InexactPartial<Create> {} } /** * If `Temporary` is true then `Macro.Implementation`, otherwise `Macro.Stored`. */ type TemporaryIf<Temporary extends boolean | undefined> = true extends Temporary ? Macro.Implementation : Macro.Stored; /** * The flags that are available for this document in the form `{ [scope: string]: { [key: string]: unknown } }`. */ interface Flags extends Document.Internal.ConfiguredFlagsForName<Name> {} namespace Flags { /** * The valid scopes for the flags on this document e.g. `"core"` or `"dnd5e"`. */ type Scope = Document.Internal.FlagKeyOf<Flags>; /** * The valid keys for a certain scope for example if the scope is "core" then a valid key may be `"sheetLock"` or `"viewMode"`. */ type Key<Scope extends Flags.Scope> = Document.Internal.FlagKeyOf<Document.Internal.FlagGetKey<Flags, Scope>>; /** * Gets the type of a particular flag given a `Scope` and a `Key`. */ type Get<Scope extends Flags.Scope, Key extends Flags.Key<Scope>> = Document.Internal.GetFlag<Flags, Scope, Key>; } interface DropData extends Document.Internal.DropData<Name> {} interface DropDataOptions extends Document.DropDataOptions {} interface DefaultNameContext extends Document.DefaultNameContext<Name, Parent> {} interface CreateDialogData extends Document.CreateDialogData<CreateData> {} interface CreateDialogOptions extends Document.CreateDialogOptions<Name> {} /** @internal */ type _ScriptScope = NullishProps<{ /** An Actor who is the protagonist of the executed action. */ actor: Actor.Implementation; /** A Token which is the protagonist of the executed action. */ token: Token.Implementation; /** The speaker data */ speaker: ChatMessage.SpeakerData; /** * @remarks Sometimes provided by core: * - When called in {@link foundry.data.regionBehaviors.ExecuteMacroRegionBehaviorType._handleRegionEvent | `ExecuteMacroRegionBehaviorType#_handleRegionEvent`}, * will be a {@linkcode Scene.Implementation} (possibly `null` if somehow called on a `RegionBehavior` whose `RegionDocument` doesn't have a parent `Scene`) */ scene?: unknown; /** * @remarks Sometimes provided by core: * - When called in {@link foundry.data.regionBehaviors.ExecuteMacroRegionBehaviorType._handleRegionEvent | `ExecuteMacroRegionBehaviorType#_handleRegionEvent`}, * will be a {@linkcode RegionDocument.Implementation} (possibly `null` if somehow called on a `RegionBehavior` without a parent `RegionDocument`) */ region?: unknown; /** * @remarks Sometimes provided by core: * - When called in {@link foundry.data.regionBehaviors.ExecuteMacroRegionBehaviorType._handleRegionEvent | `ExecuteMacroRegionBehaviorType#_handleRegionEvent`}, * will be a {@linkcode RegionBehavior.Implementation} (possibly `null` if somehow called on a `RegionBehaviorType` without a parent `RegionBehavior`) */ behavior?: unknown; /** * @remarks Sometimes provided by core: * - When called in {@link Macro._onClickDocumentLink | `Macro#_onClickDocumentLink`}, * will be a {@linkcode MouseEvent} * - When called in {@link foundry.data.regionBehaviors.ExecuteMacroRegionBehaviorType._handleRegionEvent | `ExecuteMacroRegionBehaviorType#_handleRegionEvent`}, * will be a {@linkcode RegionDocument.RegionEvent} */ event?: unknown; /** * @remarks Additional arguments passed as part of the scope. Numeric keys are disallowed (`##executeScript` throws). */ [arg: string | symbol]: unknown; }>; interface ScriptScope extends _ScriptScope {} interface ChatScope extends Pick<ScriptScope, "speaker"> {} interface UnknownScope extends ScriptScope, ChatScope {} type ExecuteScope<SubType extends Macro.SubType> = SubType extends "chat" | "script" ? UnknownScope : (SubType extends "script" ? ScriptScope : never) | (SubType extends "chat" ? ScriptScope : never); // Note: If extra types ever get added this will need to be updated to account for them, even if // just to return `undefined`. type ExecuteReturn<SubType extends Macro.SubType> = | (SubType extends "chat" ? Promise<ChatMessage.Implementation | undefined | void> : never) // Note(LukeAbby): As of 13.346 this `| void` is only possible if there's a syntax error in the function. | (SubType extends "script" ? Promise<unknown> | void : never); /** * The arguments to construct the document. * * @deprecated Writing the signature directly has helped reduce circularities and therefore is * now recommended. */ // eslint-disable-next-line @typescript-eslint/no-deprecated type ConstructorArgs = Document.ConstructorParameters<CreateData, Parent>; /** * @deprecated Replaced with {@linkcode Macro.ConfiguredSubType} (will be removed in v14). */ // eslint-disable-next-line @typescript-eslint/no-deprecated type ConfiguredSubTypes = ConfiguredSubType; } /** * The client-side Macro document which extends the common BaseMacro model. * * @see {@linkcode Macros} The world-level collection of Macro documents * @see {@linkcode MacroConfig} The Macro configuration application * * @param data - Initial data provided to construct the Macro document */ declare class Macro<out SubType extends Macro.SubType = Macro.SubType> extends BaseMacro.Internal .ClientDocument<SubType> { /** * @param data - Initial data from which to construct the `Macro` * @param context - Construction context options */ constructor(data: Macro.CreateData, context?: Macro.ConstructionContext); /** * Is the current User the author of this macro? */ get isAuthor(): boolean; /** * Test whether the current user is capable of executing a Macro script */ get canExecute(): boolean; /** * Provide a thumbnail image path used to represent this document. */ get thumbnail(): string | null; /** * Test whether the given User is capable of executing this Macro. * @param user - The User to test. * @returns Can this User execute this Macro? */ canUserExecute(user: User.Implementation): boolean; /** * Execute the Macro command. * @param scope - Macro execution scope which is passed to script macros * @returns A promise containing a created {@linkcode ChatMessage} (or `undefined`) if a chat * macro or the return value if a script macro. A void return is possible if the user * is not permitted to execute macros or a script macro execution fails. * @remarks Forwards to either `#executeChat` or `#executeScript` */ execute(scope?: Macro.ExecuteScope<SubType>): Macro.ExecuteReturn<SubType>; /** @remarks Returns `this.execute({event})` */ override _onClickDocumentLink(event: MouseEvent): Macro.ExecuteReturn<SubType>; // _onCreate is overridden but with no signature changes from its definition in BaseMacro. /* * After this point these are not really overridden methods. * They are here because Foundry's documents are complex and have lots of edge cases. * There are DRY ways of representing this but this ends up being harder to understand * for end users extending these functions, especially for static methods. There are also a * number of methods that don't make sense to call directly on `Document` like `createDocuments`, * as there is no data that can safely construct every possible document. Finally keeping definitions * separate like this helps against circularities. */ // ClientDocument overrides // Descendant Document operations have been left out because Macro does not have any descendant documents. static override defaultName(context?: Macro.DefaultNameContext): string; static override createDialog( data?: Macro.CreateData, createOptions?: Macro.Database.DialogCreateOptions, options?: Macro.CreateDialogOptions, ): Promise<Macro.Stored | null | undefined>; override deleteDialog( options?: InexactPartial<foundry.applications.api.DialogV2.ConfirmConfig>, operation?: Document.Database.DeleteOperationForName<"Macro">, ): Promise<this | false | null | undefined>; static override fromDropData( data: Macro.DropData, options?: Macro.DropDataOptions, ): Promise<Macro.Implementation | undefined>; static override fromImport( source: Macro.Source, context?: Document.FromImportContext<Macro.Parent> | null, ): Promise<Macro.Implementation>; #Macro: true; } export default Macro;