fvtt-types
Version:
TypeScript type definitions for Foundry VTT
846 lines (713 loc) • 27.8 kB
text/typescript
import type { Socket } from "socket.io-client";
import type { ValueOf, FixedInstanceType, InitializationHook, InitializedOn, EmptyObject, GetKey } from "#utils";
import type BasePackage from "#common/packages/base-package.d.mts";
import type { Document } from "#common/abstract/_module.d.mts";
import type { Canvas } from "#client/canvas/_module.d.mts";
import AVMaster = foundry.av.AVMaster;
import Module = foundry.packages.Module;
// Must be called with all hooks in a union.
// Do not increase the complexity of this type. If you do Game related types may get complex enough to complain about not being statically known.
type SimpleInitializedOn<
InitializedTo,
MustRun extends InitializationHook,
RunHooks extends InitializationHook,
BeforeInitialization = undefined,
> = Extract<RunHooks, MustRun> extends never ? BeforeInitialization : InitializedTo;
/**
* @privateRemarks In v12 many of these properties were mistakenly stripped of their readonly quality;
* This is preserved in the types despite them being technically writable.
* See https://github.com/foundryvtt/foundryvtt/issues/11813
*/
declare class InternalGame<RunEvents extends InitializationHook> {
/**
* @param view - The named view which is active for this game instance.
* @param data - An object of all the World data vended by the server when the client first connects
* @param sessionId - The ID of the currently active client session retrieved from the browser cookie
* @param socket - The open web-socket which should be used to transact game-state data
*/
constructor(view: Game["view"], data: Game.Data, sessionId: Game["sessionId"], socket: Game["socket"]);
/**
* The named view which is currently active.
* @remarks The full type includes `"join"|"setup"|"players"|"license"` but these views do not run package code.
*/
readonly view: Game.View;
/**
* The object of world data passed from the server
*/
readonly data: Game.Data;
/**
* The client session id which is currently active.
*/
readonly sessionId: string;
/**
* A reference to the open Socket.io connection
*/
readonly socket: io.Socket;
/**
* The id of the active World user, if any
*/
readonly userId: string | null;
/**
* The game World which is currently active.
*/
readonly world: foundry.packages.World;
/**
* The System which is used to power this game World.
*/
readonly system: foundry.packages.System;
/**
* A Map of active Modules which are currently eligible to be enabled in this World.
* The subset of Modules which are designated as active are currently enabled.
*/
readonly modules: Game.ModuleCollection;
/**
* A mapping of CompendiumCollection instances, one per Compendium pack.
* @remarks Initialized just before the `"setup"` hook event is called.
*/
readonly packs: SimpleInitializedOn<foundry.documents.collections.CompendiumPacks, "setup", RunEvents>;
/**
* A registry of document sub-types and their respective data models.
*/
get model(): Game.Model;
/**
* @deprecated since v12, will be removed in v14
* @remarks "Game#template is deprecated and will be removed in Version 14. Use cases for Game#template should be refactored to instead use System#documentTypes or Game#model"
*/
get template(): Game.Data["template"];
/**
* A registry of document types supported by the active world.
*/
get documentTypes(): {
[K in Document.Type]: Game.Model.TypeNames<K>[];
};
/**
* The global document index.
* @remarks Initialized just before the `"setup"` hook event is called.
*/
readonly documentIndex: SimpleInitializedOn<foundry.helpers.DocumentIndex, "setup", RunEvents>;
/**
* The UUID redirects tree.
* @remarks Initialized just before the `"ready"` hook event is called.
*/
readonly compendiumUUIDRedirects: foundry.utils.StringTree<string[]>;
/**
* A mapping of WorldCollection instances, one per primary Document type.
* @remarks Initialized just before the `"setup"` hook event is called.
*/
// TODO(LukeAbby): Ideally this would be actually vary based upon `CollectionDocument`.
readonly collections: SimpleInitializedOn<
foundry.utils.Collection<foundry.documents.abstract.WorldCollection<Game.CollectionDocument, string>>,
"setup",
RunEvents
>;
/**
* The collection of Actor documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly actors: SimpleInitializedOn<ConfiguredCollectionClassForName<"Actor">, "setup", RunEvents>;
/**
* The collection of Cards documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly cards: SimpleInitializedOn<ConfiguredCollectionClassForName<"Cards">, "setup", RunEvents>;
/**
* The collection of Combat documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly combats: SimpleInitializedOn<ConfiguredCollectionClassForName<"Combat">, "setup", RunEvents>;
/**
* The collection of Folder documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly folders: SimpleInitializedOn<ConfiguredCollectionClassForName<"Folder">, "setup", RunEvents>;
/**
* The collection of Item documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly items: SimpleInitializedOn<ConfiguredCollectionClassForName<"Item">, "setup", RunEvents>;
/**
* The collection of JournalEntry documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly journal: SimpleInitializedOn<ConfiguredCollectionClassForName<"JournalEntry">, "setup", RunEvents>;
/**
* The collection of Macro documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly macros: SimpleInitializedOn<ConfiguredCollectionClassForName<"Macro">, "setup", RunEvents>;
/**
* The collection of ChatMessage documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly messages: SimpleInitializedOn<ConfiguredCollectionClassForName<"ChatMessage">, "setup", RunEvents>;
/**
* The collection of Playlist documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly playlists: SimpleInitializedOn<ConfiguredCollectionClassForName<"Playlist">, "setup", RunEvents>;
/**
* The collection of Scene documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly scenes: SimpleInitializedOn<ConfiguredCollectionClassForName<"Scene">, "setup", RunEvents>;
/**
* The collection of RollTable documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly tables: SimpleInitializedOn<ConfiguredCollectionClassForName<"RollTable">, "setup", RunEvents>;
/**
* The collection of User documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly users: SimpleInitializedOn<ConfiguredCollectionClassForName<"User">, "setup", RunEvents>;
/**
* The Release data for this version of Foundry
*/
readonly release: foundry.config.ReleaseData;
/**
* Returns the current version of the Release, usable for comparisons using isNewerVersion
*/
get version(): string;
/**
* Whether the Game is running in debug mode
* @defaultValue `false`
*/
readonly debug: boolean;
/**
* A flag for whether texture assets for the game canvas are currently loading
* @defaultValue `false`
*/
readonly loading: boolean;
/**
* The user role permissions setting
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly permissions: SimpleInitializedOn<Game.Permissions, "setup", RunEvents>;
/**
* A flag for whether the Game has successfully reached the "ready" hook
* @defaultValue `false`
*/
readonly ready: SimpleInitializedOn<true, "ready", RunEvents, false>;
/**
* The singleton compendium art manager.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly compendiumArt: foundry.helpers.media.CompendiumArt;
/**
* A singleton instance of the Audio Helper class
*/
readonly audio: foundry.audio.AudioHelper;
/**
* A singleton reference to the Canvas object which may be used.
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly canvas: SimpleInitializedOn<Canvas, "ready", RunEvents>;
/**
* The singleton Clipboard Helper.
*/
readonly clipboard: foundry.helpers.interaction.ClipboardHelper;
/**
* Localization support
* @remarks Initialized just before the `"i18nInit"` hook event.
*/
readonly i18n: SimpleInitializedOn<foundry.helpers.Localization, "i18nInit", RunEvents>;
/**
* The singleton instance of the ClientIssues manager.
*/
readonly issues: foundry.helpers.ClientIssues;
/**
* The Gamepad Manager
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly gamepad: SimpleInitializedOn<foundry.helpers.interaction.GamepadManager, "ready", RunEvents>;
/**
* The Keyboard Manager
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly keyboard: SimpleInitializedOn<foundry.helpers.interaction.KeyboardManager, "ready", RunEvents>;
/**
* Client keybindings which are used to configure application behavior
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly keybindings: SimpleInitializedOn<foundry.helpers.interaction.ClientKeybindings, "ready", RunEvents>;
/**
* The Mouse Manager
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly mouse: SimpleInitializedOn<foundry.helpers.interaction.MouseManager, "ready", RunEvents>;
/**
* The New User Experience manager.
* @remarks Initialized just after the `"ready"` hook event.
*/
readonly nue: foundry.nue.NewUserExperienceManager;
/**
* Client settings which are used to configure application behavior
* @remarks Settings are registered between `"init"` and `"i18nInit"` hook events.
*/
readonly settings: foundry.helpers.ClientSettings;
/**
* A singleton GameTime instance which manages the progression of time within the game world.
*/
readonly time: foundry.helpers.GameTime;
/**
* A singleton instance of the TooltipManager class
* @remarks Initialized just before the `"setup"` hook events is called.
*/
readonly tooltip: SimpleInitializedOn<foundry.helpers.interaction.TooltipManager, "setup", RunEvents>;
/**
* A singleton instance of the Tour collection class
* @remarks Initialized just before the `"setup"` hook events is called.
*/
readonly tours: SimpleInitializedOn<foundry.nue.ToursCollection, "setup", RunEvents>;
/**
* A singleton instance of the Video Helper class
* @remarks Initialized just before the `"setup"` hook events is called.
*/
readonly video: SimpleInitializedOn<foundry.helpers.media.VideoHelper, "setup", RunEvents>;
/**
* A singleton web Worker manager.
*/
readonly workers: foundry.helpers.WorkerManager;
/**
* Fetch World data and return a Game instance
* @param view - The named view being created
* @param sessionId - The current sessionId of the connecting client
* @returns A Promise which resolves to the created Game instance
*/
static create(view: string, sessionId: string | null): Promise<Game>;
/**
* Establish a live connection to the game server through the socket.io URL
* @param sessionId - The client session ID with which to establish the connection
* @returns A promise which resolves to the connected socket, if successful
*/
static connect(sessionId: string): Promise<io.Socket>;
/**
* Retrieve the cookies which are attached to the client session
* @returns The session cookies
*/
static getCookies(): Record<string, string>;
/**
* Request World data from server and return it
* @param socket - The active socket connection
* @param view - The view for which data is being requested
*/
static getData(socket: Socket, view: string): Promise<unknown>;
/**
* Request World data from server and return it
*/
static getWorldData(socket: io.Socket): Promise<Game.Data>;
/**
* Get the current World status upon initial connection.
*/
static getWorldStatus(socket: io.Socket): Promise<boolean>;
/**
* Configure package data that is currently enabled for this world
*/
setupPackages(data: Game.Data): void;
// Following three fields are initialized in setupPackages
/**
* Return the named scopes which can exist for packages.
* Scopes are returned in the prioritization order that their content is loaded.
* @returns An array of string package scopes
*/
getPackageScopes(): string[];
/**
* Initialize the Game for the current window location
*/
initialize(): void;
/**
* Shut down the currently active Game. Requires GameMaster user permission.
*/
shutDown(): Promise<void>;
/**
* Fully set up the game state, initializing Documents, UI applications, and the Canvas
*/
setupGame(): Promise<void>;
/**
* Initialize configuration state.
*/
initializeConfig(): void;
/**
* Initialize game state data by creating WorldCollection instances for every primary Document type
*/
initializeDocuments(): void;
/**
* Initialize the Compendium packs which are present within this Game
* Create a Collection which maps each Compendium pack using it's collection ID
*/
initializePacks(): Promise<this["packs"]>;
/**
* Initialize the WebRTC implementation
*/
initializeRTC(): Promise<boolean>;
/**
* @remarks Initialized just before the `"ready"` hook event.
*/
webrtc: SimpleInitializedOn<AVMaster, "ready", RunEvents>;
/**
* Initialize core UI elements
*/
initializeUI(): void;
/**
* Initialize the game Canvas
*/
initializeCanvas(): Promise<void>;
/**
* Initialize Keyboard controls
*/
initializeKeyboard(): void;
/**
* Initialize Mouse controls
*/
initializeMouse(): void;
/**
* Initialize Gamepad controls
*/
initializeGamepads(): void;
/**
* Register core game settings
*/
registerSettings(): void;
/**
* Register core Tours
*/
registerTours(): Promise<void>;
/**
* Is the current session user authenticated as an application administrator?
*/
get isAdmin(): boolean;
/**
* The currently connected User entity, or null if Users is not yet initialized
*
* @remarks Initialized just before the `"setup"` hook event.
*/
get user(): SimpleInitializedOn<User.Stored, "setup", RunEvents, null>;
/**
* A convenience accessor for the currently viewed Combat encounter
*/
get combat(): foundry.documents.collections.CombatEncounters["viewed"];
/**
* A state variable which tracks whether the game session is currently paused
*/
get paused(): boolean;
/**
* A convenient reference to the currently active canvas tool
*/
get activeTool(): string;
/**
* Toggle the pause state of the game, triggering the {@link hookEvents.pauseGame} hook when the paused
* state changes.
* @param pause - The desired pause state; true for paused, false for un-paused
* @param options - Additional options which modify the pause operation
* @returns The new paused state
*/
togglePause(pause: boolean, options?: Game.TogglePauseOptions): void;
/**
* @deprecated "You are passing the legacy `push` boolean to `Game#togglePause`. This is replaced by the `broadcast` option, for example `game.togglePause(true, {broadcast: true})`" (since v13 until v15)
*/
togglePause(pause: boolean, push?: boolean): void;
/**
* Open Character sheet for current token or controlled actor
* @returns The ActorSheet which was toggled, or null if the User has no character
*/
toggleCharacterSheet(): foundry.appv1.sheets.ActorSheet.Any | foundry.applications.sheets.ActorSheetV2.Any | null;
/**
* Log out of the game session by returning to the Join screen
*/
logOut(): void;
/**
* Scale the base font size according to the user's settings.
* @param index - Optionally supply a font size index to use, otherwise use the user's setting.
* Available font sizes, starting at index 1, are: 8, 10, 12, 14, 16, 18, 20, 24, 28, and 32.
*/
scaleFonts(index?: number): void;
/**
* Activate Socket event listeners which are used to transact game state data with the server
*/
activateSocketListeners(): void;
/**
* Activate Event Listeners which apply to every Game View
*/
activateListeners(): void;
/**
* Support mousewheel control for range type input elements
* @param event - A Mouse Wheel scroll event
*/
protected static _handleMouseWheelInputChange(event: WheelEvent): void;
/**
* On left mouse clicks, check if the element is contained in a valid hyperlink and open it in a new tab.
*/
protected _onClickHyperlink(event: MouseEvent): void;
/**
* Prevent starting a drag and drop workflow on elements within the document unless the element has the draggable
* attribute explicitly defined or overrides the dragstart handler.
* @param event - The initiating drag start event
*/
protected _onPreventDragstart(event: DragEvent): boolean;
/**
* Disallow dragging of external content onto anything but a file input element
* @param event - The requested drag event
*/
protected _onPreventDragover(event: DragEvent): void;
/**
* Disallow dropping of external content onto anything but a file input element
* @param event - The requested drag event
*/
protected _onPreventDrop(event: DragEvent): void;
/**
* On a left-click event, remove any currently displayed inline roll tooltip
* @param event - The mousedown pointer event
*/
protected _onPointerDown(event: PointerEvent): void;
/**
* Fallback handling for mouse-up events which aren't handled further upstream.
* @param event - The mouseup pointer event
*/
protected _onPointerUp(event: PointerEvent): void;
/**
* Handle resizing of the game window by adjusting the canvas and repositioning active interface applications.
* @param event - The window resize event which has occurred
* @internal
*/
protected _onWindowResize(event: UIEvent): void;
/**
* Handle window unload operations to clean up any data which may be pending a final save
* @param event - The window unload event which is about to occur
*/
protected _onWindowBeforeUnload(event: Event): Promise<void>;
/**
* Handle cases where the browser window loses focus to reset detection of currently pressed keys
* @param event - The originating window.blur event
*/
protected _onWindowBlur(event: FocusEvent): void;
protected _onWindowPopState(event: PopStateEvent): void;
/**
* Initialize elements required for the current view
*/
protected _initializeView(): Promise<void>;
/**
* Initialization steps for the primary Game view
*/
protected _initializeGameView(): Promise<void>;
/**
* Initialization steps for the Stream helper view
*/
protected _initializeStreamView(): Promise<void>;
}
type _InitGame = Game & InternalGame<"init">;
type _I18nInitGame = Game & InternalGame<"init" | "i18nInit">;
type _SetupGame = Game & InternalGame<"init" | "i18nInit" | "setup">;
type _ReadyGame = Game & InternalGame<"init" | "i18nInit" | "setup" | "ready">;
/**
* The core Game instance which encapsulates the data, settings, and states relevant for managing the game experience.
* The singleton instance of the Game class is available as the global variable game.
*/
declare class Game extends InternalGame<any> {}
declare global {
// These helper types show `Game` at different points in its life cycle.
// They're merged with `Game` to preserve the invariant `XYZGame instanceof Game`.
// They're interfaces for easier user declaration merges as well as to give intellisense better names to use as the expanded type is intimidating.
interface InitGame extends _InitGame {}
interface I18nInitGame extends _I18nInitGame {}
interface SetupGame extends _SetupGame {}
interface ReadyGame extends _ReadyGame {}
}
declare namespace Game {
interface ModuleCollection extends Collection<foundry.packages.Module, ModuleCollectionMethods> {}
interface ModuleCollectionMethods {
/**
* @remarks Gets the module requested for by ID
* @see {@linkcode ModuleConfig} to add custom properties to modules, for example APIs.
* @see {@linkcode RequiredModules} to remove `undefined` from the return type for a given module
* @param id - The module ID to look up
*/
get<T extends string, Options extends Collection.GetOptions | undefined = undefined>(
id: T,
{ strict }?: Options,
): _ModuleCollectionGet<T, Options>;
}
/** @internal */
type _ModuleCollectionGet<
Name extends string,
Options extends Collection.GetOptions | undefined = undefined,
> = Name extends keyof RequiredModules ? _Module<Name> : Collection.GetReturnType<_MaybeActiveModule<Name>, Options>;
/** @internal */
type _Module<Name extends string> =
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
{ active: true } & Module & GetKey<ModuleConfig, Name, {}>;
/** @internal */
type _MaybeActiveModule<Name extends string> =
| _Module<Name>
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
| ({ active: false } & Module & { [K in keyof GetKey<ModuleConfig, Name, {}>]?: never });
namespace Model {
/**
* Get the configured core and system type names for a specific document type.
*
* Because of module subtypes, extra types of the form `${moduleName}.${subtype}` are
* possible when `hasTypeData` is true.
*
* @template DocumentName - the type of the Document this data is for
*/
type TypeNames<DocumentType extends Document.Type> = Document.SubTypesOf<DocumentType>;
}
/** @internal */
type _Model = {
[DocumentType in Document.Type]: DocumentType extends Document.WithSystem
? _ModelType<DocumentType>
: { base: EmptyObject };
};
/** @internal */
type _ModelType<DocumentType extends Document.WithSystem> =
| (DocumentType extends "ActiveEffect" ? ActiveEffect._ModelMap : never)
| (DocumentType extends "ActorDelta" ? ActorDelta._ModelMap : never)
| (DocumentType extends "Actor" ? Actor._ModelMap : never)
| (DocumentType extends "Card" ? Card._ModelMap : never)
| (DocumentType extends "Cards" ? Cards._ModelMap : never)
| (DocumentType extends "ChatMessage" ? ChatMessage._ModelMap : never)
| (DocumentType extends "Combat" ? Combat._ModelMap : never)
| (DocumentType extends "Combatant" ? Combatant._ModelMap : never)
| (DocumentType extends "CombatantGroup" ? CombatantGroup._ModelMap : never)
| (DocumentType extends "Item" ? Item._ModelMap : never)
| (DocumentType extends "JournalEntryPage" ? JournalEntryPage._ModelMap : never)
| (DocumentType extends "RegionBehavior" ? RegionBehavior._ModelMap : never);
interface Model extends _Model {}
interface PackageWarning {
/** @remarks The ID of the package, matches this objects key in {@linkcode Game.Data.packageWarnings} */
id: string;
/** @remarks From limited empirical sampling, only `false` if the package lacks a manifest */
reinstallable: boolean;
/**
* @remarks Not included if the package itself lacks a manifest (e.g JB2A patreon pack).
* Never seen explicitly `undefined`, only omitted, during testing.
*/
manifest?: string | undefined;
/** @remarks Presumably `"world" | "system" | "module"`, but difficult to confirm. */
type: string;
/**
* Error messages.
*/
error: string[];
/**
* Warning messages.
*/
warning: string[];
}
type Data = {
activeUsers: string[];
addresses: {
local: string;
remote?: string | undefined;
remoteIsAccessible: boolean | null;
};
coreUpdate: {
channel: string | null;
couldReachWebsite: boolean;
hasUpdate: boolean;
slowResponse: boolean;
version: string | null;
willDisableModules: boolean;
};
demoMode: boolean;
files: {
s3?: {
endpoint: {
protocol: string;
host: string;
port: number;
hostname: string;
pathname: string;
path: string;
href: string;
};
buckets: string[];
} | null;
storages: ("public" | "data" | "s3")[];
};
modules: foundry.packages.Module["_source"][];
options: {
language: string;
port: number;
routePrefix: string | null;
updateChannel: string;
};
packageWarnings: Record<string, PackageWarning>;
packs: Array<
PackageCompendiumData & {
/** @deprecated since v11 */
private?: boolean;
system?: string | undefined;
type: foundry.CONST.COMPENDIUM_DOCUMENT_TYPES;
packageName: BasePackage["_source"]["id"];
packageType: BasePackage["type"];
id: string;
}
>;
paused: boolean;
release: foundry.config.ReleaseData["_source"];
system: foundry.packages.System["_source"];
systemUpdate: {
hasUpdate: boolean;
version: string;
};
// TODO: I think this is only for configurable types
template: Record<Document.Type, DocumentTemplate> | null;
// TODO: This is also inheriting the configured types,
// but is only filled in if there's `template.json`
model: Model;
userId: string;
world: foundry.packages.World["_source"];
} & {
[DocumentType in // eslint-disable-next-line @typescript-eslint/no-deprecated
| foundry.CONST.DOCUMENT_TYPES
| "Setting" as Document.ImplementationClassFor<DocumentType>["metadata"]["collection"]]?: FixedInstanceType<
Document.ImplementationClassFor<DocumentType>
>["_source"][];
};
type Permissions = {
[Key in keyof typeof foundry.CONST.USER_PERMISSIONS]: foundry.CONST.USER_ROLES[];
};
type View = ValueOf<typeof foundry.CONST.GAME_VIEWS>;
interface TogglePauseOptions {
/**
* Broadcast the pause state change to other connected clients?
* Broadcasting to other clients can only be done by a GM user.
* @defaultValue `false`
*/
broadcast?: boolean | undefined;
/**
* The ID of the user who triggered the pause operation. This is
* populated automatically by the game server.
*/
userId?: string | undefined;
}
// Note(LukeAbby): See `Game#initializeDocuments`'s `initOrder`.
type CollectionDocument =
| "User"
| "Folder"
| "Actor"
| "Item"
| "Scene"
| "Combat"
| "JournalEntry"
| "Macro"
| "Playlist"
| "RollTable"
| "Cards"
| "ChatMessage";
}
declare global {
/**
* @defaultValue `undefined`
* Initialized just before the `"init"` hook event.
*/
let canvas: InitializedOn<Canvas, "init">;
}
type ConfiguredCollectionClassForName<Name extends foundry.CONST.WORLD_DOCUMENT_TYPES> = FixedInstanceType<
CONFIG[Name]["collection"]
>;
interface DocumentTemplate {
htmlFields: string[];
types: string[];
}
export default Game;