@scalemule/gallop 0.0.1

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.
@@ -0,0 +1,235 @@
1
+ interface GallopConfig {
2
+ /** ScaleMule video ID — loads video metadata from API */
3
+ videoId?: string;
4
+ /** ScaleMule API key for authenticated requests */
5
+ apiKey?: string;
6
+ /** Direct HLS source URL (alternative to videoId) */
7
+ src?: string;
8
+ /** Poster image URL shown before playback */
9
+ poster?: string;
10
+ /** Base URL for the ScaleMule API */
11
+ apiBaseUrl?: string;
12
+ /** Show built-in controls (default: true) */
13
+ controls?: boolean;
14
+ /** Autoplay on load (default: false) */
15
+ autoplay?: boolean;
16
+ /** Loop playback (default: false) */
17
+ loop?: boolean;
18
+ /** Start muted (default: false) */
19
+ muted?: boolean;
20
+ /** Start time in seconds */
21
+ startTime?: number;
22
+ /** Preferred initial quality level ('auto' or height like 720) */
23
+ preferredQuality?: 'auto' | number;
24
+ /** Theme overrides */
25
+ theme?: Partial<GallopTheme>;
26
+ /** Enable keyboard shortcuts (default: true) */
27
+ keyboard?: boolean;
28
+ /** Enable touch gestures (default: true) */
29
+ touch?: boolean;
30
+ /** Player aspect ratio (default: '16:9') */
31
+ aspectRatio?: string;
32
+ /** hls.js config overrides */
33
+ hlsConfig?: Record<string, unknown>;
34
+ /** CSP nonce applied to the injected &lt;style&gt; tag (required for strict style-src policies) */
35
+ nonce?: string;
36
+ /** Playback analytics and debugging telemetry settings */
37
+ analytics?: GallopAnalyticsConfig;
38
+ /** Enable debug mode (default: false) */
39
+ debug?: boolean;
40
+ /** Player mode: 'inline' (default), 'iframe', or 'auto' */
41
+ mode?: 'inline' | 'iframe' | 'auto';
42
+ /** Embed token for iframe mode (signed JWT) */
43
+ embedToken?: string;
44
+ /** Disable all analytics + local storage (default: false) */
45
+ doNotTrack?: boolean;
46
+ /** Host page URL — passed to context menu for "Copy link" / "Report a problem" */
47
+ pageUrl?: string;
48
+ }
49
+ interface GallopDiagnostics {
50
+ version: string;
51
+ mode: 'inline' | 'iframe';
52
+ engineType: string;
53
+ bitrate: number;
54
+ bufferLength: number;
55
+ fps: number;
56
+ droppedFrames: number;
57
+ totalFrames: number;
58
+ status: PlayerStatus;
59
+ isMuted: boolean;
60
+ volume: number;
61
+ playbackRate: number;
62
+ currentTime: number;
63
+ duration: number;
64
+ nonceStatus: string;
65
+ cspStatus: string;
66
+ }
67
+ interface GallopQueryMap {
68
+ currentTime: number;
69
+ duration: number;
70
+ volume: number;
71
+ muted: boolean;
72
+ playbackRate: number;
73
+ status: PlayerStatus;
74
+ isFullscreen: boolean;
75
+ currentQuality: number;
76
+ qualityLevels: QualityLevel[];
77
+ diagnostics: GallopDiagnostics;
78
+ }
79
+ interface GallopAnalyticsConfig {
80
+ /** Enable telemetry dispatch (default: true when apiKey and videoId are available) */
81
+ enabled?: boolean;
82
+ /** Override video ID used for telemetry (useful when loading src directly) */
83
+ videoId?: string;
84
+ /** Stable session identifier used for deduplicating playback sessions */
85
+ sessionId?: string;
86
+ /** Queue flush interval for telemetry events */
87
+ flushIntervalMs?: number;
88
+ /** Maximum number of events sent per flush cycle */
89
+ maxBatchSize?: number;
90
+ /** Maximum number of queued events before dropping oldest entries */
91
+ maxQueueSize?: number;
92
+ /** Seconds between heartbeat progress events */
93
+ progressIntervalSeconds?: number;
94
+ /** Include navigator.connection metrics when available */
95
+ includeNetworkInfo?: boolean;
96
+ /** Include browser/device context metrics when available */
97
+ includeDeviceInfo?: boolean;
98
+ /** Track if player is in viewport using IntersectionObserver (default: true) */
99
+ trackVisibility?: boolean;
100
+ /** Additional metadata attached to all events */
101
+ metadata?: Record<string, unknown>;
102
+ /** Enable console debug logs for telemetry internals */
103
+ debug?: boolean;
104
+ }
105
+ interface GallopTheme {
106
+ colorPrimary: string;
107
+ colorSecondary: string;
108
+ colorText: string;
109
+ colorBackground: string;
110
+ colorBuffered: string;
111
+ colorProgress: string;
112
+ controlBarBackground: string;
113
+ controlBarHeight: string;
114
+ borderRadius: string;
115
+ fontFamily: string;
116
+ fontSize: string;
117
+ iconSize: string;
118
+ }
119
+ interface QualityLevel {
120
+ index: number;
121
+ height: number;
122
+ width: number;
123
+ bitrate: number;
124
+ label: string;
125
+ active: boolean;
126
+ }
127
+ interface VideoMetadata {
128
+ id: string;
129
+ title: string;
130
+ duration: number;
131
+ poster?: string;
132
+ playlistUrl: string;
133
+ qualities: QualityLevel[];
134
+ }
135
+ type PlayerStatus = 'idle' | 'loading' | 'ready' | 'playing' | 'paused' | 'buffering' | 'ended' | 'error';
136
+ interface GallopEventMap {
137
+ play: void;
138
+ pause: void;
139
+ ended: void;
140
+ timeupdate: {
141
+ currentTime: number;
142
+ duration: number;
143
+ };
144
+ volumechange: {
145
+ volume: number;
146
+ muted: boolean;
147
+ };
148
+ qualitychange: {
149
+ level: QualityLevel;
150
+ };
151
+ enginestats: {
152
+ stats: GallopEngineStats;
153
+ };
154
+ qualitylevels: {
155
+ levels: QualityLevel[];
156
+ };
157
+ ratechange: {
158
+ rate: number;
159
+ };
160
+ seeked: {
161
+ time: number;
162
+ };
163
+ buffering: {
164
+ isBuffering: boolean;
165
+ };
166
+ error: {
167
+ code: string;
168
+ message: string;
169
+ };
170
+ statuschange: {
171
+ status: PlayerStatus;
172
+ };
173
+ fullscreenchange: {
174
+ isFullscreen: boolean;
175
+ };
176
+ ready: void;
177
+ destroy: void;
178
+ }
179
+ interface GallopEngineStats {
180
+ kind: 'fragment' | 'level_switch' | 'hls_error' | 'periodic';
181
+ /** Identifies which engine produced this stat: 'hlsjs' or 'native_resource_timing' */
182
+ statsSource?: 'hlsjs' | 'native_resource_timing';
183
+ bandwidthEstimate?: number;
184
+ level?: number;
185
+ fragmentDuration?: number;
186
+ fragmentSizeBytes?: number;
187
+ fragmentLoadMs?: number;
188
+ cdnNode?: string;
189
+ cdnCacheStatus?: string;
190
+ cdnRequestID?: string;
191
+ droppedFrames?: number;
192
+ totalFrames?: number;
193
+ /** Whether Timing-Allow-Origin was present on cross-origin fragment responses (false = transferSize/bandwidth unavailable) */
194
+ taoAvailable?: boolean;
195
+ fatal?: boolean;
196
+ errorType?: string;
197
+ errorDetails?: string;
198
+ }
199
+ type GallopEventCallback<T> = T extends void ? () => void : (data: T) => void;
200
+ interface GallopPlayer {
201
+ readonly currentTime: number;
202
+ readonly duration: number;
203
+ readonly paused: boolean;
204
+ volume: number;
205
+ muted: boolean;
206
+ playbackRate: number;
207
+ readonly status: PlayerStatus;
208
+ readonly isFullscreen: boolean;
209
+ play(): Promise<void>;
210
+ pause(): Promise<void>;
211
+ seek(time: number): Promise<void>;
212
+ setQualityLevel(index: number): Promise<void>;
213
+ setAutoQuality(): Promise<void>;
214
+ toggleFullscreen(): Promise<void>;
215
+ destroy(): void;
216
+ getQualityLevels(): QualityLevel[];
217
+ getCurrentQuality(): number;
218
+ getDiagnostics(): GallopDiagnostics;
219
+ query<K extends keyof GallopQueryMap>(key: K): Promise<GallopQueryMap[K]>;
220
+ on<K extends keyof GallopEventMap>(event: K, cb: GallopEventCallback<GallopEventMap[K]>): void;
221
+ off<K extends keyof GallopEventMap>(event: K, cb: GallopEventCallback<GallopEventMap[K]>): void;
222
+ }
223
+ interface StreamingEngine {
224
+ load(url: string, videoElement: HTMLVideoElement): void;
225
+ destroy(): void;
226
+ getQualityLevels(): QualityLevel[];
227
+ setQualityLevel(index: number): void;
228
+ getCurrentQuality(): number;
229
+ isAutoQuality(): boolean;
230
+ setAutoQuality(): void;
231
+ on<K extends string>(event: K, callback: (...args: unknown[]) => void): void;
232
+ off<K extends string>(event: K, callback: (...args: unknown[]) => void): void;
233
+ }
234
+
235
+ export type { GallopQueryMap as G, PlayerStatus as P, QualityLevel as Q, StreamingEngine as S, VideoMetadata as V, GallopDiagnostics as a, GallopConfig as b, GallopEventCallback as c, GallopEventMap as d, GallopPlayer as e, GallopTheme as f };
@@ -0,0 +1,235 @@
1
+ interface GallopConfig {
2
+ /** ScaleMule video ID — loads video metadata from API */
3
+ videoId?: string;
4
+ /** ScaleMule API key for authenticated requests */
5
+ apiKey?: string;
6
+ /** Direct HLS source URL (alternative to videoId) */
7
+ src?: string;
8
+ /** Poster image URL shown before playback */
9
+ poster?: string;
10
+ /** Base URL for the ScaleMule API */
11
+ apiBaseUrl?: string;
12
+ /** Show built-in controls (default: true) */
13
+ controls?: boolean;
14
+ /** Autoplay on load (default: false) */
15
+ autoplay?: boolean;
16
+ /** Loop playback (default: false) */
17
+ loop?: boolean;
18
+ /** Start muted (default: false) */
19
+ muted?: boolean;
20
+ /** Start time in seconds */
21
+ startTime?: number;
22
+ /** Preferred initial quality level ('auto' or height like 720) */
23
+ preferredQuality?: 'auto' | number;
24
+ /** Theme overrides */
25
+ theme?: Partial<GallopTheme>;
26
+ /** Enable keyboard shortcuts (default: true) */
27
+ keyboard?: boolean;
28
+ /** Enable touch gestures (default: true) */
29
+ touch?: boolean;
30
+ /** Player aspect ratio (default: '16:9') */
31
+ aspectRatio?: string;
32
+ /** hls.js config overrides */
33
+ hlsConfig?: Record<string, unknown>;
34
+ /** CSP nonce applied to the injected &lt;style&gt; tag (required for strict style-src policies) */
35
+ nonce?: string;
36
+ /** Playback analytics and debugging telemetry settings */
37
+ analytics?: GallopAnalyticsConfig;
38
+ /** Enable debug mode (default: false) */
39
+ debug?: boolean;
40
+ /** Player mode: 'inline' (default), 'iframe', or 'auto' */
41
+ mode?: 'inline' | 'iframe' | 'auto';
42
+ /** Embed token for iframe mode (signed JWT) */
43
+ embedToken?: string;
44
+ /** Disable all analytics + local storage (default: false) */
45
+ doNotTrack?: boolean;
46
+ /** Host page URL — passed to context menu for "Copy link" / "Report a problem" */
47
+ pageUrl?: string;
48
+ }
49
+ interface GallopDiagnostics {
50
+ version: string;
51
+ mode: 'inline' | 'iframe';
52
+ engineType: string;
53
+ bitrate: number;
54
+ bufferLength: number;
55
+ fps: number;
56
+ droppedFrames: number;
57
+ totalFrames: number;
58
+ status: PlayerStatus;
59
+ isMuted: boolean;
60
+ volume: number;
61
+ playbackRate: number;
62
+ currentTime: number;
63
+ duration: number;
64
+ nonceStatus: string;
65
+ cspStatus: string;
66
+ }
67
+ interface GallopQueryMap {
68
+ currentTime: number;
69
+ duration: number;
70
+ volume: number;
71
+ muted: boolean;
72
+ playbackRate: number;
73
+ status: PlayerStatus;
74
+ isFullscreen: boolean;
75
+ currentQuality: number;
76
+ qualityLevels: QualityLevel[];
77
+ diagnostics: GallopDiagnostics;
78
+ }
79
+ interface GallopAnalyticsConfig {
80
+ /** Enable telemetry dispatch (default: true when apiKey and videoId are available) */
81
+ enabled?: boolean;
82
+ /** Override video ID used for telemetry (useful when loading src directly) */
83
+ videoId?: string;
84
+ /** Stable session identifier used for deduplicating playback sessions */
85
+ sessionId?: string;
86
+ /** Queue flush interval for telemetry events */
87
+ flushIntervalMs?: number;
88
+ /** Maximum number of events sent per flush cycle */
89
+ maxBatchSize?: number;
90
+ /** Maximum number of queued events before dropping oldest entries */
91
+ maxQueueSize?: number;
92
+ /** Seconds between heartbeat progress events */
93
+ progressIntervalSeconds?: number;
94
+ /** Include navigator.connection metrics when available */
95
+ includeNetworkInfo?: boolean;
96
+ /** Include browser/device context metrics when available */
97
+ includeDeviceInfo?: boolean;
98
+ /** Track if player is in viewport using IntersectionObserver (default: true) */
99
+ trackVisibility?: boolean;
100
+ /** Additional metadata attached to all events */
101
+ metadata?: Record<string, unknown>;
102
+ /** Enable console debug logs for telemetry internals */
103
+ debug?: boolean;
104
+ }
105
+ interface GallopTheme {
106
+ colorPrimary: string;
107
+ colorSecondary: string;
108
+ colorText: string;
109
+ colorBackground: string;
110
+ colorBuffered: string;
111
+ colorProgress: string;
112
+ controlBarBackground: string;
113
+ controlBarHeight: string;
114
+ borderRadius: string;
115
+ fontFamily: string;
116
+ fontSize: string;
117
+ iconSize: string;
118
+ }
119
+ interface QualityLevel {
120
+ index: number;
121
+ height: number;
122
+ width: number;
123
+ bitrate: number;
124
+ label: string;
125
+ active: boolean;
126
+ }
127
+ interface VideoMetadata {
128
+ id: string;
129
+ title: string;
130
+ duration: number;
131
+ poster?: string;
132
+ playlistUrl: string;
133
+ qualities: QualityLevel[];
134
+ }
135
+ type PlayerStatus = 'idle' | 'loading' | 'ready' | 'playing' | 'paused' | 'buffering' | 'ended' | 'error';
136
+ interface GallopEventMap {
137
+ play: void;
138
+ pause: void;
139
+ ended: void;
140
+ timeupdate: {
141
+ currentTime: number;
142
+ duration: number;
143
+ };
144
+ volumechange: {
145
+ volume: number;
146
+ muted: boolean;
147
+ };
148
+ qualitychange: {
149
+ level: QualityLevel;
150
+ };
151
+ enginestats: {
152
+ stats: GallopEngineStats;
153
+ };
154
+ qualitylevels: {
155
+ levels: QualityLevel[];
156
+ };
157
+ ratechange: {
158
+ rate: number;
159
+ };
160
+ seeked: {
161
+ time: number;
162
+ };
163
+ buffering: {
164
+ isBuffering: boolean;
165
+ };
166
+ error: {
167
+ code: string;
168
+ message: string;
169
+ };
170
+ statuschange: {
171
+ status: PlayerStatus;
172
+ };
173
+ fullscreenchange: {
174
+ isFullscreen: boolean;
175
+ };
176
+ ready: void;
177
+ destroy: void;
178
+ }
179
+ interface GallopEngineStats {
180
+ kind: 'fragment' | 'level_switch' | 'hls_error' | 'periodic';
181
+ /** Identifies which engine produced this stat: 'hlsjs' or 'native_resource_timing' */
182
+ statsSource?: 'hlsjs' | 'native_resource_timing';
183
+ bandwidthEstimate?: number;
184
+ level?: number;
185
+ fragmentDuration?: number;
186
+ fragmentSizeBytes?: number;
187
+ fragmentLoadMs?: number;
188
+ cdnNode?: string;
189
+ cdnCacheStatus?: string;
190
+ cdnRequestID?: string;
191
+ droppedFrames?: number;
192
+ totalFrames?: number;
193
+ /** Whether Timing-Allow-Origin was present on cross-origin fragment responses (false = transferSize/bandwidth unavailable) */
194
+ taoAvailable?: boolean;
195
+ fatal?: boolean;
196
+ errorType?: string;
197
+ errorDetails?: string;
198
+ }
199
+ type GallopEventCallback<T> = T extends void ? () => void : (data: T) => void;
200
+ interface GallopPlayer {
201
+ readonly currentTime: number;
202
+ readonly duration: number;
203
+ readonly paused: boolean;
204
+ volume: number;
205
+ muted: boolean;
206
+ playbackRate: number;
207
+ readonly status: PlayerStatus;
208
+ readonly isFullscreen: boolean;
209
+ play(): Promise<void>;
210
+ pause(): Promise<void>;
211
+ seek(time: number): Promise<void>;
212
+ setQualityLevel(index: number): Promise<void>;
213
+ setAutoQuality(): Promise<void>;
214
+ toggleFullscreen(): Promise<void>;
215
+ destroy(): void;
216
+ getQualityLevels(): QualityLevel[];
217
+ getCurrentQuality(): number;
218
+ getDiagnostics(): GallopDiagnostics;
219
+ query<K extends keyof GallopQueryMap>(key: K): Promise<GallopQueryMap[K]>;
220
+ on<K extends keyof GallopEventMap>(event: K, cb: GallopEventCallback<GallopEventMap[K]>): void;
221
+ off<K extends keyof GallopEventMap>(event: K, cb: GallopEventCallback<GallopEventMap[K]>): void;
222
+ }
223
+ interface StreamingEngine {
224
+ load(url: string, videoElement: HTMLVideoElement): void;
225
+ destroy(): void;
226
+ getQualityLevels(): QualityLevel[];
227
+ setQualityLevel(index: number): void;
228
+ getCurrentQuality(): number;
229
+ isAutoQuality(): boolean;
230
+ setAutoQuality(): void;
231
+ on<K extends string>(event: K, callback: (...args: unknown[]) => void): void;
232
+ off<K extends string>(event: K, callback: (...args: unknown[]) => void): void;
233
+ }
234
+
235
+ export type { GallopQueryMap as G, PlayerStatus as P, QualityLevel as Q, StreamingEngine as S, VideoMetadata as V, GallopDiagnostics as a, GallopConfig as b, GallopEventCallback as c, GallopEventMap as d, GallopPlayer as e, GallopTheme as f };
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@scalemule/gallop",
3
+ "version": "0.0.1",
4
+ "description": "ScaleMule's video player SDK for web applications",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./element": {
16
+ "types": "./dist/element.d.ts",
17
+ "import": "./dist/element.js",
18
+ "require": "./dist/element.cjs"
19
+ },
20
+ "./react": {
21
+ "types": "./dist/react.d.ts",
22
+ "import": "./dist/react.js",
23
+ "require": "./dist/react.cjs"
24
+ },
25
+ "./iframe": {
26
+ "types": "./dist/iframe.d.ts",
27
+ "import": "./dist/iframe.js",
28
+ "require": "./dist/iframe.cjs"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsup",
38
+ "dev": "tsup --watch",
39
+ "typecheck": "tsc --noEmit",
40
+ "test": "vitest run --passWithNoTests",
41
+ "test:watch": "vitest"
42
+ },
43
+ "dependencies": {
44
+ "hls.js": "^1.5.0"
45
+ },
46
+ "peerDependencies": {
47
+ "react": ">=17.0.0",
48
+ "react-dom": ">=17.0.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "react": {
52
+ "optional": true
53
+ },
54
+ "react-dom": {
55
+ "optional": true
56
+ }
57
+ },
58
+ "devDependencies": {
59
+ "tsup": "^8.0.0",
60
+ "typescript": "^5.4.0",
61
+ "vitest": "^2.0.0",
62
+ "jsdom": "^26.0.0",
63
+ "@types/react": "^18.0.0",
64
+ "@types/react-dom": "^18.0.0"
65
+ },
66
+ "keywords": [
67
+ "scalemule",
68
+ "gallop",
69
+ "video",
70
+ "player",
71
+ "hls",
72
+ "streaming",
73
+ "web-component",
74
+ "react"
75
+ ],
76
+ "author": "ScaleMule Inc. <support@scalemule.com>",
77
+ "license": "MIT",
78
+ "homepage": "https://scalemule.com/gallop",
79
+ "repository": {
80
+ "type": "git",
81
+ "url": "git+https://github.com/scalemule/gallop.git"
82
+ },
83
+ "bugs": {
84
+ "url": "https://github.com/scalemule/gallop/issues"
85
+ },
86
+ "engines": {
87
+ "node": ">=18.0.0"
88
+ },
89
+ "publishConfig": {
90
+ "access": "public",
91
+ "registry": "https://registry.npmjs.org/"
92
+ }
93
+ }