refactor(core): CORE-08 type plugin registration and guard closed instances

This commit is contained in:
Harvey Zhao committed 2026-09-11 02:09:36 +08:00
1 parent f9707bad71
commit 874dac9f22
36 files changed
+2865 -142

No files matched your search

+27
View File
@@ -55,3 +55,30 @@ declaration. Optional capability checks belong to their consumers. Full construc
type integration is tracked by CORE-20; proxy package migration validates each real
adapter separately. Source type fixtures and real canvas integration live in
test/types/media-hosts.ts and test/browser/media-hosts.spec.js.
## Plugin and event augmentation
Use the type-only `artplayer/types` entry to augment the shared Plugins and Events
interfaces. This reaches the same definition through Node10, NodeNext CJS/ESM and
Bundler. Directly augmenting the root CJS namespace type alias is not equivalent.
```ts
import Artplayer from 'artplayer'
declare module 'artplayer/types' {
interface Plugins {
customPlugin?: { update: (value: number) => void }
}
}
const art = new Artplayer({ container: '#player' })
art.plugins.customPlugin?.update(1)
```
Types do not register a plugin or prove that it is installed; retain a presence
guard unless the application owns and verifies installation. PluginFactory describes
the existing single art argument and this receiver. Public add keeps its historical
return signature; internal manager types model actual returns separately. The new
subpath has no runtime export; use it only for types/augmentation. plugins-public.ts
tests the same declarations in all installed consumer modes, and package runtime
checks reject both require and import of artplayer/types.
+2
View File
@@ -14,6 +14,8 @@ declare namespace Artplayer {
type Option = Definition.Option
type OptionInput = Definition.OptionInput
type Player = Definition.Player
type PluginFactory<Host = Artplayer, Result = unknown> = Definition.PluginFactory<Host, Result>
type Plugins = Definition.Plugins
type Setting = Definition.Setting
type SettingOption = Definition.SettingOption
type Subtitle = Definition.Subtitle
+1 -1
View File
@@ -1,2 +1,2 @@
export { default } from './artplayer.cjs'
export type { Config, Emitter, Events, I18n, Icons, Option, OptionInput, Player, Setting, SettingOption, Subtitle, SubtitleUpdateEvents, Template, Utils } from './artplayer.js'
export type { Config, Emitter, Events, I18n, Icons, Option, OptionInput, Player, PluginFactory, Plugins, Setting, SettingOption, Subtitle, SubtitleUpdateEvents, Template, Utils } from './artplayer.js'
+4 -6
View File
@@ -6,6 +6,7 @@ import type { I18n } from './i18n'
import type { Icons } from './icons'
import type { Option, OptionInput } from './option'
import type { Player } from './player'
import type { PluginFactory, Plugins } from './plugin'
import type { Setting, SettingOption } from './setting'
import type { Subtitle } from './subtitle'
import type { Template } from './template'
@@ -20,6 +21,8 @@ export type {
Option,
OptionInput,
Player,
PluginFactory,
Plugins,
Setting,
SettingOption,
Subtitle,
@@ -205,10 +208,5 @@ export default class Artplayer extends Player {
remove: (name: string) => Artplayer['setting']
} & Component
readonly plugins: {
/** Legacy signature: synchronous factories return this registry directly; Promise factories return a Promise of it. */
add: (
plugin: (this: Artplayer, art: Artplayer) => unknown | Promise<unknown>,
) => Promise<Artplayer['plugins']>
} & Record<string, unknown>
readonly plugins: Plugins
}
+2 -1
View File
@@ -3,6 +3,7 @@ import type { ComponentInput, ComponentOption } from './component'
import type { CssVar } from './cssVar'
import type { I18n } from './i18n'
import type { Icons } from './icons'
import type { PluginFactory } from './plugin'
import type { Quality } from './quality'
import type { Setting } from './setting'
import type { Subtitle } from './subtitle'
@@ -240,7 +241,7 @@ export interface Option {
/**
* Custom plugin list
*/
plugins?: ((this: Artplayer, art: Artplayer) => unknown | Promise<unknown>)[]
plugins?: PluginFactory[]
/**
* Custom layer list
+10
View File
@@ -0,0 +1,10 @@
import type Artplayer from './artplayer'
export type PluginFactory<Host = Artplayer, Result = unknown> = (this: Host, art: Host) => Result
/** Augment this interface with installed plugin results; augmentation does not register a plugin. */
export interface Plugins {
/** Legacy signature: synchronous factories return this registry; Promise factories return a Promise of it. */
add: (plugin: PluginFactory) => Promise<Plugins>
[name: string]: unknown
}