@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.
Files changed (59) hide show
  1. package/dist/error-handler.d.ts.map +1 -0
  2. package/dist/error-handler.js +300 -0
  3. package/dist/error-handler.js.map +1 -0
  4. package/dist/events/event-bus.d.ts.map +1 -0
  5. package/dist/events/event-bus.js +407 -0
  6. package/dist/events/event-bus.js.map +1 -0
  7. package/dist/index.cjs +2 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.d.ts +16 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +2271 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/logger.d.ts.map +1 -0
  14. package/dist/logger.js +272 -0
  15. package/dist/logger.js.map +1 -0
  16. package/dist/plugin-api.d.ts +147 -0
  17. package/dist/plugin-api.d.ts.map +1 -0
  18. package/dist/plugin-api.js +160 -0
  19. package/dist/plugin-api.js.map +1 -0
  20. package/dist/plugin-manager.d.ts +52 -0
  21. package/dist/plugin-manager.d.ts.map +1 -0
  22. package/dist/plugin-manager.js +224 -0
  23. package/dist/plugin-manager.js.map +1 -0
  24. package/dist/scarlett-player.d.ts +404 -0
  25. package/dist/scarlett-player.d.ts.map +1 -0
  26. package/dist/scarlett-player.js +769 -0
  27. package/dist/scarlett-player.js.map +1 -0
  28. package/dist/state/computed.d.ts.map +1 -0
  29. package/dist/state/computed.js +134 -0
  30. package/dist/state/computed.js.map +1 -0
  31. package/dist/state/effect.d.ts.map +1 -0
  32. package/dist/state/effect.js +77 -0
  33. package/dist/state/effect.js.map +1 -0
  34. package/dist/state/index.d.ts.map +1 -0
  35. package/dist/state/index.js +9 -0
  36. package/dist/state/index.js.map +1 -0
  37. package/dist/state/signal.d.ts.map +1 -0
  38. package/dist/state/signal.js +126 -0
  39. package/dist/state/signal.js.map +1 -0
  40. package/dist/state/state-manager.d.ts.map +1 -0
  41. package/dist/state/state-manager.js +334 -0
  42. package/dist/state/state-manager.js.map +1 -0
  43. package/dist/types/events.d.ts +323 -0
  44. package/dist/types/events.d.ts.map +1 -0
  45. package/dist/types/events.js +7 -0
  46. package/dist/types/events.js.map +1 -0
  47. package/dist/types/index.d.ts +9 -0
  48. package/dist/types/index.d.ts.map +1 -0
  49. package/dist/types/index.js +7 -0
  50. package/dist/types/index.js.map +1 -0
  51. package/dist/types/plugin.d.ts +141 -0
  52. package/dist/types/plugin.d.ts.map +1 -0
  53. package/dist/types/plugin.js +8 -0
  54. package/dist/types/plugin.js.map +1 -0
  55. package/dist/types/state.d.ts +232 -0
  56. package/dist/types/state.d.ts.map +1 -0
  57. package/dist/types/state.js +8 -0
  58. package/dist/types/state.js.map +1 -0
  59. 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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"}