@scarlett-player/core 0.1.1 → 0.1.2
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 +229 -0
- package/dist/events/event-bus.d.ts +212 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +234 -0
- package/dist/scarlett-player.d.ts +3 -2
- package/dist/scarlett-player.d.ts.map +1 -1
- package/dist/scarlett-player.js.map +1 -1
- package/dist/state/computed.d.ts +85 -0
- package/dist/state/effect.d.ts +47 -0
- package/dist/state/index.d.ts +9 -0
- package/dist/state/signal.d.ts +92 -0
- package/dist/state/state-manager.d.ts +199 -0
- package/package.json +2 -2
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErrorHandler - Centralized error handling for Scarlett Player.
|
|
3
|
+
*
|
|
4
|
+
* Provides error classification, logging, history tracking, and event emission
|
|
5
|
+
* for all player errors.
|
|
6
|
+
*
|
|
7
|
+
* Target size: ~0.4-0.6KB
|
|
8
|
+
*/
|
|
9
|
+
import type { EventBus } from './events/event-bus';
|
|
10
|
+
import type { Logger } from './logger';
|
|
11
|
+
/**
|
|
12
|
+
* Player error codes.
|
|
13
|
+
*/
|
|
14
|
+
export declare enum ErrorCode {
|
|
15
|
+
SOURCE_NOT_SUPPORTED = "SOURCE_NOT_SUPPORTED",
|
|
16
|
+
SOURCE_LOAD_FAILED = "SOURCE_LOAD_FAILED",
|
|
17
|
+
PROVIDER_NOT_FOUND = "PROVIDER_NOT_FOUND",
|
|
18
|
+
PROVIDER_SETUP_FAILED = "PROVIDER_SETUP_FAILED",
|
|
19
|
+
PLUGIN_SETUP_FAILED = "PLUGIN_SETUP_FAILED",
|
|
20
|
+
PLUGIN_NOT_FOUND = "PLUGIN_NOT_FOUND",
|
|
21
|
+
PLAYBACK_FAILED = "PLAYBACK_FAILED",
|
|
22
|
+
MEDIA_DECODE_ERROR = "MEDIA_DECODE_ERROR",
|
|
23
|
+
MEDIA_NETWORK_ERROR = "MEDIA_NETWORK_ERROR",
|
|
24
|
+
UNKNOWN_ERROR = "UNKNOWN_ERROR"
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Structured player error.
|
|
28
|
+
*/
|
|
29
|
+
export interface PlayerError {
|
|
30
|
+
/** Error code */
|
|
31
|
+
code: ErrorCode;
|
|
32
|
+
/** Error message */
|
|
33
|
+
message: string;
|
|
34
|
+
/** Whether error is fatal (unrecoverable) */
|
|
35
|
+
fatal: boolean;
|
|
36
|
+
/** Timestamp (milliseconds since epoch) */
|
|
37
|
+
timestamp: number;
|
|
38
|
+
/** Optional context (what was happening) */
|
|
39
|
+
context?: Record<string, any>;
|
|
40
|
+
/** Original error if wrapped */
|
|
41
|
+
originalError?: Error;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* ErrorHandler options.
|
|
45
|
+
*/
|
|
46
|
+
export interface ErrorHandlerOptions {
|
|
47
|
+
/** Maximum error history to keep (default: 10) */
|
|
48
|
+
maxHistory?: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* ErrorHandler manages all player errors with classification and history.
|
|
52
|
+
*
|
|
53
|
+
* Features:
|
|
54
|
+
* - Error classification (fatal vs recoverable)
|
|
55
|
+
* - Error code mapping
|
|
56
|
+
* - Error event emission
|
|
57
|
+
* - Error history tracking
|
|
58
|
+
* - Context capture
|
|
59
|
+
* - Logger integration
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const errorHandler = new ErrorHandler(eventBus, logger);
|
|
64
|
+
*
|
|
65
|
+
* // Handle native error
|
|
66
|
+
* try {
|
|
67
|
+
* // Some operation
|
|
68
|
+
* } catch (error) {
|
|
69
|
+
* errorHandler.handle(error as Error, {
|
|
70
|
+
* operation: 'loadSource',
|
|
71
|
+
* src: 'video.mp4'
|
|
72
|
+
* });
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* // Throw specific error
|
|
76
|
+
* errorHandler.throw(
|
|
77
|
+
* ErrorCode.SOURCE_NOT_SUPPORTED,
|
|
78
|
+
* 'MP4 files are not supported',
|
|
79
|
+
* { fatal: true, context: { src: 'video.mp4' } }
|
|
80
|
+
* );
|
|
81
|
+
*
|
|
82
|
+
* // Check error history
|
|
83
|
+
* const lastError = errorHandler.getLastError();
|
|
84
|
+
* const hasFatal = errorHandler.hasFatalError();
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare class ErrorHandler {
|
|
88
|
+
/** Event bus for error emission */
|
|
89
|
+
private eventBus;
|
|
90
|
+
/** Logger for error logging */
|
|
91
|
+
private logger;
|
|
92
|
+
/** Error history */
|
|
93
|
+
private errors;
|
|
94
|
+
/** Maximum history size */
|
|
95
|
+
private maxHistory;
|
|
96
|
+
/**
|
|
97
|
+
* Create a new ErrorHandler.
|
|
98
|
+
*
|
|
99
|
+
* @param eventBus - Event bus for error emission
|
|
100
|
+
* @param logger - Logger for error logging
|
|
101
|
+
* @param options - Optional configuration
|
|
102
|
+
*/
|
|
103
|
+
constructor(eventBus: EventBus, logger: Logger, options?: ErrorHandlerOptions);
|
|
104
|
+
/**
|
|
105
|
+
* Handle an error.
|
|
106
|
+
*
|
|
107
|
+
* Normalizes, logs, emits, and tracks the error.
|
|
108
|
+
*
|
|
109
|
+
* @param error - Error to handle (native or PlayerError)
|
|
110
|
+
* @param context - Optional context (what was happening)
|
|
111
|
+
* @returns Normalized PlayerError
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* try {
|
|
116
|
+
* loadVideo();
|
|
117
|
+
* } catch (error) {
|
|
118
|
+
* errorHandler.handle(error as Error, { src: 'video.mp4' });
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
handle(error: Error | PlayerError, context?: Record<string, any>): PlayerError;
|
|
123
|
+
/**
|
|
124
|
+
* Create and handle an error from code.
|
|
125
|
+
*
|
|
126
|
+
* @param code - Error code
|
|
127
|
+
* @param message - Error message
|
|
128
|
+
* @param options - Optional error options
|
|
129
|
+
* @returns Created PlayerError
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* errorHandler.throw(
|
|
134
|
+
* ErrorCode.SOURCE_NOT_SUPPORTED,
|
|
135
|
+
* 'MP4 not supported',
|
|
136
|
+
* { fatal: true, context: { type: 'video/mp4' } }
|
|
137
|
+
* );
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
throw(code: ErrorCode, message: string, options?: {
|
|
141
|
+
fatal?: boolean;
|
|
142
|
+
context?: Record<string, any>;
|
|
143
|
+
originalError?: Error;
|
|
144
|
+
}): PlayerError;
|
|
145
|
+
/**
|
|
146
|
+
* Get error history.
|
|
147
|
+
*
|
|
148
|
+
* @returns Readonly copy of error history
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* const history = errorHandler.getHistory();
|
|
153
|
+
* console.log(`${history.length} errors occurred`);
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
getHistory(): readonly PlayerError[];
|
|
157
|
+
/**
|
|
158
|
+
* Get last error that occurred.
|
|
159
|
+
*
|
|
160
|
+
* @returns Last error or null if none
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* const lastError = errorHandler.getLastError();
|
|
165
|
+
* if (lastError?.fatal) {
|
|
166
|
+
* showErrorMessage(lastError.message);
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
getLastError(): PlayerError | null;
|
|
171
|
+
/**
|
|
172
|
+
* Clear error history.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* errorHandler.clearHistory();
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
clearHistory(): void;
|
|
180
|
+
/**
|
|
181
|
+
* Check if any fatal errors occurred.
|
|
182
|
+
*
|
|
183
|
+
* @returns True if any fatal error in history
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* if (errorHandler.hasFatalError()) {
|
|
188
|
+
* player.reset();
|
|
189
|
+
* }
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
hasFatalError(): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Normalize error to PlayerError.
|
|
195
|
+
* @private
|
|
196
|
+
*/
|
|
197
|
+
private normalizeError;
|
|
198
|
+
/**
|
|
199
|
+
* Determine error code from native Error.
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
private getErrorCode;
|
|
203
|
+
/**
|
|
204
|
+
* Determine if error is fatal.
|
|
205
|
+
* @private
|
|
206
|
+
*/
|
|
207
|
+
private isFatal;
|
|
208
|
+
/**
|
|
209
|
+
* Determine if error code is fatal.
|
|
210
|
+
* @private
|
|
211
|
+
*/
|
|
212
|
+
private isFatalCode;
|
|
213
|
+
/**
|
|
214
|
+
* Type guard for PlayerError.
|
|
215
|
+
* @private
|
|
216
|
+
*/
|
|
217
|
+
private isPlayerError;
|
|
218
|
+
/**
|
|
219
|
+
* Add error to history.
|
|
220
|
+
* @private
|
|
221
|
+
*/
|
|
222
|
+
private addToHistory;
|
|
223
|
+
/**
|
|
224
|
+
* Log error with appropriate level.
|
|
225
|
+
* @private
|
|
226
|
+
*/
|
|
227
|
+
private logError;
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventBus - Type-safe event system for Scarlett Player.
|
|
3
|
+
*
|
|
4
|
+
* Provides pub/sub event communication between player components and plugins
|
|
5
|
+
* with optional interceptors for event modification/cancellation.
|
|
6
|
+
*
|
|
7
|
+
* Target size: ~1KB
|
|
8
|
+
*/
|
|
9
|
+
import type { EventName, EventPayload, EventHandler, EventInterceptor, EventEmitterOptions } from '../types/events';
|
|
10
|
+
/**
|
|
11
|
+
* EventBus provides type-safe event emission and subscription.
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Type-safe events based on PlayerEventMap
|
|
15
|
+
* - Event interceptors for modification/cancellation
|
|
16
|
+
* - One-time subscriptions with once()
|
|
17
|
+
* - Async event emission
|
|
18
|
+
* - Error handling for handlers
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const events = new EventBus();
|
|
23
|
+
*
|
|
24
|
+
* // Subscribe to event
|
|
25
|
+
* events.on('playback:play', () => {
|
|
26
|
+
* console.log('Playing!');
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Emit event
|
|
30
|
+
* events.emit('playback:play', undefined);
|
|
31
|
+
*
|
|
32
|
+
* // Intercept events
|
|
33
|
+
* events.intercept('playback:timeupdate', (payload) => {
|
|
34
|
+
* // Modify payload or return null to cancel
|
|
35
|
+
* return { currentTime: Math.floor(payload.currentTime) };
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class EventBus {
|
|
40
|
+
/** Event listeners map */
|
|
41
|
+
private listeners;
|
|
42
|
+
/** One-time listeners (removed after first call) */
|
|
43
|
+
private onceListeners;
|
|
44
|
+
/** Event interceptors map */
|
|
45
|
+
private interceptors;
|
|
46
|
+
/** Configuration options */
|
|
47
|
+
private options;
|
|
48
|
+
/**
|
|
49
|
+
* Create a new EventBus.
|
|
50
|
+
*
|
|
51
|
+
* @param options - Optional configuration
|
|
52
|
+
*/
|
|
53
|
+
constructor(options?: EventEmitterOptions);
|
|
54
|
+
/**
|
|
55
|
+
* Subscribe to an event.
|
|
56
|
+
*
|
|
57
|
+
* @param event - Event name
|
|
58
|
+
* @param handler - Event handler function
|
|
59
|
+
* @returns Unsubscribe function
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const unsub = events.on('playback:play', () => {
|
|
64
|
+
* console.log('Playing!');
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* // Later: unsubscribe
|
|
68
|
+
* unsub();
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
on<T extends EventName>(event: T, handler: EventHandler<T>): () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Subscribe to an event once (auto-unsubscribe after first call).
|
|
74
|
+
*
|
|
75
|
+
* @param event - Event name
|
|
76
|
+
* @param handler - Event handler function
|
|
77
|
+
* @returns Unsubscribe function
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* events.once('player:ready', () => {
|
|
82
|
+
* console.log('Player ready!');
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
once<T extends EventName>(event: T, handler: EventHandler<T>): () => void;
|
|
87
|
+
/**
|
|
88
|
+
* Unsubscribe from an event.
|
|
89
|
+
*
|
|
90
|
+
* @param event - Event name
|
|
91
|
+
* @param handler - Event handler function to remove
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const handler = () => console.log('Playing!');
|
|
96
|
+
* events.on('playback:play', handler);
|
|
97
|
+
* events.off('playback:play', handler);
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
off<T extends EventName>(event: T, handler: EventHandler<T>): void;
|
|
101
|
+
/**
|
|
102
|
+
* Emit an event synchronously.
|
|
103
|
+
*
|
|
104
|
+
* Runs interceptors first, then calls all handlers.
|
|
105
|
+
*
|
|
106
|
+
* @param event - Event name
|
|
107
|
+
* @param payload - Event payload
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* events.emit('playback:play', undefined);
|
|
112
|
+
* events.emit('playback:timeupdate', { currentTime: 10.5 });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
emit<T extends EventName>(event: T, payload: EventPayload<T>): void;
|
|
116
|
+
/**
|
|
117
|
+
* Emit an event asynchronously (next tick).
|
|
118
|
+
*
|
|
119
|
+
* @param event - Event name
|
|
120
|
+
* @param payload - Event payload
|
|
121
|
+
* @returns Promise that resolves when all handlers complete
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* await events.emitAsync('media:loaded', { src: 'video.mp4', type: 'video/mp4' });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
emitAsync<T extends EventName>(event: T, payload: EventPayload<T>): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Add an event interceptor.
|
|
131
|
+
*
|
|
132
|
+
* Interceptors run before handlers and can modify or cancel events.
|
|
133
|
+
*
|
|
134
|
+
* @param event - Event name
|
|
135
|
+
* @param interceptor - Interceptor function
|
|
136
|
+
* @returns Remove interceptor function
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* events.intercept('playback:timeupdate', (payload) => {
|
|
141
|
+
* // Round time to 2 decimals
|
|
142
|
+
* return { currentTime: Math.round(payload.currentTime * 100) / 100 };
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* // Cancel events
|
|
146
|
+
* events.intercept('playback:play', (payload) => {
|
|
147
|
+
* if (notReady) return null; // Cancel event
|
|
148
|
+
* return payload;
|
|
149
|
+
* });
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
intercept<T extends EventName>(event: T, interceptor: EventInterceptor<T>): () => void;
|
|
153
|
+
/**
|
|
154
|
+
* Remove all listeners for an event (or all events if no event specified).
|
|
155
|
+
*
|
|
156
|
+
* @param event - Optional event name
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* events.removeAllListeners('playback:play'); // Remove all playback:play listeners
|
|
161
|
+
* events.removeAllListeners(); // Remove ALL listeners
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
removeAllListeners(event?: EventName): void;
|
|
165
|
+
/**
|
|
166
|
+
* Get the number of listeners for an event.
|
|
167
|
+
*
|
|
168
|
+
* @param event - Event name
|
|
169
|
+
* @returns Number of listeners
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* events.listenerCount('playback:play'); // 3
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
listenerCount(event: EventName): number;
|
|
177
|
+
/**
|
|
178
|
+
* Destroy event bus and cleanup all listeners/interceptors.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* events.destroy();
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
destroy(): void;
|
|
186
|
+
/**
|
|
187
|
+
* Run interceptors synchronously.
|
|
188
|
+
* @private
|
|
189
|
+
*/
|
|
190
|
+
private runInterceptors;
|
|
191
|
+
/**
|
|
192
|
+
* Run interceptors asynchronously.
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
195
|
+
private runInterceptorsAsync;
|
|
196
|
+
/**
|
|
197
|
+
* Safely call a handler with error handling.
|
|
198
|
+
* @private
|
|
199
|
+
*/
|
|
200
|
+
private safeCallHandler;
|
|
201
|
+
/**
|
|
202
|
+
* Safely call a handler asynchronously with error handling.
|
|
203
|
+
* @private
|
|
204
|
+
*/
|
|
205
|
+
private safeCallHandlerAsync;
|
|
206
|
+
/**
|
|
207
|
+
* Check if max listeners exceeded and warn.
|
|
208
|
+
* @private
|
|
209
|
+
*/
|
|
210
|
+
private checkMaxListeners;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=event-bus.d.ts.map
|