import type ECSpresso from './ecspresso'; import type { SystemPhase } from './types'; import type { SystemDefaults } from './system-registrar'; import type { CleanupControl } from './cleanup-control'; import type { WorldConfig, EmptyConfig, MergeConfigs, WithComponents, WithEvents, WithResources, WithAssets, WithScreens } from './type-utils'; /** * Registrar passed as the second argument to a plugin's `install` function. * Each registered disposer runs (in reverse order) when the plugin is * uninstalled via `world.uninstallPlugin(id)` or when `world.dispose()` is called. * Disposers may return promises; world disposal awaits them. The supplied * cleanup control can request world disposal without making the callback wait * on the external teardown barrier that includes that callback. */ export type PluginCleanup = ((cleanup: CleanupControl) => void) | ((cleanup: CleanupControl) => Promise); export type PluginCleanupRegistrar = (fn: PluginCleanup) => void; /** * Plugin interface for ECSpresso. A plugin is a plain object with an `install` * function that configures a world directly, plus phantom properties for * compile-time type extraction. * * @typeParam Cfg - The WorldConfig this plugin provides (components, events, resources, etc.) * @typeParam Requires - The WorldConfig this plugin requires from other plugins */ export interface Plugin { readonly id: string; readonly install: (world: ECSpresso>, onCleanup: PluginCleanupRegistrar) => void; /** * Default system configuration applied to every `world.addSystem(...)` call * made inside the plugin's install function. Explicit per-system calls * override. Set via `PluginBuilder.setSystemDefaults(...)`. */ readonly systemDefaults?: SystemDefaults>; readonly _cfg?: Cfg; readonly _requires?: Requires; readonly _labels?: Labels; readonly _groups?: Groups; readonly _assetGroupNames?: AssetGroupNames; readonly _reactiveQueryNames?: ReactiveQueryNames; } /** * Common configuration options shared by most plugins. * Plugin-specific options interfaces extend this with additional fields. */ export interface BasePluginOptions { /** System group name for all systems registered by this plugin */ systemGroup?: G; /** Priority for the plugin's primary system (default varies per plugin) */ priority?: number; /** Execution phase for the plugin's primary system */ phase?: SystemPhase; } /** * Fluent builder for defining plugins. Mirrors `ECSpressoBuilder`'s * type-accumulator pattern: each `.withXxx()` call threads `T` into the * appropriate WorldConfig slot at the type level, with no runtime cost. * * Terminal call is `.install(fn)` which returns the finalized `Plugin<...>`. * * @example * ```typescript * const myPlugin = definePlugin('my-plugin') * .withComponentTypes() * .withEventTypes() * .withResourceTypes() * .install((world) => { * world.addSystem('foo').setProcess(() => {}); * }); * ``` */ export declare class PluginBuilder { private readonly _id; constructor(_id: string); private _systemDefaults?; /** * Set defaults applied to every system created via `world.addSystem(...)` * inside this plugin's install function. Calling again replaces the * previous defaults wholesale (not merge). Per-system builder calls * override defaults. */ setSystemDefaults(defaults: SystemDefaults>): this; /** * Declare component types this plugin provides. * Pure type-level operation with no runtime cost. */ withComponentTypes>(): PluginBuilder, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames>; /** * Declare event types this plugin provides. * Pure type-level operation with no runtime cost. */ withEventTypes>(): PluginBuilder, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames>; /** * Declare resource types this plugin provides. * Pure type-level operation with no runtime cost. */ withResourceTypes>(): PluginBuilder, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames>; /** * Declare asset types this plugin provides. * Pure type-level operation with no runtime cost. */ withAssetTypes>(): PluginBuilder, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames>; /** * Declare screen types this plugin provides. * Pure type-level operation with no runtime cost. */ withScreenTypes>(): PluginBuilder, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames>; /** * Declare system labels this plugin registers. * Pure type-level operation with no runtime cost. */ withLabels(): PluginBuilder; /** * Declare system groups this plugin uses. * Pure type-level operation with no runtime cost. */ withGroups(): PluginBuilder; /** * Declare asset group names this plugin uses. * Pure type-level operation with no runtime cost. */ withAssetGroupNames(): PluginBuilder; /** * Declare reactive query names this plugin registers. * Pure type-level operation with no runtime cost. */ withReactiveQueryNames(): PluginBuilder; /** * Declare dependencies this plugin requires from other plugins. * Accepts a pre-built `WorldConfig` type (typically a named alias like * `TransformWorldConfig`). The install callback will see these types * merged into its world parameter. Since that world is writable, required * overlapping values must be mutually compatible with the installed world. * Pure type-level operation with no runtime cost. */ requires(): PluginBuilder; /** * Terminal method. Provide the install function and receive the finalized * `Plugin<...>` object. The install function receives a world typed as * `ECSpresso>` — meaning it can use both the * types this plugin provides and the types it declared via `.requires<>()`. */ install(install: (world: ECSpresso>, onCleanup: PluginCleanupRegistrar) => void): Plugin; } /** * Entry point for the fluent plugin builder. Pass the plugin id and chain * type-accumulator methods, terminating with `.install(fn)`. * * @example * ```typescript * const myPlugin = definePlugin('my-plugin') * .withComponentTypes() * .withResourceTypes() * .install((world) => { ... }); * ``` */ export declare function definePlugin(id: string): PluginBuilder;