@scarlett-player/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +300 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +407 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2271 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +272 -0
- package/dist/logger.js.map +1 -0
- package/dist/plugin-api.d.ts +147 -0
- package/dist/plugin-api.d.ts.map +1 -0
- package/dist/plugin-api.js +160 -0
- package/dist/plugin-api.js.map +1 -0
- package/dist/plugin-manager.d.ts +52 -0
- package/dist/plugin-manager.d.ts.map +1 -0
- package/dist/plugin-manager.js +224 -0
- package/dist/plugin-manager.js.map +1 -0
- package/dist/scarlett-player.d.ts +404 -0
- package/dist/scarlett-player.d.ts.map +1 -0
- package/dist/scarlett-player.js +769 -0
- package/dist/scarlett-player.js.map +1 -0
- package/dist/state/computed.d.ts.map +1 -0
- package/dist/state/computed.js +134 -0
- package/dist/state/computed.js.map +1 -0
- package/dist/state/effect.d.ts.map +1 -0
- package/dist/state/effect.js +77 -0
- package/dist/state/effect.js.map +1 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +9 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/signal.d.ts.map +1 -0
- package/dist/state/signal.js +126 -0
- package/dist/state/signal.js.map +1 -0
- package/dist/state/state-manager.d.ts.map +1 -0
- package/dist/state/state-manager.js +334 -0
- package/dist/state/state-manager.js.map +1 -0
- package/dist/types/events.d.ts +323 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +7 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/plugin.d.ts +141 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +8 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/types/state.d.ts +232 -0
- package/dist/types/state.d.ts.map +1 -0
- package/dist/types/state.js +8 -0
- package/dist/types/state.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginAPI - Scoped API surface for plugins.
|
|
3
|
+
*
|
|
4
|
+
* Wraps StateManager and EventBus to provide a controlled interface
|
|
5
|
+
* for plugins to interact with player state and events.
|
|
6
|
+
*
|
|
7
|
+
* Target size: ~0.5KB
|
|
8
|
+
*/
|
|
9
|
+
import type { StateManager } from './state/state-manager';
|
|
10
|
+
import type { EventBus } from './events/event-bus';
|
|
11
|
+
import type { Logger } from './logger';
|
|
12
|
+
import type { StateKey, StateValue, StateChangeEvent } from './types/state';
|
|
13
|
+
import type { EventName, EventPayload, EventHandler } from './types/events';
|
|
14
|
+
import type { IPluginAPI } from './types/plugin';
|
|
15
|
+
/**
|
|
16
|
+
* PluginAPI dependencies.
|
|
17
|
+
*/
|
|
18
|
+
export interface PluginAPIDeps {
|
|
19
|
+
stateManager: StateManager;
|
|
20
|
+
eventBus: EventBus;
|
|
21
|
+
logger: Logger;
|
|
22
|
+
container: HTMLElement;
|
|
23
|
+
getPlugin: <T = unknown>(id: string) => T | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* PluginAPI provides a scoped interface for plugins to interact with the player.
|
|
27
|
+
*
|
|
28
|
+
* Instead of giving plugins direct access to StateManager and EventBus,
|
|
29
|
+
* PluginAPI provides controlled methods that can be scoped, logged, and monitored.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // Inside a plugin's init() method:
|
|
34
|
+
* init(api: IPluginAPI) {
|
|
35
|
+
* // Get state
|
|
36
|
+
* const isPlaying = api.getState('playing');
|
|
37
|
+
*
|
|
38
|
+
* // Set state
|
|
39
|
+
* api.setState('volume', 0.8);
|
|
40
|
+
*
|
|
41
|
+
* // Subscribe to events
|
|
42
|
+
* const unsub = api.on('playback:play', () => {
|
|
43
|
+
* console.log('Playback started');
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* // Emit events
|
|
47
|
+
* api.emit('plugin:ready', { name: this.id });
|
|
48
|
+
*
|
|
49
|
+
* // Register cleanup
|
|
50
|
+
* api.onDestroy(unsub);
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class PluginAPI implements IPluginAPI {
|
|
55
|
+
/** Plugin ID this API belongs to */
|
|
56
|
+
readonly pluginId: string;
|
|
57
|
+
/** Player container element */
|
|
58
|
+
readonly container: HTMLElement;
|
|
59
|
+
/** Scoped logger for this plugin */
|
|
60
|
+
readonly logger: IPluginAPI['logger'];
|
|
61
|
+
/** State manager reference */
|
|
62
|
+
private stateManager;
|
|
63
|
+
/** Event bus reference */
|
|
64
|
+
private eventBus;
|
|
65
|
+
/** Function to get other plugins */
|
|
66
|
+
private getPluginFn;
|
|
67
|
+
/** Cleanup functions registered by this plugin */
|
|
68
|
+
private cleanupFns;
|
|
69
|
+
/**
|
|
70
|
+
* Create a new PluginAPI.
|
|
71
|
+
*
|
|
72
|
+
* @param pluginId - ID of the plugin this API belongs to
|
|
73
|
+
* @param deps - Dependencies (stateManager, eventBus, logger, container, getPlugin)
|
|
74
|
+
*/
|
|
75
|
+
constructor(pluginId: string, deps: PluginAPIDeps);
|
|
76
|
+
/**
|
|
77
|
+
* Get a state value.
|
|
78
|
+
*
|
|
79
|
+
* @param key - State property key
|
|
80
|
+
* @returns Current state value
|
|
81
|
+
*/
|
|
82
|
+
getState<K extends StateKey>(key: K): StateValue<K>;
|
|
83
|
+
/**
|
|
84
|
+
* Set a state value.
|
|
85
|
+
*
|
|
86
|
+
* @param key - State property key
|
|
87
|
+
* @param value - New state value
|
|
88
|
+
*/
|
|
89
|
+
setState<K extends StateKey>(key: K, value: StateValue<K>): void;
|
|
90
|
+
/**
|
|
91
|
+
* Subscribe to an event.
|
|
92
|
+
*
|
|
93
|
+
* @param event - Event name
|
|
94
|
+
* @param handler - Event handler
|
|
95
|
+
* @returns Unsubscribe function
|
|
96
|
+
*/
|
|
97
|
+
on<T extends EventName>(event: T, handler: EventHandler<T>): () => void;
|
|
98
|
+
/**
|
|
99
|
+
* Unsubscribe from an event.
|
|
100
|
+
*
|
|
101
|
+
* @param event - Event name
|
|
102
|
+
* @param handler - Event handler to remove
|
|
103
|
+
*/
|
|
104
|
+
off<T extends EventName>(event: T, handler: EventHandler<T>): void;
|
|
105
|
+
/**
|
|
106
|
+
* Emit an event.
|
|
107
|
+
*
|
|
108
|
+
* @param event - Event name
|
|
109
|
+
* @param payload - Event payload
|
|
110
|
+
*/
|
|
111
|
+
emit<T extends EventName>(event: T, payload: EventPayload<T>): void;
|
|
112
|
+
/**
|
|
113
|
+
* Get another plugin by ID (if ready).
|
|
114
|
+
*
|
|
115
|
+
* @param id - Plugin ID
|
|
116
|
+
* @returns Plugin instance or null if not found/ready
|
|
117
|
+
*/
|
|
118
|
+
getPlugin<T = unknown>(id: string): T | null;
|
|
119
|
+
/**
|
|
120
|
+
* Register a cleanup function to run when plugin is destroyed.
|
|
121
|
+
*
|
|
122
|
+
* @param cleanup - Cleanup function
|
|
123
|
+
*/
|
|
124
|
+
onDestroy(cleanup: () => void): void;
|
|
125
|
+
/**
|
|
126
|
+
* Subscribe to state changes.
|
|
127
|
+
*
|
|
128
|
+
* @param callback - Callback function called on any state change
|
|
129
|
+
* @returns Unsubscribe function
|
|
130
|
+
*/
|
|
131
|
+
subscribeToState(callback: (event: StateChangeEvent) => void): () => void;
|
|
132
|
+
/**
|
|
133
|
+
* Run all registered cleanup functions.
|
|
134
|
+
* Called by PluginManager when destroying the plugin.
|
|
135
|
+
*
|
|
136
|
+
* @internal
|
|
137
|
+
*/
|
|
138
|
+
runCleanups(): void;
|
|
139
|
+
/**
|
|
140
|
+
* Get all registered cleanup functions.
|
|
141
|
+
*
|
|
142
|
+
* @returns Array of cleanup functions
|
|
143
|
+
* @internal
|
|
144
|
+
*/
|
|
145
|
+
getCleanupFns(): Array<() => void>;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=plugin-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-api.d.ts","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,SAAU,YAAW,UAAU;IAC1C,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAEhC,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEtC,8BAA8B;IAC9B,OAAO,CAAC,YAAY,CAAe;IAEnC,0BAA0B;IAC1B,OAAO,CAAC,QAAQ,CAAW;IAE3B,oCAAoC;IACpC,OAAO,CAAC,WAAW,CAAwC;IAE3D,kDAAkD;IAClD,OAAO,CAAC,UAAU,CAAyB;IAE3C;;;;;OAKG;gBACS,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa;IAgBjD;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IAInD;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;IAIhE;;;;;;OAMG;IACH,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAIvE;;;;;OAKG;IACH,GAAG,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAIlE;;;;;OAKG;IACH,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAInE;;;;;OAKG;IACH,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAI5C;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIpC;;;;;OAKG;IACH,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAIzE;;;;;OAKG;IACH,WAAW,IAAI,IAAI;IAWnB;;;;;OAKG;IACH,aAAa,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;CAGnC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginAPI - Scoped API surface for plugins.
|
|
3
|
+
*
|
|
4
|
+
* Wraps StateManager and EventBus to provide a controlled interface
|
|
5
|
+
* for plugins to interact with player state and events.
|
|
6
|
+
*
|
|
7
|
+
* Target size: ~0.5KB
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* PluginAPI provides a scoped interface for plugins to interact with the player.
|
|
11
|
+
*
|
|
12
|
+
* Instead of giving plugins direct access to StateManager and EventBus,
|
|
13
|
+
* PluginAPI provides controlled methods that can be scoped, logged, and monitored.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* // Inside a plugin's init() method:
|
|
18
|
+
* init(api: IPluginAPI) {
|
|
19
|
+
* // Get state
|
|
20
|
+
* const isPlaying = api.getState('playing');
|
|
21
|
+
*
|
|
22
|
+
* // Set state
|
|
23
|
+
* api.setState('volume', 0.8);
|
|
24
|
+
*
|
|
25
|
+
* // Subscribe to events
|
|
26
|
+
* const unsub = api.on('playback:play', () => {
|
|
27
|
+
* console.log('Playback started');
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Emit events
|
|
31
|
+
* api.emit('plugin:ready', { name: this.id });
|
|
32
|
+
*
|
|
33
|
+
* // Register cleanup
|
|
34
|
+
* api.onDestroy(unsub);
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class PluginAPI {
|
|
39
|
+
/**
|
|
40
|
+
* Create a new PluginAPI.
|
|
41
|
+
*
|
|
42
|
+
* @param pluginId - ID of the plugin this API belongs to
|
|
43
|
+
* @param deps - Dependencies (stateManager, eventBus, logger, container, getPlugin)
|
|
44
|
+
*/
|
|
45
|
+
constructor(pluginId, deps) {
|
|
46
|
+
/** Cleanup functions registered by this plugin */
|
|
47
|
+
this.cleanupFns = [];
|
|
48
|
+
this.pluginId = pluginId;
|
|
49
|
+
this.stateManager = deps.stateManager;
|
|
50
|
+
this.eventBus = deps.eventBus;
|
|
51
|
+
this.container = deps.container;
|
|
52
|
+
this.getPluginFn = deps.getPlugin;
|
|
53
|
+
// Create scoped logger for this plugin
|
|
54
|
+
this.logger = {
|
|
55
|
+
debug: (msg, metadata) => deps.logger.debug(`[${pluginId}] ${msg}`, metadata),
|
|
56
|
+
info: (msg, metadata) => deps.logger.info(`[${pluginId}] ${msg}`, metadata),
|
|
57
|
+
warn: (msg, metadata) => deps.logger.warn(`[${pluginId}] ${msg}`, metadata),
|
|
58
|
+
error: (msg, metadata) => deps.logger.error(`[${pluginId}] ${msg}`, metadata),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get a state value.
|
|
63
|
+
*
|
|
64
|
+
* @param key - State property key
|
|
65
|
+
* @returns Current state value
|
|
66
|
+
*/
|
|
67
|
+
getState(key) {
|
|
68
|
+
return this.stateManager.getValue(key);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Set a state value.
|
|
72
|
+
*
|
|
73
|
+
* @param key - State property key
|
|
74
|
+
* @param value - New state value
|
|
75
|
+
*/
|
|
76
|
+
setState(key, value) {
|
|
77
|
+
this.stateManager.set(key, value);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Subscribe to an event.
|
|
81
|
+
*
|
|
82
|
+
* @param event - Event name
|
|
83
|
+
* @param handler - Event handler
|
|
84
|
+
* @returns Unsubscribe function
|
|
85
|
+
*/
|
|
86
|
+
on(event, handler) {
|
|
87
|
+
return this.eventBus.on(event, handler);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Unsubscribe from an event.
|
|
91
|
+
*
|
|
92
|
+
* @param event - Event name
|
|
93
|
+
* @param handler - Event handler to remove
|
|
94
|
+
*/
|
|
95
|
+
off(event, handler) {
|
|
96
|
+
this.eventBus.off(event, handler);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Emit an event.
|
|
100
|
+
*
|
|
101
|
+
* @param event - Event name
|
|
102
|
+
* @param payload - Event payload
|
|
103
|
+
*/
|
|
104
|
+
emit(event, payload) {
|
|
105
|
+
this.eventBus.emit(event, payload);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get another plugin by ID (if ready).
|
|
109
|
+
*
|
|
110
|
+
* @param id - Plugin ID
|
|
111
|
+
* @returns Plugin instance or null if not found/ready
|
|
112
|
+
*/
|
|
113
|
+
getPlugin(id) {
|
|
114
|
+
return this.getPluginFn(id);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Register a cleanup function to run when plugin is destroyed.
|
|
118
|
+
*
|
|
119
|
+
* @param cleanup - Cleanup function
|
|
120
|
+
*/
|
|
121
|
+
onDestroy(cleanup) {
|
|
122
|
+
this.cleanupFns.push(cleanup);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Subscribe to state changes.
|
|
126
|
+
*
|
|
127
|
+
* @param callback - Callback function called on any state change
|
|
128
|
+
* @returns Unsubscribe function
|
|
129
|
+
*/
|
|
130
|
+
subscribeToState(callback) {
|
|
131
|
+
return this.stateManager.subscribe(callback);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Run all registered cleanup functions.
|
|
135
|
+
* Called by PluginManager when destroying the plugin.
|
|
136
|
+
*
|
|
137
|
+
* @internal
|
|
138
|
+
*/
|
|
139
|
+
runCleanups() {
|
|
140
|
+
for (const cleanup of this.cleanupFns) {
|
|
141
|
+
try {
|
|
142
|
+
cleanup();
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
this.logger.error('Cleanup function failed', { error });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
this.cleanupFns = [];
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get all registered cleanup functions.
|
|
152
|
+
*
|
|
153
|
+
* @returns Array of cleanup functions
|
|
154
|
+
* @internal
|
|
155
|
+
*/
|
|
156
|
+
getCleanupFns() {
|
|
157
|
+
return this.cleanupFns;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=plugin-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginManager - Plugin lifecycle and dependency management with
|
|
3
|
+
* topological dependency resolution and circular dependency detection.
|
|
4
|
+
*/
|
|
5
|
+
import type { EventBus } from './events/event-bus';
|
|
6
|
+
import type { StateManager } from './state/state-manager';
|
|
7
|
+
import type { Logger } from './logger';
|
|
8
|
+
import type { Plugin, PluginState, PluginConfig } from './types/plugin';
|
|
9
|
+
export interface PluginManagerOptions {
|
|
10
|
+
container: HTMLElement;
|
|
11
|
+
}
|
|
12
|
+
export declare class PluginManager {
|
|
13
|
+
private plugins;
|
|
14
|
+
private eventBus;
|
|
15
|
+
private stateManager;
|
|
16
|
+
private logger;
|
|
17
|
+
private container;
|
|
18
|
+
constructor(eventBus: EventBus, stateManager: StateManager, logger: Logger, options: PluginManagerOptions);
|
|
19
|
+
/** Register a plugin with optional configuration. */
|
|
20
|
+
register<T extends PluginConfig>(plugin: Plugin<T>, config?: T): void;
|
|
21
|
+
/** Unregister a plugin. Destroys it first if active. */
|
|
22
|
+
unregister(id: string): Promise<void>;
|
|
23
|
+
/** Initialize all registered plugins in dependency order. */
|
|
24
|
+
initAll(): Promise<void>;
|
|
25
|
+
/** Initialize a specific plugin. */
|
|
26
|
+
initPlugin(id: string): Promise<void>;
|
|
27
|
+
/** Destroy all plugins in reverse dependency order. */
|
|
28
|
+
destroyAll(): Promise<void>;
|
|
29
|
+
/** Destroy a specific plugin. */
|
|
30
|
+
destroyPlugin(id: string): Promise<void>;
|
|
31
|
+
/** Get a plugin by ID (returns any registered plugin). */
|
|
32
|
+
getPlugin<T extends Plugin = Plugin>(id: string): T | null;
|
|
33
|
+
/** Get a plugin by ID only if ready (used by PluginAPI). */
|
|
34
|
+
getReadyPlugin<T extends Plugin = Plugin>(id: string): T | null;
|
|
35
|
+
/** Check if a plugin is registered. */
|
|
36
|
+
hasPlugin(id: string): boolean;
|
|
37
|
+
/** Get plugin state. */
|
|
38
|
+
getPluginState(id: string): PluginState | null;
|
|
39
|
+
/** Get all registered plugin IDs. */
|
|
40
|
+
getPluginIds(): string[];
|
|
41
|
+
/** Get all ready plugins. */
|
|
42
|
+
getReadyPlugins(): Plugin[];
|
|
43
|
+
/** Get plugins by type. */
|
|
44
|
+
getPluginsByType(type: string): Plugin[];
|
|
45
|
+
/** Select a provider plugin that can play a source. */
|
|
46
|
+
selectProvider(source: string): Plugin | null;
|
|
47
|
+
/** Resolve plugin initialization order using topological sort. */
|
|
48
|
+
private resolveDependencyOrder;
|
|
49
|
+
/** Validate plugin has required properties. */
|
|
50
|
+
private validatePlugin;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=plugin-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../src/plugin-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAG1F,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,WAAW,CAAC;CACxB;AAOD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAc;gBAG7B,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,oBAAoB;IAQ/B,qDAAqD;IACrD,QAAQ,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI;IA2BrE,wDAAwD;IAClD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3C,6DAA6D;IACvD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B,oCAAoC;IAC9B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmD3C,uDAAuD;IACjD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC,iCAAiC;IAC3B,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9C,0DAA0D;IAC1D,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAK1D,4DAA4D;IAC5D,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAK/D,uCAAuC;IACvC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI9B,wBAAwB;IACxB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAI9C,qCAAqC;IACrC,YAAY,IAAI,MAAM,EAAE;IAIxB,6BAA6B;IAC7B,eAAe,IAAI,MAAM,EAAE;IAM3B,2BAA2B;IAC3B,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAMxC,uDAAuD;IACvD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAW7C,kEAAkE;IAClE,OAAO,CAAC,sBAAsB;IAoC9B,+CAA+C;IAC/C,OAAO,CAAC,cAAc;CAoBvB"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginManager - Plugin lifecycle and dependency management with
|
|
3
|
+
* topological dependency resolution and circular dependency detection.
|
|
4
|
+
*/
|
|
5
|
+
import { PluginAPI } from './plugin-api';
|
|
6
|
+
export class PluginManager {
|
|
7
|
+
constructor(eventBus, stateManager, logger, options) {
|
|
8
|
+
this.plugins = new Map();
|
|
9
|
+
this.eventBus = eventBus;
|
|
10
|
+
this.stateManager = stateManager;
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
this.container = options.container;
|
|
13
|
+
}
|
|
14
|
+
/** Register a plugin with optional configuration. */
|
|
15
|
+
register(plugin, config) {
|
|
16
|
+
if (this.plugins.has(plugin.id)) {
|
|
17
|
+
throw new Error(`Plugin "${plugin.id}" is already registered`);
|
|
18
|
+
}
|
|
19
|
+
this.validatePlugin(plugin);
|
|
20
|
+
const api = new PluginAPI(plugin.id, {
|
|
21
|
+
stateManager: this.stateManager,
|
|
22
|
+
eventBus: this.eventBus,
|
|
23
|
+
logger: this.logger,
|
|
24
|
+
container: this.container,
|
|
25
|
+
getPlugin: (id) => this.getReadyPlugin(id),
|
|
26
|
+
});
|
|
27
|
+
this.plugins.set(plugin.id, {
|
|
28
|
+
plugin,
|
|
29
|
+
state: 'registered',
|
|
30
|
+
config,
|
|
31
|
+
cleanupFns: [],
|
|
32
|
+
api,
|
|
33
|
+
});
|
|
34
|
+
this.logger.info(`Plugin registered: ${plugin.id}`);
|
|
35
|
+
this.eventBus.emit('plugin:registered', { name: plugin.id, type: plugin.type });
|
|
36
|
+
}
|
|
37
|
+
/** Unregister a plugin. Destroys it first if active. */
|
|
38
|
+
async unregister(id) {
|
|
39
|
+
const record = this.plugins.get(id);
|
|
40
|
+
if (!record)
|
|
41
|
+
return;
|
|
42
|
+
if (record.state === 'ready') {
|
|
43
|
+
await this.destroyPlugin(id);
|
|
44
|
+
}
|
|
45
|
+
this.plugins.delete(id);
|
|
46
|
+
this.logger.info(`Plugin unregistered: ${id}`);
|
|
47
|
+
}
|
|
48
|
+
/** Initialize all registered plugins in dependency order. */
|
|
49
|
+
async initAll() {
|
|
50
|
+
const order = this.resolveDependencyOrder();
|
|
51
|
+
for (const id of order) {
|
|
52
|
+
await this.initPlugin(id);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Initialize a specific plugin. */
|
|
56
|
+
async initPlugin(id) {
|
|
57
|
+
const record = this.plugins.get(id);
|
|
58
|
+
if (!record) {
|
|
59
|
+
throw new Error(`Plugin "${id}" not found`);
|
|
60
|
+
}
|
|
61
|
+
if (record.state === 'ready')
|
|
62
|
+
return;
|
|
63
|
+
if (record.state === 'initializing') {
|
|
64
|
+
throw new Error(`Plugin "${id}" is already initializing (possible circular dependency)`);
|
|
65
|
+
}
|
|
66
|
+
// Ensure dependencies are ready
|
|
67
|
+
for (const depId of record.plugin.dependencies || []) {
|
|
68
|
+
const dep = this.plugins.get(depId);
|
|
69
|
+
if (!dep) {
|
|
70
|
+
throw new Error(`Plugin "${id}" depends on missing plugin "${depId}"`);
|
|
71
|
+
}
|
|
72
|
+
if (dep.state !== 'ready') {
|
|
73
|
+
await this.initPlugin(depId);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
record.state = 'initializing';
|
|
78
|
+
if (record.plugin.onStateChange) {
|
|
79
|
+
const unsub = this.stateManager.subscribe(record.plugin.onStateChange.bind(record.plugin));
|
|
80
|
+
record.api.onDestroy(unsub);
|
|
81
|
+
}
|
|
82
|
+
if (record.plugin.onError) {
|
|
83
|
+
const unsub = this.eventBus.on('error', (err) => {
|
|
84
|
+
record.plugin.onError?.(err.originalError || new Error(err.message));
|
|
85
|
+
});
|
|
86
|
+
record.api.onDestroy(unsub);
|
|
87
|
+
}
|
|
88
|
+
await record.plugin.init(record.api, record.config);
|
|
89
|
+
record.state = 'ready';
|
|
90
|
+
this.logger.info(`Plugin ready: ${id}`);
|
|
91
|
+
this.eventBus.emit('plugin:active', { name: id });
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
record.state = 'error';
|
|
95
|
+
record.error = error;
|
|
96
|
+
this.logger.error(`Plugin init failed: ${id}`, { error });
|
|
97
|
+
this.eventBus.emit('plugin:error', { name: id, error: error });
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Destroy all plugins in reverse dependency order. */
|
|
102
|
+
async destroyAll() {
|
|
103
|
+
const order = this.resolveDependencyOrder().reverse();
|
|
104
|
+
for (const id of order) {
|
|
105
|
+
await this.destroyPlugin(id);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Destroy a specific plugin. */
|
|
109
|
+
async destroyPlugin(id) {
|
|
110
|
+
const record = this.plugins.get(id);
|
|
111
|
+
if (!record || record.state !== 'ready')
|
|
112
|
+
return;
|
|
113
|
+
try {
|
|
114
|
+
await record.plugin.destroy();
|
|
115
|
+
record.api.runCleanups();
|
|
116
|
+
// Reset to 'registered' so it can be re-initialized later
|
|
117
|
+
record.state = 'registered';
|
|
118
|
+
this.logger.info(`Plugin destroyed: ${id}`);
|
|
119
|
+
this.eventBus.emit('plugin:destroyed', { name: id });
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.logger.error(`Plugin destroy failed: ${id}`, { error });
|
|
123
|
+
// Even on error, reset state so plugin can be retried
|
|
124
|
+
record.state = 'registered';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** Get a plugin by ID (returns any registered plugin). */
|
|
128
|
+
getPlugin(id) {
|
|
129
|
+
const record = this.plugins.get(id);
|
|
130
|
+
return record ? record.plugin : null;
|
|
131
|
+
}
|
|
132
|
+
/** Get a plugin by ID only if ready (used by PluginAPI). */
|
|
133
|
+
getReadyPlugin(id) {
|
|
134
|
+
const record = this.plugins.get(id);
|
|
135
|
+
return record?.state === 'ready' ? record.plugin : null;
|
|
136
|
+
}
|
|
137
|
+
/** Check if a plugin is registered. */
|
|
138
|
+
hasPlugin(id) {
|
|
139
|
+
return this.plugins.has(id);
|
|
140
|
+
}
|
|
141
|
+
/** Get plugin state. */
|
|
142
|
+
getPluginState(id) {
|
|
143
|
+
return this.plugins.get(id)?.state ?? null;
|
|
144
|
+
}
|
|
145
|
+
/** Get all registered plugin IDs. */
|
|
146
|
+
getPluginIds() {
|
|
147
|
+
return Array.from(this.plugins.keys());
|
|
148
|
+
}
|
|
149
|
+
/** Get all ready plugins. */
|
|
150
|
+
getReadyPlugins() {
|
|
151
|
+
return Array.from(this.plugins.values())
|
|
152
|
+
.filter((r) => r.state === 'ready')
|
|
153
|
+
.map((r) => r.plugin);
|
|
154
|
+
}
|
|
155
|
+
/** Get plugins by type. */
|
|
156
|
+
getPluginsByType(type) {
|
|
157
|
+
return Array.from(this.plugins.values())
|
|
158
|
+
.filter((r) => r.plugin.type === type)
|
|
159
|
+
.map((r) => r.plugin);
|
|
160
|
+
}
|
|
161
|
+
/** Select a provider plugin that can play a source. */
|
|
162
|
+
selectProvider(source) {
|
|
163
|
+
const providers = this.getPluginsByType('provider');
|
|
164
|
+
for (const provider of providers) {
|
|
165
|
+
const canPlay = provider.canPlay;
|
|
166
|
+
if (typeof canPlay === 'function' && canPlay(source)) {
|
|
167
|
+
return provider;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
/** Resolve plugin initialization order using topological sort. */
|
|
173
|
+
resolveDependencyOrder() {
|
|
174
|
+
const visited = new Set();
|
|
175
|
+
const visiting = new Set();
|
|
176
|
+
const sorted = [];
|
|
177
|
+
const visit = (id, path = []) => {
|
|
178
|
+
if (visited.has(id))
|
|
179
|
+
return;
|
|
180
|
+
if (visiting.has(id)) {
|
|
181
|
+
const cycle = [...path, id].join(' -> ');
|
|
182
|
+
throw new Error(`Circular dependency detected: ${cycle}`);
|
|
183
|
+
}
|
|
184
|
+
const record = this.plugins.get(id);
|
|
185
|
+
if (!record)
|
|
186
|
+
return;
|
|
187
|
+
visiting.add(id);
|
|
188
|
+
for (const depId of record.plugin.dependencies || []) {
|
|
189
|
+
if (this.plugins.has(depId)) {
|
|
190
|
+
visit(depId, [...path, id]);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
visiting.delete(id);
|
|
194
|
+
visited.add(id);
|
|
195
|
+
sorted.push(id);
|
|
196
|
+
};
|
|
197
|
+
for (const id of this.plugins.keys()) {
|
|
198
|
+
visit(id);
|
|
199
|
+
}
|
|
200
|
+
return sorted;
|
|
201
|
+
}
|
|
202
|
+
/** Validate plugin has required properties. */
|
|
203
|
+
validatePlugin(plugin) {
|
|
204
|
+
if (!plugin.id || typeof plugin.id !== 'string') {
|
|
205
|
+
throw new Error('Plugin must have a valid id');
|
|
206
|
+
}
|
|
207
|
+
if (!plugin.name || typeof plugin.name !== 'string') {
|
|
208
|
+
throw new Error(`Plugin "${plugin.id}" must have a valid name`);
|
|
209
|
+
}
|
|
210
|
+
if (!plugin.version || typeof plugin.version !== 'string') {
|
|
211
|
+
throw new Error(`Plugin "${plugin.id}" must have a valid version`);
|
|
212
|
+
}
|
|
213
|
+
if (!plugin.type || typeof plugin.type !== 'string') {
|
|
214
|
+
throw new Error(`Plugin "${plugin.id}" must have a valid type`);
|
|
215
|
+
}
|
|
216
|
+
if (typeof plugin.init !== 'function') {
|
|
217
|
+
throw new Error(`Plugin "${plugin.id}" must have an init() method`);
|
|
218
|
+
}
|
|
219
|
+
if (typeof plugin.destroy !== 'function') {
|
|
220
|
+
throw new Error(`Plugin "${plugin.id}" must have a destroy() method`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=plugin-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-manager.js","sourceRoot":"","sources":["../src/plugin-manager.ts"],"names":[],"mappings":"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"}
|