diff --git a/build/lib/extractor.ts b/build/lib/extractor.ts index 8b0c8912074..b8eb922efff 100644 --- a/build/lib/extractor.ts +++ b/build/lib/extractor.ts @@ -390,7 +390,7 @@ class PackExtractor { } else if ("details" in docSource.system && "publicNotes" in docSource.system.details) { docSource.system.details.publicNotes = cleanDescription(docSource.system.details.publicNotes); } - } else if ("content" in docSource) { + } else if ("content" in docSource && typeof docSource.content === "string") { docSource.content = cleanDescription(docSource.content); } @@ -409,10 +409,12 @@ class PackExtractor { } delete (docSource as { _stats?: unknown })._stats; - docSource.img &&= docSource.img.replace( - "https://assets.forge-vtt.com/bazaar/systems/pf2e/assets/", - "systems/pf2e/" - ) as ImageFilePath; + if ("img" in docSource && typeof docSource.img === "string") { + docSource.img = docSource.img.replace( + "https://assets.forge-vtt.com/bazaar/systems/pf2e/assets/", + "systems/pf2e/" + ) as ImageFilePath; + } if (isObject(docSource.flags?.pf2e) && Object.keys(docSource.flags.pf2e).length === 0) { delete docSource.flags.pf2e; diff --git a/src/module/actor/helpers.ts b/src/module/actor/helpers.ts index 4453dda7c8f..9a76d9f3db5 100644 --- a/src/module/actor/helpers.ts +++ b/src/module/actor/helpers.ts @@ -197,7 +197,7 @@ function createEncounterRollOptions(actor: ActorPF2e): Record { [`encounter:threat:${numericThreat}`, !!threat], [`encounter:threat:${threat}`, !!threat], [`encounter:round:${encounter.round}`, true], - [`encounter:turn:${encounter.turn + 1}`, true], + [`encounter:turn:${Number(encounter.turn) + 1}`, true], ["self:participant:own-turn", encounter.combatant?.actor === actor], [`self:participant:initiative:roll:${initiativeRoll}`, true], [`self:participant:initiative:rank:${initiativeRank}`, true], diff --git a/src/module/apps/sidebar/chat-log.ts b/src/module/apps/sidebar/chat-log.ts index 361a7118f0e..a51f013fd88 100644 --- a/src/module/apps/sidebar/chat-log.ts +++ b/src/module/apps/sidebar/chat-log.ts @@ -86,7 +86,7 @@ class ChatLogPF2e extends ChatLog { protected override async _processDiceCommand( command: string, matches: RegExpMatchArray[], - chatData: DeepPartial, + chatData: PreCreate & { rolls: (string | RollJSON)[] }>, createOptions: ChatMessageModificationContext ): Promise { const actor = ChatMessage.getSpeakerActor(chatData.speaker ?? {}) || game.user.character; diff --git a/src/module/encounter/document.ts b/src/module/encounter/document.ts index 7f7b0aee415..9d67ccc0bbc 100644 --- a/src/module/encounter/document.ts +++ b/src/module/encounter/document.ts @@ -341,6 +341,8 @@ class EncounterPF2e extends Combat { interface EncounterPF2e extends Combat { readonly combatants: foundry.abstract.EmbeddedCollection>; + scene: ScenePF2e; + rollNPC(options: RollInitiativeOptionsPF2e): Promise; } diff --git a/src/module/migration/migrations/850-flat-footed-to-off-guard.ts b/src/module/migration/migrations/850-flat-footed-to-off-guard.ts index 7cfb42fcfba..12927202c06 100644 --- a/src/module/migration/migrations/850-flat-footed-to-off-guard.ts +++ b/src/module/migration/migrations/850-flat-footed-to-off-guard.ts @@ -68,7 +68,9 @@ export class Migration850FlatFootedToOffGuard extends MigrationBase { if (source.name === "Remaster Changes") return; source.name = source.name.replace(this.#oldNamePattern, this.#newName); - source.img &&= source.img.replace(this.#imgPattern, "off-guard.webp") as ImageFilePath; + if ("img" in source && typeof source.img === "string") { + source.img = source.img.replace(this.#imgPattern, "off-guard.webp"); + } source.pages = recursiveReplaceString(source.pages, (s) => this.#replace(s)); if ("content" in source && typeof source.content === "string") { source.content = this.#replace(source.content); diff --git a/src/module/system/damage/damage.ts b/src/module/system/damage/damage.ts index ee0287ca2fc..8304c9dbe6d 100644 --- a/src/module/system/damage/damage.ts +++ b/src/module/system/damage/damage.ts @@ -212,23 +212,24 @@ export class DamagePF2e { unadjustedOutcome: context.unadjustedOutcome ?? null, }; - const messageData = await roll.toMessage( - { - speaker: ChatMessagePF2e.getSpeaker({ actor: self?.actor, token: self?.token }), - flavor, - flags: { - pf2e: { - context: contextFlag, - target: targetFlag, - modifiers: data.modifiers?.map((m) => m.toObject()) ?? [], - origin: item?.getOriginData(), - strike, - preformatted: "both", + const messageData: Omit & { rolls: (string | RollJSON)[] } = + await roll.toMessage( + { + speaker: ChatMessagePF2e.getSpeaker({ actor: self?.actor, token: self?.token }), + flavor, + flags: { + pf2e: { + context: contextFlag, + target: targetFlag, + modifiers: data.modifiers?.map((m) => m.toObject()) ?? [], + origin: item?.getOriginData(), + strike, + preformatted: "both", + }, }, }, - }, - { create: false } - ); + { create: false } + ); // If there is splash damage, include it as an additional roll for separate application const splashRolls = await (async (): Promise => { diff --git a/src/scripts/macros/hotbar.ts b/src/scripts/macros/hotbar.ts index ac42451c30c..d2cafc169cd 100644 --- a/src/scripts/macros/hotbar.ts +++ b/src/scripts/macros/hotbar.ts @@ -79,7 +79,7 @@ export async function rollActionMacro( const content = await renderTemplate("systems/pf2e/templates/chat/strike-card.hbs", templateData); const token = actor.token ?? actor.getActiveTokens(true, true).shift() ?? null; - const chatData: Partial = { + const chatData: PreCreate = { speaker: ChatMessagePF2e.getSpeaker({ actor, token }), content, type: CONST.CHAT_MESSAGE_TYPES.OTHER, diff --git a/types/foundry/client/data/documents/chat-message.d.ts b/types/foundry/client/data/documents/chat-message.d.ts index 6ffbb7970a6..0fecc443eca 100644 --- a/types/foundry/client/data/documents/chat-message.d.ts +++ b/types/foundry/client/data/documents/chat-message.d.ts @@ -10,8 +10,6 @@ declare global { class ChatMessage extends ClientBaseChatMessage { constructor(data: PreCreate, context?: DocumentConstructionContext); - flavor: string; - _rollExpanded: boolean; /** @@ -39,9 +37,6 @@ declare global { */ override get visible(): boolean; - /** The User who created the chat message. */ - get user(): User | undefined; - override prepareData(): void; /** @@ -173,20 +168,26 @@ declare global { export(): string; } + interface ChatMessage extends ClientBaseChatMessage { + user: User; + } + namespace ChatMessage { function create( this: ConstructorOf, - data: PreCreate[], + data: DeepPartial & { rolls: (string | RollJSON)[] }>[], context?: ChatMessageModificationContext ): Promise; function create( this: ConstructorOf, - data: PreCreate, + data: DeepPartial & { rolls: (string | RollJSON)[] }>, context?: ChatMessageModificationContext ): Promise; function create( this: ConstructorOf, - data: PreCreate[] | PreCreate, + data: + | DeepPartial & { rolls: (string | RollJSON)[] }>[] + | DeepPartial & { rolls: (string | RollJSON)[] }>, context?: ChatMessageModificationContext ): Promise; } diff --git a/types/foundry/client/data/documents/combat.d.ts b/types/foundry/client/data/documents/combat.d.ts index b35edf9f528..f104c5b4757 100644 --- a/types/foundry/client/data/documents/combat.d.ts +++ b/types/foundry/client/data/documents/combat.d.ts @@ -9,8 +9,6 @@ declare global { class Combat extends ClientBaseCombat { constructor(data: PreCreate, context?: DocumentConstructionContext); - active: boolean; - /** Track the sorted turn order of this combat encounter */ turns: CollectionValue[]; @@ -30,21 +28,12 @@ declare global { /** Get the Combatant who has the current turn. */ get combatant(): CollectionValue | undefined; - /** The numeric round of the Combat encounter */ - get round(): number; - - /** A reference to the Scene document within which this Combat encounter occurs */ - get scene(): NonNullable["actor"]>["parent"]>["parent"]; - /** Return the object of settings which modify the Combat Tracker behavior */ get settings(): Record; /** Has this combat encounter been started? */ get started(): boolean; - /** The numeric turn of the combat round in the Combat encounter */ - get turn(): number; - override get visible(): true; /** Is this combat active in the current scene? */ diff --git a/types/foundry/common/abstract/data.d.ts b/types/foundry/common/abstract/data.d.ts index 0c1b886cc22..eab2da1d917 100644 --- a/types/foundry/common/abstract/data.d.ts +++ b/types/foundry/common/abstract/data.d.ts @@ -204,15 +204,7 @@ export default abstract class DataModel< static migrateDataSafe(source: object): object; } -export type RawObject = { - [P in keyof TModel]: TModel[P] extends EmbeddedCollection - ? RawObject[] - : TModel[P] extends DataModel - ? RawObject - : TModel[P] extends DataModel[] - ? RawObject[] - : TModel[P]; -}; +export type RawObject = TModel["_source"]; export interface DataModelValidationOptions { changes?: object; diff --git a/types/foundry/common/documents/chat-message.d.ts b/types/foundry/common/documents/chat-message.d.ts index b2eb89d4773..fa8d684f971 100644 --- a/types/foundry/common/documents/chat-message.d.ts +++ b/types/foundry/common/documents/chat-message.d.ts @@ -1,4 +1,5 @@ import type { Document, DocumentMetadata } from "../abstract/module.d.ts"; +import type * as fields from "../data/fields.d.ts"; import type { BaseUser } from "./module.d.ts"; /** @@ -8,54 +9,52 @@ import type { BaseUser } from "./module.d.ts"; * @param data Initial data from which to construct the document. * @property data The constructed data object for the document. */ -export default class BaseChatMessage extends Document { - blind: boolean; - content: string; - flags: ChatMessageFlags; +export default class BaseChatMessage extends Document { rolls: Rolled[]; - speaker: ChatSpeakerData; - type: ChatMessageType; - whisper: string[]; static override get metadata(): ChatMessageMetadata; - /** Is a user able to create a new chat message? */ - protected static _canCreate(user: BaseUser, doc: BaseChatMessage): boolean; - - /** Is a user able to update an existing chat message? */ - protected static _canUpdate(user: BaseUser, doc: BaseChatMessage, data: ChatMessageSource): boolean; - - /** Is a user able to delete an existing chat message? */ - protected static _canDelete(user: BaseUser, doc: BaseChatMessage): boolean; - - static override createDocuments>( - this: ConstructorOf, - data?: (TDocument | PreCreate)[], - context?: ChatMessageModificationContext - ): Promise; + static override defineSchema(): ChatMessageSchema; } -export default interface BaseChatMessage extends Document { +export default interface BaseChatMessage + extends Document, + ModelPropsFromSchema { readonly _source: ChatMessageSource; get documentName(): "ChatMessage"; } -export interface ChatMessageSource { - _id: string; - type: ChatMessageType; - user: string; - timestamp: string; - flavor?: string; - content: string; - speaker: ChatSpeakerData; - whisper: string[]; - blind: boolean; - rolls: (string | RollJSON)[]; - sound: AudioFilePath; - emote?: boolean; - flags: ChatMessageFlags; -} +export type ChatMessageSchema = { + /** The _id which uniquely identifies this ChatMessage document */ + _id: fields.DocumentIdField; + /** The message type from CONST.CHAT_MESSAGE_TYPES */ + type: fields.NumberField; + /** The _id of the User document who generated this message */ + user: fields.ForeignDocumentField; + /** The timestamp at which point this message was generated */ + timestamp: fields.NumberField; + /** An optional flavor text message which summarizes this message */ + flavor: fields.HTMLField; + /** The HTML content of this chat message */ + content: fields.HTMLField; + /** A ChatSpeakerData object which describes the origin of the ChatMessage */ + speaker: fields.SchemaField; + /** An array of User _id values to whom this message is privately whispered */ + whisper: fields.ArrayField>; + /** Is this message sent blindly where the creating User cannot see it? */ + blind: fields.BooleanField; + /** Serialized content of any Roll instances attached to the ChatMessage */ + rolls: fields.ArrayField>; + /** The URL of an audio file which plays when this message is received */ + sound: fields.FilePathField; + /** Is this message styled as an emote? */ + emote: fields.BooleanField; + /** An object of optional key/value flags */ + flags: fields.ObjectField; +}; + +export type ChatMessageSource = SourceFromSchema; export interface ChatMessageFlags extends DocumentFlags { core?: { @@ -65,37 +64,25 @@ export interface ChatMessageFlags extends DocumentFlags { }; } -/** - * The data schema for an embedded Chat Speaker object. - * @extends DocumentData - * @memberof data - * @see ChatMessageData - * - * @param data Initial data used to construct the data object - * @param [document] The document to which this data object belongs - * - * @property [scene] The _id of the Scene where this message was created - * @property [actor] The _id of the Actor who generated this message - * @property [token] The _id of the Token who generated this message - * @property [alias] An overridden alias name used instead of the Actor or Token name - */ -export interface ChatSpeakerData { - scene?: string | null; - actor?: string | null; - token?: string | null; - alias: string; -} +type ChatSpeakerSchema = { + /** The _id of the Scene where this message was created */ + scene: fields.ForeignDocumentField; + /** The _id of the Actor who generated this message */ + actor: fields.ForeignDocumentField; + /** The _id of the Token who generated this message */ + token: fields.ForeignDocumentField; + /** An overridden alias name used instead of the Actor or Token name */ + alias: fields.StringField; +}; + +type ChatSpeakerData = SourceFromSchema; interface ChatMessageMetadata extends DocumentMetadata { name: "ChatMessage"; collection: "messages"; label: "DOCUMENT.ChatMessage"; + labelPlural: "DOCUMENT.ChatMessages"; isPrimary: true; - permissions: { - create: (typeof BaseChatMessage)["_canCreate"]; - update: (typeof BaseChatMessage)["_canUpdate"]; - delete: (typeof BaseChatMessage)["_canDelete"]; - }; } declare global { diff --git a/types/foundry/common/documents/combat.d.ts b/types/foundry/common/documents/combat.d.ts index 1fefd72653b..20ec4f96792 100644 --- a/types/foundry/common/documents/combat.d.ts +++ b/types/foundry/common/documents/combat.d.ts @@ -1,23 +1,19 @@ import type { Document, DocumentMetadata, EmbeddedCollection } from "../abstract/module.d.ts"; -import type { CombatantSource } from "./combatant.d.ts"; -import type { BaseCombatant, BaseUser } from "./module.d.ts"; +import type * as fields from "../data/fields.d.ts"; +import type { BaseCombatant, BaseScene } from "./module.d.ts"; /** The Combat document model. */ -export default class BaseCombat extends Document { +export default class BaseCombat extends Document { static override get metadata(): CombatMetadata; - flags: DocumentFlags; - - /** A reference to the Collection of Combatant instances in the Combat document, indexed by id. */ - readonly combatants: EmbeddedCollection>; - - /** Is a user able to update an existing Combat? */ - protected static _canUpdate(user: BaseUser, doc: BaseCombat, data: CombatSource): boolean; + static override defineSchema(): CombatSchema; } -export default interface BaseCombat extends Document { +export default interface BaseCombat extends Document, ModelPropsFromSchema { readonly _source: CombatSource; + readonly combatants: EmbeddedCollection>; + get documentName(): "Combat"; } @@ -29,31 +25,26 @@ interface CombatMetadata extends DocumentMetadata { Combatant: "combatants"; }; isPrimary: true; - permissions: { - create: "ASSISTANT"; - update: (typeof BaseCombat)["_canUpdate"]; - delete: "ASSISTANT"; - }; } -/** - * The data schema for a Combat document. - * @property _id The _id which uniquely identifies this Combat document - * @property scene The _id of a Scene within which this Combat occurs - * @property combatants A Collection of Combatant embedded Documents - * @property [active=false] Is the Combat encounter currently active? - * @property [round=0] The current round of the Combat encounter - * @property [turn=0] The current turn in the Combat round - * @property [sort=0] The current sort order of this Combat relative to others in the same Scene - * @property [flags={}] An object of optional key/value flags - */ -interface CombatSource { - _id: string; - scene: string; - combatants: CombatantSource[]; - active: boolean; - round: number; - turn: number; - sort: number; - flags: DocumentFlags; -} +type CombatSchema = { + /** The _id which uniquely identifies this Combat document */ + _id: fields.DocumentIdField; + /** The _id of a Scene within which this Combat occurs */ + scene: fields.ForeignDocumentField; + /** A Collection of Combatant embedded Documents */ + combatants: fields.EmbeddedCollectionField>; + /** Is the Combat encounter currently active? */ + active: fields.BooleanField; + /** The current round of the Combat encounter */ + round: fields.NumberField; + /** The current turn in the Combat round */ + turn: fields.NumberField; + /** The current sort order of this Combat relative to others in the same Scene */ + sort: fields.IntegerSortField; + /** An object of optional key/value flags */ + flags: fields.ObjectField; + _stats: fields.DocumentStatsField; +}; + +type CombatSource = SourceFromSchema; diff --git a/types/foundry/common/documents/combatant.d.ts b/types/foundry/common/documents/combatant.d.ts index 1856b8d8ad4..b1054047a76 100644 --- a/types/foundry/common/documents/combatant.d.ts +++ b/types/foundry/common/documents/combatant.d.ts @@ -5,9 +5,6 @@ import type * as fields from "../data/fields.d.ts"; /** The Combat document model. */ export default class BaseCombatant extends Document { static override get metadata(): CombatantMetadata; - - /** Is a user able to update an existing Combatant? */ - protected static _canUpdate(user: BaseUser, doc: BaseCombatant, data: CombatantSource): boolean; } export default interface BaseCombatant @@ -21,11 +18,6 @@ interface CombatantMetadata extends DocumentMetadata { collection: "combatants"; label: "DOCUMENT.Combatant"; isPrimary: true; - permissions: { - create: "PLAYER"; - update: (typeof BaseCombatant)["_canUpdate"]; - delete: "ASSISTANT"; - }; } /** The data schema for a Combat document. */ diff --git a/types/foundry/common/documents/journal-entry-page.d.ts b/types/foundry/common/documents/journal-entry-page.d.ts index d7595eee0a7..c6f317cf033 100644 --- a/types/foundry/common/documents/journal-entry-page.d.ts +++ b/types/foundry/common/documents/journal-entry-page.d.ts @@ -3,7 +3,10 @@ import type * as fields from "../data/fields.d.ts"; import type { BaseJournalEntry, BaseUser } from "./module.d.ts"; /** The JournalEntryPage document model. */ -export default class BaseJournalEntryPage extends abstract.Document { +export default class BaseJournalEntryPage extends abstract.Document< + TParent, + JournalEntryPageSchema +> { static override get metadata(): JournalEntryPageMetadata; static override defineSchema(): JournalEntryPageSchema; @@ -12,7 +15,7 @@ export default class BaseJournalEntryPage - extends abstract.Document, + extends abstract.Document, ModelPropsFromSchema { readonly _source: SourceFromSchema; diff --git a/types/foundry/common/documents/journal-entry.d.ts b/types/foundry/common/documents/journal-entry.d.ts index a35293f0c55..b9ea422ffea 100644 --- a/types/foundry/common/documents/journal-entry.d.ts +++ b/types/foundry/common/documents/journal-entry.d.ts @@ -1,46 +1,25 @@ import type { Document, DocumentMetadata, EmbeddedCollection } from "../abstract/module.d.ts"; -import type { JournalEntryPageSchema } from "./journal-entry-page.d.ts"; +import type * as fields from "../data/fields.d.ts"; +import type * as documents from "./module.d.ts"; import type { BaseJournalEntryPage } from "./module.d.ts"; /** The JournalEntry document model. */ -export default class BaseJournalEntry extends Document { +export default class BaseJournalEntry extends Document { static override get metadata(): JournalEntryMetadata; + static override defineSchema(): JournalEntrySchema; + readonly pages: EmbeddedCollection>; } -export default interface BaseJournalEntry extends Document { +export default interface BaseJournalEntry + extends Document, + ModelPropsFromSchema { readonly _source: JournalEntrySource; get documentName(): (typeof BaseJournalEntry)["metadata"]["name"]; -} -/** - * The data schema for a JournalEntry document. - * @see BaseJournalEntry - * - * @param data Initial data used to construct the data object - * @param [document] The document to which this data object belongs - * - * @property _id The _id which uniquely identifies this JournalEntry document - * @property name The name of this JournalEntry - * @property pages The pages contained within this JournalEntry document - * @property [img] An image file path which provides the artwork for this JournalEntry - * @property folder The _id of a Folder which contains this JournalEntry - * @property [sort] The numeric sort value which orders this JournalEntry relative to its siblings - * @property [permission] An object which configures user permissions to this JournalEntry - * @property [flags={}] An object of optional key/value flags - */ -interface JournalEntrySource { - _id: string; - name: string; - pages: SourceFromSchema[]; - content: string; - img: ImageFilePath; - folder: string | null; - sort: number; - ownership: Record; - flags: Record>; + foo: this["_source"]["pages"]; } interface JournalEntryMetadata extends DocumentMetadata { @@ -58,3 +37,25 @@ interface JournalEntryMetadata extends DocumentMetadata { create: "JOURNAL_CREATE"; }; } + +type JournalEntrySchema = { + /** The _id which uniquely identifies this JournalEntry document */ + _id: fields.DocumentIdField; + /** The name of this JournalEntry */ + name: fields.StringField; + /** The pages contained within this JournalEntry document */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + pages: fields.EmbeddedCollectionField>; + /** The _id of a Folder which contains this JournalEntry */ + folder: fields.ForeignDocumentField; + /** The numeric sort value which orders this JournalEntry relative to its siblings */ + sort: fields.IntegerSortField; + /** An object which configures ownership of this JournalEntry */ + ownership: fields.DocumentOwnershipField; + /** An object of optional key/value flags */ + flags: fields.ObjectField; + /** An object of creation and access information */ + _stats: fields.DocumentStatsField; +}; + +type JournalEntrySource = SourceFromSchema; diff --git a/types/foundry/common/documents/roll-table.d.ts b/types/foundry/common/documents/roll-table.d.ts index d4b3058f6d7..1cb82496927 100644 --- a/types/foundry/common/documents/roll-table.d.ts +++ b/types/foundry/common/documents/roll-table.d.ts @@ -1,60 +1,28 @@ import type { Document, DocumentMetadata, EmbeddedCollection } from "../abstract/module.d.ts"; -import type { BaseTableResult } from "./module.d.ts"; -import type { TableResultSource } from "./table-result.d.ts"; +import type * as fields from "../data/fields.d.ts"; +import type * as documents from "./module.d.ts"; /** * The RollTable document model. * @param data Initial data from which to construct the document. * @property data The constructed data object for the document. */ -export default class BaseRollTable extends Document { +export default class BaseRollTable extends Document { static override get metadata(): RollTableMetadata; - name: string; + static override defineSchema(): RollTableSchema; - /** A reference to the Collection of TableResult instances in this document, indexed by _id. */ - readonly results: EmbeddedCollection>; + /** The default icon used for newly created Macro documents */ + static DEFAULT_ICON: ImageFilePath; } -export default interface BaseRollTable extends Document { +export default interface BaseRollTable extends Document, ModelPropsFromSchema { readonly _source: RollTableSource; - get documentName(): (typeof BaseRollTable)["metadata"]["name"]; -} + /** A reference to the Collection of TableResult instances in this document, indexed by _id. */ + readonly results: EmbeddedCollection>; -/** - * The data schema for a RollTable document. - * @see BaseRollTable - * - * @param data Initial data used to construct the data object - * @param [document] The document to which this data object belongs - * - * @property _id The _id which uniquely identifies this RollTable document - * @property name The name of this RollTable - * @property [img] An image file path which provides the thumbnail artwork for this RollTable - * @property [description] The HTML text description for this RollTable document - * @property [results=[]] A Collection of TableResult embedded documents which belong to this RollTable - * @property formula The Roll formula which determines the results chosen from the table - * @property [replacement=true] Are results from this table drawn with replacement? - * @property [displayRoll=true] Is the Roll result used to draw from this RollTable displayed in chat? - * @property folder The _id of a Folder which contains this RollTable - * @property [sort] The numeric sort value which orders this RollTable relative to its siblings - * @property [permission] An object which configures user permissions to this RollTable - * @property [flags={}] An object of optional key/value flags - */ -interface RollTableSource { - _id: string; - name: string; - img?: ImageFilePath; - description: string; - results: TableResultSource[]; - formula: string; - replacement: boolean; - displayRoll: boolean; - folder?: string | null; - sort: number; - ownership: Record; - flags: Record>; + get documentName(): (typeof BaseRollTable)["metadata"]["name"]; } interface RollTableMetadata extends DocumentMetadata { @@ -66,3 +34,35 @@ interface RollTableMetadata extends DocumentMetadata { }; isPrimary: true; } + +type RollTableSchema = { + /** The _id which uniquely identifies this RollTable document */ + _id: fields.DocumentIdField; + /** The name of this RollTable */ + name: fields.StringField; + /** An image file path which provides the thumbnail artwork for this RollTable */ + img: fields.FilePathField; + /** The HTML text description for this RollTable document */ + description: fields.HTMLField; + /** A Collection of TableResult embedded documents which belong to this RollTable */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + results: fields.EmbeddedCollectionField>; + /** The Roll formula which determines the results chosen from the table */ + formula: fields.StringField; + /** Are results from this table drawn with replacement? */ + replacement: fields.BooleanField; + /** Is the Roll result used to draw from this RollTable displayed in chat? */ + displayRoll: fields.BooleanField; + /** The _id of a Folder which contains this RollTable */ + folder: fields.ForeignDocumentField; + /** The numeric sort value which orders this RollTable relative to its siblings */ + sort: fields.IntegerSortField; + /** An object which configures ownership of this RollTable */ + ownership: fields.DocumentOwnershipField; + /** An object of optional key/value flags */ + flags: fields.ObjectField; + /** An object of creation and access information */ + _stats: fields.DocumentStatsField; +}; + +type RollTableSource = SourceFromSchema; diff --git a/types/foundry/common/documents/table-result.d.ts b/types/foundry/common/documents/table-result.d.ts index 91ca05c4b59..fff5c43fef0 100644 --- a/types/foundry/common/documents/table-result.d.ts +++ b/types/foundry/common/documents/table-result.d.ts @@ -1,16 +1,15 @@ import type { Document, DocumentMetadata } from "../abstract/module.d.ts"; import type { BaseRollTable, BaseUser } from "./module.d.ts"; +import type * as fields from "../data/fields.d.ts"; /** The TableResult document model. */ -export default class BaseTableResult extends Document { +export default class BaseTableResult extends Document< + TParent, + TableResultSchema +> { static override get metadata(): TableResultMetadata; - /** Is a user able to update an existing TableResult? */ - protected static _canUpdate( - user: BaseUser, - doc: BaseTableResult, - data: TableResultSource - ): boolean; + static override defineSchema(): TableResultSchema; override testUserPermission( user: BaseUser, @@ -19,45 +18,42 @@ export default class BaseTableResult exten ): boolean; } -export default interface BaseTableResult extends Document { +export default interface BaseTableResult + extends Document { readonly _source: TableResultSource; } -/** - * The data schema for a TableResult embedded document within a Roll Table. - * @see BaseTableResult - * - * @param data Initial data used to construct the data object - * @param [document] The document to which this data object belongs - * - * @property [type=p] A result sub-type from CONST.TABLE_RESULT_TYPES - * @property [text] The text which describes the table result - * @property [img] An image file url that represents the table result - * @property [collection] A named collection from which this result is drawn - * @property [resultId] The _id of a Document within the collection this result references - * @property [weight=1] The probabilistic weight of this result relative to other results - * @property [range] A length 2 array of ascending integers which defines the range of dice roll - * totals which produce this drawn result - * @property [drawn=false] Has this result already been drawn (without replacement) - */ -interface TableResultSource { - _id: string; - type: TableResultType; - text: string; - img: ImageFilePath; - collection: string; - resultId: string; - weight: number; - range: [number, number]; - drawn: boolean; -} - interface TableResultMetadata extends DocumentMetadata { name: "TableResult"; collection: "results"; label: "DOCUMENT.TableResult"; types: typeof CONST.TABLE_RESULT_TYPES; - permissions: Omit & { - update: (typeof BaseTableResult)["_canUpdate"]; - }; } + +type TableResultSchema = { + /** The _id which uniquely identifies this TableResult embedded document */ + _id: fields.DocumentIdField; + /** A result subtype from CONST.TABLE_RESULT_TYPES */ + type: fields.NumberField; + /** The text which describes the table result */ + text: fields.HTMLField; + /** An image file url that represents the table result */ + img: fields.FilePathField; + /** A named collection from which this result is drawn */ + documentCollection: fields.StringField; + /** The _id of a Document within the collection this result references */ + documentId: fields.ForeignDocumentField; + /** The probabilistic weight of this result relative to other results */ + weight: fields.NumberField; + /** + * A length 2 array of ascending integers which defines the range of dice roll totals which produce this drawn + * result + */ + range: fields.ArrayField; + /** Has this result already been drawn (without replacement) */ + drawn: fields.BooleanField; + /** An object of optional key/value flags */ + flags: fields.ObjectField; +}; + +type TableResultSource = SourceFromSchema;