@rawcast/sdk 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/README.md ADDED
@@ -0,0 +1,285 @@
1
+ # @rawcast/sdk
2
+
3
+ The official, zero-dependency TypeScript & JavaScript SDK for the **Rawcast Media Resolution API**.
4
+
5
+ Resolves high-speed adaptive HLS/DASH video streams, multi-language WebVTT subtitles, comprehensive TMDB metadata, and 4-quality direct MP4 download links (1080p, 720p, 480p, 360p) with sub-second latency.
6
+
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)]()
9
+ [![Types: Included](https://img.shields.io/badge/types-TypeScript%20Strict-blue.svg)]()
10
+ [![Runtimes](https://img.shields.io/badge/runtimes-Node%2018%2B%20%7C%20Bun%20%7C%20Deno%20%7C%20CF%20Workers-orange.svg)]()
11
+
12
+ ---
13
+
14
+ ## ⚡ Features
15
+
16
+ - **Zero Runtime Dependencies**: Powered entirely by the standard Web Fetch API (`fetch`, `Headers`, `AbortController`). Runs anywhere (Node 18+, Bun, Deno, Cloudflare Workers, Next.js, Fastly Compute).
17
+ - **Dual ESM & CommonJS**: Full first-class support for `import` and `require()`.
18
+ - **Smart Stream Selection**: Built-in `.bestStream()` ranking engine automatically picks optimal CDN manifests based on format (HLS/DASH/MP4), resolution, and audio track.
19
+ - **Direct MP4 Downloads**: 1-click download links with RFC 6266 `Content-Disposition` attachment headers across 4 video qualities.
20
+ - **Live Quota Tracking**: Real-time snapshot of remaining monthly developer quota and rate-limit reset windows via `client.quota`.
21
+ - **Built-in Resilience**: Automatic exponential backoff with jitter on HTTP 429 (`Retry-After`) and transient upstream gateway errors (502/503/504).
22
+ - **TypeScript First**: 100% strict type definitions with rich JSDoc documentation and autocomplete.
23
+
24
+ ---
25
+
26
+ ## 📦 Installation
27
+
28
+ ```bash
29
+ # npm
30
+ npm install @rawcast/sdk
31
+
32
+ # bun
33
+ bun add @rawcast/sdk
34
+
35
+ # pnpm
36
+ pnpm add @rawcast/sdk
37
+
38
+ # yarn
39
+ yarn add @rawcast/sdk
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 🚀 Quickstart
45
+
46
+ ```typescript
47
+ import { Rawcast } from '@rawcast/sdk';
48
+
49
+ // Initialize with your API key (or set RAWCAST_API_KEY environment variable)
50
+ const rawcast = new Rawcast({
51
+ apiKey: 'rc_live_your_api_key_here',
52
+ });
53
+
54
+ // Resolve movie streaming servers & subtitles
55
+ const sources = await rawcast.movies.getSources(550); // 550 = Fight Club
56
+
57
+ // Automatically pick the highest quality HLS stream
58
+ const stream = sources.bestStream({ preferFormat: 'hls' });
59
+
60
+ console.log('Stream Manifest:', stream.manifestUrl);
61
+ console.log('Available Subtitles:', sources.subtitles.length);
62
+ console.log('Remaining Monthly Quota:', rawcast.quota.remaining);
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 📖 Usage Guide
68
+
69
+ ### 1. Resolving Movie Streams
70
+
71
+ ```typescript
72
+ const sources = await rawcast.movies.getSources(550, {
73
+ lang: 'en', // Preferred audio language
74
+ title: 'Fight Club', // Optional title override
75
+ });
76
+
77
+ // Pick best stream
78
+ const stream = sources.bestStream({
79
+ preferFormat: 'hls', // 'hls' | 'dash' | 'mp4'
80
+ maxQuality: '1080p', // '1080p' | '720p' | '480p' | '360p'
81
+ preferredAudio: 'English',
82
+ });
83
+
84
+ // Access server groups directly
85
+ for (const server of sources.servers) {
86
+ console.log(`Server: ${server.name} (${server.format})`);
87
+ for (const s of server.streams) {
88
+ console.log(` - Quality: ${s.quality}, Audio: ${s.audio}, URL: ${s.url}`);
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### 2. Resolving TV Show Episodes
94
+
95
+ ```typescript
96
+ // Resolve Game of Thrones Season 1, Episode 1 (TMDB: 1399)
97
+ const sources = await rawcast.tv.getSources(1399, 1, 1, { lang: 'en' });
98
+
99
+ // Or pass an options object:
100
+ const sourcesAlt = await rawcast.tv.getSources({
101
+ tmdbId: 1399,
102
+ season: 1,
103
+ episode: 1,
104
+ });
105
+
106
+ const bestStream = sources.bestStream({ preferFormat: 'hls' });
107
+ console.log('HLS Manifest:', bestStream?.manifestUrl);
108
+ ```
109
+
110
+ ### 3. Subtitles & On-The-Fly WebVTT Conversion
111
+
112
+ Rawcast provides CORS-ready WebVTT conversion on the fly for any remote SRT or VTT subtitle track:
113
+
114
+ ```typescript
115
+ // 1. Fetch available subtitle tracks for a title
116
+ const { subtitles } = await rawcast.subtitles.getMovie(550, { lang: 'en' });
117
+
118
+ for (const track of subtitles) {
119
+ console.log(`[${track.language}] ${track.label} -> ${track.url}`);
120
+ }
121
+
122
+ // 2. Or convert any remote SRT URL to a CORS-friendly WebVTT proxy URL
123
+ const webVttUrl = rawcast.subtitles.getVttUrl('https://example.com/subs.srt');
124
+ // Pass directly to <track src={webVttUrl} kind="subtitles" srcLang="en" />
125
+ ```
126
+
127
+ ### 4. Direct 4-Quality MP4 Downloads
128
+
129
+ Fetch direct download URLs with filename attachments:
130
+
131
+ ```typescript
132
+ // Fetch a specific quality
133
+ const download = await rawcast.movies.getDownload(550, { quality: '1080p' });
134
+ console.log('Download URL:', download.downloadUrl);
135
+ console.log('Filename:', download.filename);
136
+
137
+ // Or fetch all available qualities (1080p, 720p, 480p, 360p):
138
+ const allDownloads = await rawcast.movies.getDownload(550);
139
+ for (const dl of allDownloads.downloads) {
140
+ console.log(`${dl.quality}: ${dl.downloadUrl} (${dl.filename})`);
141
+ }
142
+
143
+ // TV Downloads:
144
+ const tvDownload = await rawcast.tv.getDownload(1399, 1, 1, { quality: '720p' });
145
+ console.log('TV Download:', tvDownload.downloadUrl);
146
+ ```
147
+
148
+ ### 5. TMDB Metadata with CDN Posters & Backdrops
149
+
150
+ ```typescript
151
+ // Fetch Movie Metadata
152
+ const movie = await rawcast.metadata.getMovie(550);
153
+ console.log(movie.title, movie.runtime, movie.rating.voteAverage);
154
+ console.log('Poster:', movie.poster?.original);
155
+ console.log('Cast:', movie.cast.slice(0, 5).map(c => c.name).join(', '));
156
+
157
+ // Fetch TV Show Metadata
158
+ const series = await rawcast.metadata.getTv(1399);
159
+ console.log(series.name, series.numberOfSeasons, series.seasons);
160
+
161
+ // Fetch Season breakdown with episodes:
162
+ const season1 = await rawcast.metadata.getTv(1399, { season: 1 });
163
+ for (const ep of season1.episodes ?? []) {
164
+ console.log(`Episode ${ep.episodeNumber}: ${ep.name} (Rating: ${ep.voteAverage})`);
165
+ }
166
+ ```
167
+
168
+ ### 6. Live Quota & Rate Limit Inspection
169
+
170
+ The client automatically captures quota headers from every API call:
171
+
172
+ ```typescript
173
+ await rawcast.movies.getSources(550);
174
+
175
+ console.log('Monthly Limit:', rawcast.quota.limit);
176
+ console.log('Requests Remaining:', rawcast.quota.remaining);
177
+ console.log('Reset Timestamp:', new Date((rawcast.quota.reset ?? 0) * 1000));
178
+ console.log('Last Sync:', new Date(rawcast.quota.lastUpdated ?? 0));
179
+ ```
180
+
181
+ ### 7. Stream Resolution & Direct Player URLs
182
+
183
+ ```typescript
184
+ // Construct a direct streaming URL from a stream token
185
+ const playerUrl = rawcast.resolve.getStreamUrl(stream.token);
186
+
187
+ // Construct an HLS master playlist URL
188
+ const hlsUrl = rawcast.resolve.getHlsManifestUrl(stream.token);
189
+
190
+ // Or resolve the upstream CDN destination URL directly
191
+ const directCdnUrl = await rawcast.resolve.resolveDirect(stream.token);
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 📺 Video Player Integration Examples
197
+
198
+ ### HTML5 / Hls.js
199
+
200
+ ```html
201
+ <video id="video" controls style="width: 100%; max-width: 800px;"></video>
202
+ <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
203
+ <script type="module">
204
+ import { Rawcast } from '@rawcast/sdk';
205
+
206
+ const rawcast = new Rawcast('rc_live_...');
207
+ const sources = await rawcast.movies.getSources(550);
208
+ const stream = sources.bestStream({ preferFormat: 'hls' });
209
+
210
+ const video = document.getElementById('video');
211
+ if (Hls.isSupported() && stream.manifestUrl) {
212
+ const hls = new Hls();
213
+ hls.loadSource(stream.manifestUrl);
214
+ hls.attachMedia(video);
215
+ } else {
216
+ video.src = stream.url;
217
+ }
218
+ </script>
219
+ ```
220
+
221
+ ---
222
+
223
+ ## 🛡️ Error Handling
224
+
225
+ The SDK exposes granular error classes for all failure modes:
226
+
227
+ ```typescript
228
+ import {
229
+ Rawcast,
230
+ RawcastAuthenticationError,
231
+ RawcastForbiddenError,
232
+ RawcastNotFoundError,
233
+ RawcastRateLimitError,
234
+ RawcastTimeoutError,
235
+ RawcastUpstreamError,
236
+ } from '@rawcast/sdk';
237
+
238
+ try {
239
+ const sources = await rawcast.movies.getSources(550);
240
+ } catch (err) {
241
+ if (err instanceof RawcastAuthenticationError) {
242
+ console.error('Invalid or missing API key.');
243
+ } else if (err instanceof RawcastRateLimitError) {
244
+ console.error(`Rate limited! Retry in ${err.retryAfterSeconds}s.`);
245
+ console.error(`Quota Remaining: ${err.remaining}/${err.limit}`);
246
+ } else if (err instanceof RawcastNotFoundError) {
247
+ console.error('Media title or token not found.');
248
+ } else if (err instanceof RawcastUpstreamError) {
249
+ console.error('Upstream scraper temporary failure. HTTP status:', err.statusCode);
250
+ } else if (err instanceof RawcastTimeoutError) {
251
+ console.error(`Request timed out after ${err.timeoutMs}ms.`);
252
+ } else {
253
+ console.error('Unexpected error:', err);
254
+ }
255
+ }
256
+ ```
257
+
258
+ ---
259
+
260
+ ## ⚙️ Client Options
261
+
262
+ ```typescript
263
+ interface RawcastOptions {
264
+ /** Your Rawcast API key (starts with rc_live_) */
265
+ apiKey: string;
266
+
267
+ /** API Base URL (defaults to https://zeroms.space/v1) */
268
+ baseUrl?: string;
269
+
270
+ /** Request timeout in milliseconds (defaults to 25000) */
271
+ timeoutMs?: number;
272
+
273
+ /** Maximum retries on 429 or 502/503/504 errors (defaults to 2) */
274
+ maxRetries?: number;
275
+
276
+ /** Custom fetch implementation for proxies or test mocks */
277
+ fetch?: typeof fetch;
278
+ }
279
+ ```
280
+
281
+ ---
282
+
283
+ ## 📄 License
284
+
285
+ MIT © Rawcast Team.
@@ -0,0 +1,45 @@
1
+ import { HealthResource } from './resources/health';
2
+ import { MetadataResource } from './resources/metadata';
3
+ import { MoviesResource } from './resources/movies';
4
+ import { ResolveResource } from './resources/resolve';
5
+ import { SubtitlesResource } from './resources/subtitles';
6
+ import { TvResource } from './resources/tv';
7
+ import type { QuotaState, RawcastOptions } from './types';
8
+ /**
9
+ * Main Rawcast SDK client entry point.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { Rawcast } from '@rawcast/sdk';
14
+ *
15
+ * const rawcast = new Rawcast({ apiKey: 'rc_live_...' });
16
+ *
17
+ * // Resolve movie streams:
18
+ * const sources = await rawcast.movies.getSources(550);
19
+ * const stream = sources.bestStream({ preferFormat: 'hls' });
20
+ *
21
+ * // TV streams:
22
+ * const tvSources = await rawcast.tv.getSources(1399, 1, 1);
23
+ *
24
+ * // Check remaining monthly quota:
25
+ * console.log(rawcast.quota.remaining);
26
+ * ```
27
+ */
28
+ export declare class Rawcast {
29
+ private readonly transport;
30
+ readonly movies: MoviesResource;
31
+ readonly tv: TvResource;
32
+ readonly subtitles: SubtitlesResource;
33
+ readonly metadata: MetadataResource;
34
+ /** Short alias for metadata */
35
+ readonly meta: MetadataResource;
36
+ readonly resolve: ResolveResource;
37
+ readonly health: HealthResource;
38
+ constructor(optionsOrApiKey?: string | RawcastOptions);
39
+ /**
40
+ * Current rate-limit and monthly credit quota snapshot,
41
+ * updated automatically after every API response.
42
+ */
43
+ get quota(): Readonly<QuotaState>;
44
+ }
45
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAE1C,SAAgB,MAAM,EAAE,cAAc,CAAC;IACvC,SAAgB,EAAE,EAAE,UAAU,CAAC;IAC/B,SAAgB,SAAS,EAAE,iBAAiB,CAAC;IAC7C,SAAgB,QAAQ,EAAE,gBAAgB,CAAC;IAC3C,+BAA+B;IAC/B,SAAgB,IAAI,EAAE,gBAAgB,CAAC;IACvC,SAAgB,OAAO,EAAE,eAAe,CAAC;IACzC,SAAgB,MAAM,EAAE,cAAc,CAAC;gBAE3B,eAAe,CAAC,EAAE,MAAM,GAAG,cAAc;IAwBrD;;;OAGG;IACH,IAAW,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC,CAEvC;CACF"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Base error class for all Rawcast SDK errors.
3
+ */
4
+ export declare class RawcastError extends Error {
5
+ readonly code: string;
6
+ readonly statusCode?: number;
7
+ readonly responseBody?: unknown;
8
+ constructor(message: string, code?: string, statusCode?: number, responseBody?: unknown);
9
+ }
10
+ /**
11
+ * Thrown when an invalid or missing API key is supplied (HTTP 401).
12
+ */
13
+ export declare class RawcastAuthenticationError extends RawcastError {
14
+ constructor(message?: string, responseBody?: unknown);
15
+ }
16
+ /**
17
+ * Thrown when account permission or email verification fails (HTTP 403).
18
+ */
19
+ export declare class RawcastForbiddenError extends RawcastError {
20
+ constructor(message?: string, code?: string, responseBody?: unknown);
21
+ }
22
+ /**
23
+ * Thrown when a requested resource, title, or stream token is not found (HTTP 404).
24
+ */
25
+ export declare class RawcastNotFoundError extends RawcastError {
26
+ constructor(message?: string, code?: string, responseBody?: unknown);
27
+ }
28
+ /**
29
+ * Thrown when requests exceed plan quotas or burst rate limits (HTTP 429).
30
+ */
31
+ export declare class RawcastRateLimitError extends RawcastError {
32
+ readonly retryAfterSeconds?: number;
33
+ readonly limit?: number;
34
+ readonly remaining?: number;
35
+ readonly reset?: number;
36
+ constructor(message?: string, options?: {
37
+ retryAfterSeconds?: number;
38
+ limit?: number;
39
+ remaining?: number;
40
+ reset?: number;
41
+ responseBody?: unknown;
42
+ });
43
+ }
44
+ /**
45
+ * Thrown when upstream scrapers fail or timeout (HTTP 502 / 504).
46
+ */
47
+ export declare class RawcastUpstreamError extends RawcastError {
48
+ constructor(message?: string, statusCode?: number, responseBody?: unknown);
49
+ }
50
+ /**
51
+ * Thrown when an SDK request exceeds the configured client timeout.
52
+ */
53
+ export declare class RawcastTimeoutError extends RawcastError {
54
+ constructor(timeoutMs: number);
55
+ }
56
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpC,SAAgB,YAAY,CAAC,EAAE,OAAO,CAAC;gBAGrC,OAAO,EAAE,MAAM,EACf,IAAI,SAAqB,EACzB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,OAAO;CASzB;AAED;;GAEG;AACH,qBAAa,0BAA2B,SAAQ,YAAY;gBAC9C,OAAO,SAAmC,EAAE,YAAY,CAAC,EAAE,OAAO;CAI/E;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,YAAY;gBAEnD,OAAO,SAAuD,EAC9D,IAAI,SAAiB,EACrB,YAAY,CAAC,EAAE,OAAO;CAKzB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;gBAElD,OAAO,SAAyC,EAChD,IAAI,SAAiB,EACrB,YAAY,CAAC,EAAE,OAAO;CAKzB;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,SAAgB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3C,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAgB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnC,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;gBAG7B,OAAO,SAA0C,EACjD,OAAO,CAAC,EAAE;QACR,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB;CASJ;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;gBAElD,OAAO,SAAwC,EAC/C,UAAU,SAAM,EAChB,YAAY,CAAC,EAAE,OAAO;CAKzB;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;gBACvC,SAAS,EAAE,MAAM;CAI9B"}