stophy 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -16,24 +16,26 @@ Get an API key from your [Stophy dashboard](https://stophy.dev). The SDK sends i
16
16
  ```ts
17
17
  import { Stophy } from "stophy";
18
18
 
19
- const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY! });
20
-
21
- const { data } = await stophy.video({
22
- type: "transcript",
23
- videoUrl: "https://www.youtube.com/watch?v=D7liwdjvhWc",
24
- });
25
- console.log(data?.text);
19
+ const stophy = new Stophy(); // reads STOPHY_API_KEY
20
+ const result = await stophy.transcript(
21
+ "https://www.youtube.com/watch?v=D7liwdjvhWc",
22
+ );
23
+ console.log(result.data.text);
26
24
  ```
27
25
 
28
26
  ## Methods
29
27
 
30
28
  | Method | Description |
31
29
  | --- | --- |
32
- | `stophy.video(body)` | Details, transcript, comments, replies, or live chat (set `type`) |
33
- | `stophy.search(body)` | Search with filters for type, sort, date, duration, features |
34
- | `stophy.channel(body)` | Channel metadata + content by tab (`video`/`short`/`playlist`/`about`) |
35
- | `stophy.playlist(body)` | Playlist items, paginated |
36
- | `stophy.suggest(query)` | Search autocomplete suggestions |
30
+ | `stophy.videoDetails(url)` | Video metadata and related videos |
31
+ | `stophy.transcript(url)` | Timestamped captions and full text |
32
+ | `stophy.comments(url, options?)` | Top-level comments |
33
+ | `stophy.replies(token)` | Replies for a comment thread |
34
+ | `stophy.liveChat(url, options?)` | Live stream chat messages |
35
+ | `stophy.search(query, options?)` | Search with filters |
36
+ | `stophy.channel(url, options?)` | Channel metadata and content |
37
+ | `stophy.playlist(url, options?)` | Playlist items, paginated |
38
+ | `stophy.suggest(query, options?)` | Search autocomplete suggestions |
37
39
  | `stophy.credits()` | Current credit balance |
38
40
  | `stophy.logs(query?)` | Recent request logs |
39
41
  | `stophy.usage(query?)` | Daily credit/request counts |
@@ -42,21 +44,26 @@ console.log(data?.text);
42
44
 
43
45
  ```ts
44
46
  // Search
45
- const results = await stophy.search({ q: "typescript tutorial", sortBy: "popularity", duration: "long" });
47
+ const results = await stophy.search("typescript tutorial", {
48
+ sortBy: "popularity",
49
+ duration: "long",
50
+ });
46
51
 
47
52
  // Comments (top-level), then replies to a comment.
48
53
  // `video()` is overloaded on `type`, so `data` is typed — no casts needed.
49
- const comments = await stophy.video({ type: "comments", videoUrl, sortBy: "top" });
54
+ const comments = await stophy.comments(videoUrl, { sortBy: "top" });
50
55
  const firstReplyToken = comments.data.items[0]?.repliesToken;
51
56
  if (firstReplyToken) {
52
- const replies = await stophy.video({ type: "replies", continuationToken: firstReplyToken });
57
+ const replies = await stophy.replies(firstReplyToken);
53
58
  }
54
59
 
55
60
  // Channel videos
56
- const channel = await stophy.channel({ channelUrl: "https://www.youtube.com/@mkbhd", tab: "video" });
61
+ const channel = await stophy.channel("https://www.youtube.com/@mkbhd", {
62
+ tab: "video",
63
+ });
57
64
 
58
65
  // Autocomplete
59
- const { data: s } = await stophy.suggest({ q: "react", hl: "en", gl: "US" });
66
+ const { data: s } = await stophy.suggest("react", { hl: "en", gl: "US" });
60
67
  console.log(s?.suggestions);
61
68
 
62
69
  // Account
@@ -70,7 +77,7 @@ List endpoints return a `continuationToken`. Pass it back in to fetch the next p
70
77
  ```ts
71
78
  let token: string | undefined;
72
79
  do {
73
- const page = await stophy.search({ q: "lofi", continuationToken: token });
80
+ const page = await stophy.search("lofi", { continuationToken: token });
74
81
  // ...handle page.data?.items
75
82
  token = page.data?.continuationToken ?? undefined;
76
83
  } while (token);
package/dist/index.cjs CHANGED
@@ -4,10 +4,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var clientFetch = require('@hey-api/client-fetch');
6
6
 
7
- // src/index.ts
8
- var client = clientFetch.createClient(clientFetch.createConfig({
9
- baseUrl: "https://api.stophy.dev"
10
- }));
7
+ // src/generated/client.gen.ts
8
+ var client = clientFetch.createClient(
9
+ clientFetch.createConfig({
10
+ baseUrl: "https://api.stophy.dev"
11
+ })
12
+ );
11
13
 
12
14
  // src/generated/sdk.gen.ts
13
15
  var getVideo = (options) => {
@@ -123,93 +125,56 @@ var getUsage = (options) => {
123
125
  });
124
126
  };
125
127
 
126
- // src/index.ts
128
+ // src/errors.ts
127
129
  var StophyError = class extends Error {
128
130
  code;
129
131
  status;
130
132
  requestId;
131
133
  details;
132
- constructor(message, opts) {
134
+ constructor(message, options) {
133
135
  super(message);
134
136
  this.name = "StophyError";
135
- this.status = opts.status;
136
- this.code = opts.code;
137
- this.requestId = opts.requestId;
138
- this.details = opts.details;
139
- }
140
- };
141
- var Stophy = class {
142
- /** The underlying fetch client, if you need lower-level access. */
143
- client;
144
- constructor(options) {
145
- if (!options?.apiKey) {
146
- throw new Error("Stophy: `apiKey` is required.");
147
- }
148
- const baseFetch = options.fetch ?? globalThis.fetch;
149
- this.client = clientFetch.createClient(
150
- clientFetch.createConfig({
151
- baseUrl: options.baseUrl ?? "https://api.stophy.dev",
152
- auth: () => options.apiKey,
153
- headers: options.headers,
154
- fetch: withRetries(
155
- baseFetch,
156
- options.maxRetries ?? 2,
157
- options.retryInitialDelayMs ?? 500
158
- )
159
- })
160
- );
161
- }
162
- async video(body) {
163
- return unwrap(await getVideo({ client: this.client, body }));
164
- }
165
- /** Search YouTube, optionally filtered by type, sort, date, duration, and features. */
166
- async search(body) {
167
- return unwrap(await searchVideos({ client: this.client, body }));
168
- }
169
- /** Channel metadata and content. Switch sections with `tab`. */
170
- async channel(body) {
171
- return unwrap(await getChannel({ client: this.client, body }));
172
- }
173
- /** Playlist items. Page through long playlists with `continuationToken`. */
174
- async playlist(body) {
175
- return unwrap(await getPlaylist({ client: this.client, body }));
176
- }
177
- /** Search autocomplete suggestions. */
178
- async suggest(query) {
179
- return unwrap(await getSuggestions({ client: this.client, query }));
180
- }
181
- /** Your current credit balance. */
182
- async credits() {
183
- return unwrap(await getCredits({ client: this.client }));
184
- }
185
- /** Recent API request logs. */
186
- async logs(query) {
187
- return unwrap(await getLogs({ client: this.client, query }));
188
- }
189
- /** Daily credit and request counts. */
190
- async usage(query) {
191
- return unwrap(await getUsage({ client: this.client, query }));
137
+ this.status = options.status;
138
+ this.code = options.code;
139
+ this.requestId = options.requestId;
140
+ this.details = options.details;
192
141
  }
193
142
  };
143
+
144
+ // src/transport.ts
145
+ var DEFAULT_BASE_URL = "https://api.stophy.dev";
194
146
  var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
147
+ function createTransport(options) {
148
+ const baseFetch = options.fetch ?? globalThis.fetch;
149
+ return clientFetch.createClient(
150
+ clientFetch.createConfig({
151
+ baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
152
+ auth: () => options.apiKey,
153
+ headers: options.headers,
154
+ fetch: withRetries(
155
+ baseFetch,
156
+ options.maxRetries ?? 2,
157
+ options.retryInitialDelayMs ?? 500
158
+ )
159
+ })
160
+ );
161
+ }
195
162
  function withRetries(baseFetch, maxRetries, initialDelayMs) {
196
- if (maxRetries <= 0) {
197
- return baseFetch;
198
- }
163
+ if (maxRetries <= 0) return baseFetch;
199
164
  return async (input, init) => {
200
165
  for (let attempt = 0; ; attempt++) {
201
166
  const request = input instanceof Request ? input.clone() : input;
202
167
  try {
203
168
  const response = await baseFetch(request, init);
204
169
  if (attempt < maxRetries && RETRYABLE_STATUS.has(response.status)) {
205
- await sleep(retryAfterMs(response) ?? backoffMs(attempt, initialDelayMs));
170
+ await sleep(
171
+ retryAfterMs(response) ?? backoffMs(attempt, initialDelayMs)
172
+ );
206
173
  continue;
207
174
  }
208
175
  return response;
209
176
  } catch (error) {
210
- if (attempt >= maxRetries) {
211
- throw error;
212
- }
177
+ if (attempt >= maxRetries) throw error;
213
178
  await sleep(backoffMs(attempt, initialDelayMs));
214
179
  }
215
180
  }
@@ -221,13 +186,9 @@ function backoffMs(attempt, base) {
221
186
  }
222
187
  function retryAfterMs(response) {
223
188
  const header = response.headers.get("retry-after");
224
- if (!header) {
225
- return null;
226
- }
189
+ if (!header) return null;
227
190
  const seconds = Number(header);
228
- if (!Number.isNaN(seconds)) {
229
- return seconds * 1e3;
230
- }
191
+ if (!Number.isNaN(seconds)) return seconds * 1e3;
231
192
  const date = Date.parse(header);
232
193
  return Number.isNaN(date) ? null : Math.max(0, date - Date.now());
233
194
  }
@@ -235,21 +196,155 @@ function sleep(ms) {
235
196
  return new Promise((resolve) => setTimeout(resolve, ms));
236
197
  }
237
198
  function unwrap(result) {
238
- if (result.error !== void 0 || result.data === void 0) {
239
- const err = result.error ?? {};
240
- throw new StophyError(err.error ?? `Stophy request failed with status ${result.response.status}`, {
199
+ if (result.error === void 0 && result.data !== void 0)
200
+ return result.data;
201
+ const error = result.error ?? {};
202
+ throw new StophyError(
203
+ error.error ?? `Stophy request failed with status ${result.response.status}`,
204
+ {
241
205
  status: result.response.status,
242
- code: err.code,
206
+ code: error.code,
243
207
  requestId: result.response.headers.get("x-request-id") ?? void 0,
244
- details: err.details
245
- });
208
+ details: error.details
209
+ }
210
+ );
211
+ }
212
+
213
+ // src/methods/account.ts
214
+ function credits(client2) {
215
+ return getCredits({ client: client2 }).then(unwrap);
216
+ }
217
+ function logs(client2, query) {
218
+ return getLogs({ client: client2, query }).then(unwrap);
219
+ }
220
+ function usage(client2, query) {
221
+ return getUsage({ client: client2, query }).then(unwrap);
222
+ }
223
+
224
+ // src/methods/channel.ts
225
+ function channel(client2, urlOrBody, options = {}) {
226
+ const body = typeof urlOrBody === "string" ? { channelUrl: urlOrBody, ...options } : urlOrBody;
227
+ return getChannel({ client: client2, body }).then(unwrap);
228
+ }
229
+
230
+ // src/methods/playlist.ts
231
+ function playlist(client2, urlOrBody, options = {}) {
232
+ const body = typeof urlOrBody === "string" ? { playlistUrl: urlOrBody, ...options } : urlOrBody;
233
+ return getPlaylist({ client: client2, body }).then(unwrap);
234
+ }
235
+
236
+ // src/methods/search.ts
237
+ function search(client2, queryOrBody, options = {}) {
238
+ if (typeof queryOrBody === "string" && !queryOrBody.trim()) {
239
+ throw new Error("query cannot be empty");
240
+ }
241
+ const body = typeof queryOrBody === "string" ? { q: queryOrBody, ...options } : queryOrBody;
242
+ return searchVideos({ client: client2, body }).then(unwrap);
243
+ }
244
+
245
+ // src/methods/suggest.ts
246
+ function suggest(client2, queryOrOptions, options = {}) {
247
+ if (typeof queryOrOptions === "string" && !queryOrOptions.trim()) {
248
+ throw new Error("query cannot be empty");
246
249
  }
247
- return result.data;
250
+ const query = typeof queryOrOptions === "string" ? { q: queryOrOptions, ...options } : queryOrOptions;
251
+ return getSuggestions({ client: client2, query }).then(unwrap);
248
252
  }
249
- var index_default = Stophy;
253
+
254
+ // src/methods/video.ts
255
+ async function video(client2, body) {
256
+ return unwrap(await getVideo({ client: client2, body }));
257
+ }
258
+ function videoDetails(client2, videoUrl) {
259
+ return video(client2, { type: "details", videoUrl });
260
+ }
261
+ function transcript(client2, videoUrl) {
262
+ return video(client2, { type: "transcript", videoUrl });
263
+ }
264
+ function comments(client2, videoUrl, options = {}) {
265
+ return video(client2, {
266
+ type: "comments",
267
+ videoUrl,
268
+ ...options
269
+ });
270
+ }
271
+ function replies(client2, continuationToken) {
272
+ return video(client2, {
273
+ type: "replies",
274
+ continuationToken
275
+ });
276
+ }
277
+ function liveChat(client2, videoUrl, options = {}) {
278
+ return video(client2, {
279
+ type: "livechat",
280
+ videoUrl,
281
+ ...options
282
+ });
283
+ }
284
+
285
+ // src/client.ts
286
+ function env(name) {
287
+ return typeof process === "undefined" ? void 0 : process.env[name];
288
+ }
289
+ var Stophy = class {
290
+ client;
291
+ constructor(input = {}) {
292
+ const options = typeof input === "string" ? { apiKey: input } : input;
293
+ const apiKey = options.apiKey?.trim() || env("STOPHY_API_KEY")?.trim();
294
+ if (!apiKey) {
295
+ throw new Error(
296
+ "Stophy: provide `apiKey` or set the STOPHY_API_KEY environment variable."
297
+ );
298
+ }
299
+ this.client = createTransport({
300
+ ...options,
301
+ apiKey,
302
+ baseUrl: options.baseUrl ?? env("STOPHY_BASE_URL")
303
+ });
304
+ }
305
+ async video(body) {
306
+ return video(this.client, body);
307
+ }
308
+ videoDetails(videoUrl) {
309
+ return videoDetails(this.client, videoUrl);
310
+ }
311
+ transcript(videoUrl) {
312
+ return transcript(this.client, videoUrl);
313
+ }
314
+ comments(videoUrl, options) {
315
+ return comments(this.client, videoUrl, options);
316
+ }
317
+ replies(continuationToken) {
318
+ return replies(this.client, continuationToken);
319
+ }
320
+ liveChat(videoUrl, options) {
321
+ return liveChat(this.client, videoUrl, options);
322
+ }
323
+ async search(queryOrBody, options) {
324
+ return search(this.client, queryOrBody, options);
325
+ }
326
+ async channel(urlOrBody, options) {
327
+ return channel(this.client, urlOrBody, options);
328
+ }
329
+ async playlist(urlOrBody, options) {
330
+ return playlist(this.client, urlOrBody, options);
331
+ }
332
+ async suggest(queryOrOptions, options) {
333
+ return suggest(this.client, queryOrOptions, options);
334
+ }
335
+ credits() {
336
+ return credits(this.client);
337
+ }
338
+ logs(query) {
339
+ return logs(this.client, query);
340
+ }
341
+ usage(query) {
342
+ return usage(this.client, query);
343
+ }
344
+ };
250
345
 
251
346
  exports.Stophy = Stophy;
252
347
  exports.StophyError = StophyError;
253
- exports.default = index_default;
348
+ exports.default = Stophy;
254
349
  //# sourceMappingURL=index.cjs.map
255
350
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generated/client.gen.ts","../src/generated/sdk.gen.ts","../src/index.ts"],"names":["createClient","createConfig"],"mappings":"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","file":"index.cjs","sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from './types.gen';\nimport { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from '@hey-api/client-fetch';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions>({\n baseUrl: 'https://api.stophy.dev'\n}));","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';\nimport type { GetVideoData, GetVideoResponse, GetVideoError, SearchVideosData, SearchVideosResponse, SearchVideosError, GetChannelData, GetChannelResponse, GetChannelError, GetPlaylistData, GetPlaylistResponse, GetPlaylistError, GetSuggestionsData, GetSuggestionsResponse, GetSuggestionsError, GetCreditsData, GetCreditsResponse, GetCreditsError, GetLogsData, GetLogsResponse, GetLogsError, GetUsageData, GetUsageResponse, GetUsageError } from './types.gen';\nimport { client as _heyApiClient } from './client.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\n/**\n * Video\n * Fetch video details, transcript, comments, replies, or live chat. Pass type: details for metadata, transcript for timestamped captions, comments for top-level comments, replies for a comment thread (pass the repliesToken from a comment as continuationToken), or livechat for live stream chat messages.\n */\nexport const getVideo = <ThrowOnError extends boolean = false>(options: Options<GetVideoData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<GetVideoResponse, GetVideoError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/video',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Search\n * Search YouTube with optional filters for content type, sort order, upload date, duration, and features. Returns paginated results.\n */\nexport const searchVideos = <ThrowOnError extends boolean = false>(options: Options<SearchVideosData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<SearchVideosResponse, SearchVideosError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/search',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Channel\n * Retrieve channel metadata and content by channelUrl. Use the tab field to switch between videos, shorts, playlists, and about info.\n */\nexport const getChannel = <ThrowOnError extends boolean = false>(options: Options<GetChannelData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<GetChannelResponse, GetChannelError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/channel',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Playlist\n * Retrieve items from a YouTube playlist. Use continuationToken to page through long playlists.\n */\nexport const getPlaylist = <ThrowOnError extends boolean = false>(options: Options<GetPlaylistData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<GetPlaylistResponse, GetPlaylistError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/playlist',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Suggest\n * Get YouTube search autocomplete suggestions for a query.\n */\nexport const getSuggestions = <ThrowOnError extends boolean = false>(options: Options<GetSuggestionsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetSuggestionsResponse, GetSuggestionsError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/suggest',\n ...options\n });\n};\n\n/**\n * Credits\n * Return the current credit balance for the authenticated API key.\n */\nexport const getCredits = <ThrowOnError extends boolean = false>(options?: Options<GetCreditsData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).get<GetCreditsResponse, GetCreditsError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/credits',\n ...options\n });\n};\n\n/**\n * Logs\n * Return recent API request logs for the authenticated key.\n */\nexport const getLogs = <ThrowOnError extends boolean = false>(options?: Options<GetLogsData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).get<GetLogsResponse, GetLogsError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/logs',\n ...options\n });\n};\n\n/**\n * Usage\n * Return daily credit and request counts for the authenticated key.\n */\nexport const getUsage = <ThrowOnError extends boolean = false>(options?: Options<GetUsageData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).get<GetUsageResponse, GetUsageError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/v1/usage',\n ...options\n });\n};","import { createClient, createConfig, type Client } from \"@hey-api/client-fetch\";\nimport * as ops from \"./generated/sdk.gen\";\nimport type {\n ErrorResponse,\n GetVideoData,\n GetVideoResponse,\n SearchVideosData,\n SearchVideosResponse,\n GetChannelData,\n GetChannelResponse,\n GetPlaylistData,\n GetPlaylistResponse,\n GetSuggestionsData,\n GetSuggestionsResponse,\n GetCreditsResponse,\n GetLogsData,\n GetLogsResponse,\n GetUsageData,\n GetUsageResponse,\n VideoDetailsData,\n TranscriptResult,\n CommentsData,\n LiveChatData,\n} from \"./generated/types.gen\";\n\n/** A video response with `data` narrowed to the shape for a given request `type`. */\ntype VideoResponseFor<D> = Omit<GetVideoResponse, \"data\"> & { data: D };\n\nexport * from \"./generated/types.gen\";\n\nexport interface StophyOptions {\n /** API key from your dashboard. Sent as `Authorization: Bearer <key>`. */\n apiKey: string;\n /** Defaults to `https://api.stophy.dev`. */\n baseUrl?: string;\n /** Bring your own `fetch` (handy for tests or non-global runtimes). */\n fetch?: typeof globalThis.fetch;\n /** Sent with every request. */\n headers?: Record<string, string>;\n /**\n * Retry attempts for transient failures (network errors and\n * 429/500/502/503/504). Set to `0` to disable. Defaults to `2`.\n */\n maxRetries?: number;\n /** Base delay for backoff, in ms. Defaults to `500`. */\n retryInitialDelayMs?: number;\n}\n\n/** Thrown when the API responds with a non-2xx status. */\nexport class StophyError extends Error {\n readonly code?: ErrorResponse[\"code\"];\n readonly status: number;\n readonly requestId?: string;\n readonly details?: unknown;\n\n constructor(\n message: string,\n opts: {\n status: number;\n code?: ErrorResponse[\"code\"];\n requestId?: string;\n details?: unknown;\n },\n ) {\n super(message);\n this.name = \"StophyError\";\n this.status = opts.status;\n this.code = opts.code;\n this.requestId = opts.requestId;\n this.details = opts.details;\n }\n}\n\n/**\n * Stophy API client — YouTube context API for AI agents.\n *\n * ```ts\n * const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY! });\n * const { data } = await stophy.video({ type: \"transcript\", videoUrl });\n * ```\n */\nexport class Stophy {\n /** The underlying fetch client, if you need lower-level access. */\n readonly client: Client;\n\n constructor(options: StophyOptions) {\n if (!options?.apiKey) {\n throw new Error(\"Stophy: `apiKey` is required.\");\n }\n const baseFetch = options.fetch ?? globalThis.fetch;\n this.client = createClient(\n createConfig({\n baseUrl: options.baseUrl ?? \"https://api.stophy.dev\",\n auth: () => options.apiKey,\n headers: options.headers,\n fetch: withRetries(\n baseFetch,\n options.maxRetries ?? 2,\n options.retryInitialDelayMs ?? 500,\n ),\n }),\n );\n }\n\n /** Video details, transcript, comments, replies, or live chat — pick with `type`. */\n async video(\n body: GetVideoData[\"body\"] & { type: \"details\" },\n ): Promise<VideoResponseFor<VideoDetailsData>>;\n async video(\n body: GetVideoData[\"body\"] & { type: \"transcript\" },\n ): Promise<VideoResponseFor<TranscriptResult>>;\n async video(\n body: GetVideoData[\"body\"] & { type: \"comments\" | \"replies\" },\n ): Promise<VideoResponseFor<CommentsData>>;\n async video(\n body: GetVideoData[\"body\"] & { type: \"livechat\" },\n ): Promise<VideoResponseFor<LiveChatData>>;\n async video(body: GetVideoData[\"body\"]): Promise<GetVideoResponse>;\n async video(body: GetVideoData[\"body\"]): Promise<GetVideoResponse> {\n return unwrap(await ops.getVideo({ client: this.client, body }));\n }\n\n /** Search YouTube, optionally filtered by type, sort, date, duration, and features. */\n async search(body: SearchVideosData[\"body\"]): Promise<SearchVideosResponse> {\n return unwrap(await ops.searchVideos({ client: this.client, body }));\n }\n\n /** Channel metadata and content. Switch sections with `tab`. */\n async channel(body: GetChannelData[\"body\"]): Promise<GetChannelResponse> {\n return unwrap(await ops.getChannel({ client: this.client, body }));\n }\n\n /** Playlist items. Page through long playlists with `continuationToken`. */\n async playlist(body: GetPlaylistData[\"body\"]): Promise<GetPlaylistResponse> {\n return unwrap(await ops.getPlaylist({ client: this.client, body }));\n }\n\n /** Search autocomplete suggestions. */\n async suggest(query: GetSuggestionsData[\"query\"]): Promise<GetSuggestionsResponse> {\n return unwrap(await ops.getSuggestions({ client: this.client, query }));\n }\n\n /** Your current credit balance. */\n async credits(): Promise<GetCreditsResponse> {\n return unwrap(await ops.getCredits({ client: this.client }));\n }\n\n /** Recent API request logs. */\n async logs(query?: GetLogsData[\"query\"]): Promise<GetLogsResponse> {\n return unwrap(await ops.getLogs({ client: this.client, query }));\n }\n\n /** Daily credit and request counts. */\n async usage(query?: GetUsageData[\"query\"]): Promise<GetUsageResponse> {\n return unwrap(await ops.getUsage({ client: this.client, query }));\n }\n}\n\nconst RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]);\n\ntype FetchFn = (input: Request | URL | string, init?: RequestInit) => Promise<Response>;\n\n// Wrap a fetch so transient failures (network errors and retryable statuses)\n// are retried with exponential backoff + jitter, honoring `Retry-After`.\n// Every Stophy endpoint is a read, so retrying is always safe.\nfunction withRetries(\n baseFetch: typeof globalThis.fetch,\n maxRetries: number,\n initialDelayMs: number,\n): FetchFn {\n if (maxRetries <= 0) {\n return baseFetch;\n }\n return async (input, init) => {\n for (let attempt = 0; ; attempt++) {\n // Clone so the body survives a retry when `input` is a Request.\n const request = input instanceof Request ? input.clone() : input;\n try {\n const response = await baseFetch(request, init);\n if (attempt < maxRetries && RETRYABLE_STATUS.has(response.status)) {\n await sleep(retryAfterMs(response) ?? backoffMs(attempt, initialDelayMs));\n continue;\n }\n return response;\n } catch (error) {\n if (attempt >= maxRetries) {\n throw error;\n }\n await sleep(backoffMs(attempt, initialDelayMs));\n }\n }\n };\n}\n\nfunction backoffMs(attempt: number, base: number): number {\n const window = base * 2 ** attempt;\n return window / 2 + Math.random() * (window / 2);\n}\n\nfunction retryAfterMs(response: Response): number | null {\n const header = response.headers.get(\"retry-after\");\n if (!header) {\n return null;\n }\n const seconds = Number(header);\n if (!Number.isNaN(seconds)) {\n return seconds * 1000;\n }\n const date = Date.parse(header);\n return Number.isNaN(date) ? null : Math.max(0, date - Date.now());\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// Pull `data` out of a result, or throw a StophyError if the call failed.\nfunction unwrap<T>(result: {\n data?: T;\n error?: unknown;\n response: Response;\n}): T {\n if (result.error !== undefined || result.data === undefined) {\n const err = (result.error ?? {}) as Partial<ErrorResponse>;\n throw new StophyError(err.error ?? `Stophy request failed with status ${result.response.status}`, {\n status: result.response.status,\n code: err.code,\n requestId: result.response.headers.get(\"x-request-id\") ?? undefined,\n details: err.details,\n });\n }\n return result.data;\n}\n\nexport default Stophy;\n"]}
1
+ {"version":3,"sources":["../src/generated/client.gen.ts","../src/generated/sdk.gen.ts","../src/errors.ts","../src/transport.ts","../src/methods/account.ts","../src/methods/channel.ts","../src/methods/playlist.ts","../src/methods/search.ts","../src/methods/suggest.ts","../src/methods/video.ts","../src/client.ts"],"names":["createClient","createConfig","client"],"mappings":"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","file":"index.cjs","sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from \"./types.gen\";\nimport {\n type Config,\n type ClientOptions as DefaultClientOptions,\n createClient,\n createConfig,\n} from \"@hey-api/client-fetch\";\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> =\n (\n override?: Config<DefaultClientOptions & T>\n ) => Config<Required<DefaultClientOptions> & T>;\n\nexport const client = createClient(\n createConfig<ClientOptions>({\n baseUrl: \"https://api.stophy.dev\",\n })\n);\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n Options as ClientOptions,\n TDataShape,\n Client,\n} from \"@hey-api/client-fetch\";\nimport type {\n GetVideoData,\n GetVideoResponse,\n GetVideoError,\n SearchVideosData,\n SearchVideosResponse,\n SearchVideosError,\n GetChannelData,\n GetChannelResponse,\n GetChannelError,\n GetPlaylistData,\n GetPlaylistResponse,\n GetPlaylistError,\n GetSuggestionsData,\n GetSuggestionsResponse,\n GetSuggestionsError,\n GetCreditsData,\n GetCreditsResponse,\n GetCreditsError,\n GetLogsData,\n GetLogsResponse,\n GetLogsError,\n GetUsageData,\n GetUsageResponse,\n GetUsageError,\n} from \"./types.gen\";\nimport { client as _heyApiClient } from \"./client.gen\";\n\nexport type Options<\n TData extends TDataShape = TDataShape,\n ThrowOnError extends boolean = boolean\n> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\n/**\n * Video\n * Fetch video details, transcript, comments, replies, or live chat. Pass type: details for metadata, transcript for timestamped captions, comments for top-level comments, replies for a comment thread (pass the repliesToken from a comment as continuationToken), or livechat for live stream chat messages.\n */\nexport const getVideo = <ThrowOnError extends boolean = false>(\n options: Options<GetVideoData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n GetVideoResponse,\n GetVideoError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/video\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n};\n\n/**\n * Search\n * Search YouTube with optional filters for content type, sort order, upload date, duration, and features. Returns paginated results.\n */\nexport const searchVideos = <ThrowOnError extends boolean = false>(\n options: Options<SearchVideosData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n SearchVideosResponse,\n SearchVideosError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/search\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n};\n\n/**\n * Channel\n * Retrieve channel metadata and content by channelUrl. Use the tab field to switch between videos, shorts, playlists, and about info.\n */\nexport const getChannel = <ThrowOnError extends boolean = false>(\n options: Options<GetChannelData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n GetChannelResponse,\n GetChannelError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/channel\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n};\n\n/**\n * Playlist\n * Retrieve items from a YouTube playlist. Use continuationToken to page through long playlists.\n */\nexport const getPlaylist = <ThrowOnError extends boolean = false>(\n options: Options<GetPlaylistData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n GetPlaylistResponse,\n GetPlaylistError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/playlist\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n};\n\n/**\n * Suggest\n * Get YouTube search autocomplete suggestions for a query.\n */\nexport const getSuggestions = <ThrowOnError extends boolean = false>(\n options: Options<GetSuggestionsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n GetSuggestionsResponse,\n GetSuggestionsError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/suggest\",\n ...options,\n });\n};\n\n/**\n * Credits\n * Return the current credit balance for the authenticated API key.\n */\nexport const getCredits = <ThrowOnError extends boolean = false>(\n options?: Options<GetCreditsData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n GetCreditsResponse,\n GetCreditsError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/credits\",\n ...options,\n });\n};\n\n/**\n * Logs\n * Return recent API request logs for the authenticated key.\n */\nexport const getLogs = <ThrowOnError extends boolean = false>(\n options?: Options<GetLogsData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n GetLogsResponse,\n GetLogsError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/logs\",\n ...options,\n });\n};\n\n/**\n * Usage\n * Return daily credit and request counts for the authenticated key.\n */\nexport const getUsage = <ThrowOnError extends boolean = false>(\n options?: Options<GetUsageData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n GetUsageResponse,\n GetUsageError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/v1/usage\",\n ...options,\n });\n};\n","import type { ErrorResponse } from \"./generated/types.gen\";\n\n/** Thrown when the Stophy API responds with a non-success status. */\nexport class StophyError extends Error {\n\treadonly code?: ErrorResponse[\"code\"];\n\treadonly status: number;\n\treadonly requestId?: string;\n\treadonly details?: unknown;\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions: {\n\t\t\tstatus: number;\n\t\t\tcode?: ErrorResponse[\"code\"];\n\t\t\trequestId?: string;\n\t\t\tdetails?: unknown;\n\t\t},\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"StophyError\";\n\t\tthis.status = options.status;\n\t\tthis.code = options.code;\n\t\tthis.requestId = options.requestId;\n\t\tthis.details = options.details;\n\t}\n}\n","import { type Client, createClient, createConfig } from \"@hey-api/client-fetch\";\nimport { StophyError } from \"./errors\";\nimport type { ErrorResponse } from \"./generated/types.gen\";\n\nconst DEFAULT_BASE_URL = \"https://api.stophy.dev\";\nconst RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]);\n\nexport interface TransportOptions {\n\tapiKey: string;\n\tbaseUrl?: string;\n\tfetch?: typeof globalThis.fetch;\n\theaders?: Record<string, string>;\n\tmaxRetries?: number;\n\tretryInitialDelayMs?: number;\n}\n\nexport function createTransport(options: TransportOptions): Client {\n\tconst baseFetch = options.fetch ?? globalThis.fetch;\n\treturn createClient(\n\t\tcreateConfig({\n\t\t\tbaseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n\t\t\tauth: () => options.apiKey,\n\t\t\theaders: options.headers,\n\t\t\tfetch: withRetries(\n\t\t\t\tbaseFetch,\n\t\t\t\toptions.maxRetries ?? 2,\n\t\t\t\toptions.retryInitialDelayMs ?? 500,\n\t\t\t),\n\t\t}),\n\t);\n}\n\ntype FetchFn = (\n\tinput: Request | URL | string,\n\tinit?: RequestInit,\n) => Promise<Response>;\n\nfunction withRetries(\n\tbaseFetch: typeof globalThis.fetch,\n\tmaxRetries: number,\n\tinitialDelayMs: number,\n): FetchFn {\n\tif (maxRetries <= 0) return baseFetch;\n\n\treturn async (input, init) => {\n\t\tfor (let attempt = 0; ; attempt++) {\n\t\t\tconst request = input instanceof Request ? input.clone() : input;\n\t\t\ttry {\n\t\t\t\tconst response = await baseFetch(request, init);\n\t\t\t\tif (attempt < maxRetries && RETRYABLE_STATUS.has(response.status)) {\n\t\t\t\t\tawait sleep(\n\t\t\t\t\t\tretryAfterMs(response) ?? backoffMs(attempt, initialDelayMs),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t} catch (error) {\n\t\t\t\tif (attempt >= maxRetries) throw error;\n\t\t\t\tawait sleep(backoffMs(attempt, initialDelayMs));\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction backoffMs(attempt: number, base: number): number {\n\tconst window = base * 2 ** attempt;\n\treturn window / 2 + Math.random() * (window / 2);\n}\n\nfunction retryAfterMs(response: Response): number | null {\n\tconst header = response.headers.get(\"retry-after\");\n\tif (!header) return null;\n\tconst seconds = Number(header);\n\tif (!Number.isNaN(seconds)) return seconds * 1000;\n\tconst date = Date.parse(header);\n\treturn Number.isNaN(date) ? null : Math.max(0, date - Date.now());\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function unwrap<T>(result: {\n\tdata?: T;\n\terror?: unknown;\n\tresponse: Response;\n}): T {\n\tif (result.error === undefined && result.data !== undefined)\n\t\treturn result.data;\n\n\tconst error = (result.error ?? {}) as Partial<ErrorResponse>;\n\tthrow new StophyError(\n\t\terror.error ??\n\t\t\t`Stophy request failed with status ${result.response.status}`,\n\t\t{\n\t\t\tstatus: result.response.status,\n\t\t\tcode: error.code,\n\t\t\trequestId: result.response.headers.get(\"x-request-id\") ?? undefined,\n\t\t\tdetails: error.details,\n\t\t},\n\t);\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport { getCredits, getLogs, getUsage } from \"../generated/sdk.gen\";\nimport type {\n\tGetCreditsResponse,\n\tGetLogsData,\n\tGetLogsResponse,\n\tGetUsageData,\n\tGetUsageResponse,\n} from \"../generated/types.gen\";\nimport { unwrap } from \"../transport\";\n\nexport function credits(client: Client): Promise<GetCreditsResponse> {\n\treturn getCredits({ client }).then(unwrap);\n}\n\nexport function logs(\n\tclient: Client,\n\tquery?: GetLogsData[\"query\"],\n): Promise<GetLogsResponse> {\n\treturn getLogs({ client, query }).then(unwrap);\n}\n\nexport function usage(\n\tclient: Client,\n\tquery?: GetUsageData[\"query\"],\n): Promise<GetUsageResponse> {\n\treturn getUsage({ client, query }).then(unwrap);\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport { getChannel } from \"../generated/sdk.gen\";\nimport type {\n\tGetChannelData,\n\tGetChannelResponse,\n} from \"../generated/types.gen\";\nimport { unwrap } from \"../transport\";\n\ntype ChannelBody = GetChannelData[\"body\"];\nexport type ChannelOptions = Omit<ChannelBody, \"channelUrl\">;\n\nexport function channel(\n\tclient: Client,\n\turlOrBody: string | ChannelBody,\n\toptions: ChannelOptions = {},\n): Promise<GetChannelResponse> {\n\tconst body =\n\t\ttypeof urlOrBody === \"string\"\n\t\t\t? { channelUrl: urlOrBody, ...options }\n\t\t\t: urlOrBody;\n\treturn getChannel({ client, body }).then(unwrap);\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport { getPlaylist } from \"../generated/sdk.gen\";\nimport type {\n\tGetPlaylistData,\n\tGetPlaylistResponse,\n} from \"../generated/types.gen\";\nimport { unwrap } from \"../transport\";\n\ntype PlaylistBody = GetPlaylistData[\"body\"];\nexport type PlaylistOptions = Omit<PlaylistBody, \"playlistUrl\">;\n\nexport function playlist(\n\tclient: Client,\n\turlOrBody: string | PlaylistBody,\n\toptions: PlaylistOptions = {},\n): Promise<GetPlaylistResponse> {\n\tconst body =\n\t\ttypeof urlOrBody === \"string\"\n\t\t\t? { playlistUrl: urlOrBody, ...options }\n\t\t\t: urlOrBody;\n\treturn getPlaylist({ client, body }).then(unwrap);\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport { searchVideos } from \"../generated/sdk.gen\";\nimport type {\n\tSearchVideosData,\n\tSearchVideosResponse,\n} from \"../generated/types.gen\";\nimport { unwrap } from \"../transport\";\n\ntype SearchBody = SearchVideosData[\"body\"];\nexport type SearchOptions = Omit<SearchBody, \"q\">;\n\nexport function search(\n\tclient: Client,\n\tqueryOrBody: string | SearchBody,\n\toptions: SearchOptions = {},\n): Promise<SearchVideosResponse> {\n\tif (typeof queryOrBody === \"string\" && !queryOrBody.trim()) {\n\t\tthrow new Error(\"query cannot be empty\");\n\t}\n\tconst body =\n\t\ttypeof queryOrBody === \"string\"\n\t\t\t? { q: queryOrBody, ...options }\n\t\t\t: queryOrBody;\n\treturn searchVideos({ client, body }).then(unwrap);\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport { getSuggestions } from \"../generated/sdk.gen\";\nimport type {\n\tGetSuggestionsData,\n\tGetSuggestionsResponse,\n} from \"../generated/types.gen\";\nimport { unwrap } from \"../transport\";\n\ntype SuggestQuery = GetSuggestionsData[\"query\"];\nexport type SuggestOptions = Omit<SuggestQuery, \"q\">;\n\nexport function suggest(\n\tclient: Client,\n\tqueryOrOptions: string | SuggestQuery,\n\toptions: SuggestOptions = {},\n): Promise<GetSuggestionsResponse> {\n\tif (typeof queryOrOptions === \"string\" && !queryOrOptions.trim()) {\n\t\tthrow new Error(\"query cannot be empty\");\n\t}\n\tconst query =\n\t\ttypeof queryOrOptions === \"string\"\n\t\t\t? { q: queryOrOptions, ...options }\n\t\t\t: queryOrOptions;\n\treturn getSuggestions({ client, query }).then(unwrap);\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport { getVideo } from \"../generated/sdk.gen\";\nimport type {\n\tCommentsData,\n\tGetVideoData,\n\tGetVideoResponse,\n\tLiveChatData,\n\tTranscriptResult,\n\tVideoDetailsData,\n} from \"../generated/types.gen\";\nimport { unwrap } from \"../transport\";\n\nexport type VideoResponseFor<T> = Omit<GetVideoResponse, \"data\"> & { data: T };\ntype VideoUrlBody = Extract<GetVideoData[\"body\"], { videoUrl: string }>;\nexport type CommentsOptions = Pick<\n\tVideoUrlBody,\n\t\"sortBy\" | \"continuationToken\"\n>;\nexport type LiveChatOptions = Pick<\n\tVideoUrlBody,\n\t\"chatType\" | \"continuationToken\"\n>;\n\nexport async function video(\n\tclient: Client,\n\tbody: GetVideoData[\"body\"],\n): Promise<GetVideoResponse> {\n\treturn unwrap(await getVideo({ client, body }));\n}\n\nexport function videoDetails(\n\tclient: Client,\n\tvideoUrl: string,\n): Promise<VideoResponseFor<VideoDetailsData>> {\n\treturn video(client, { type: \"details\", videoUrl }) as Promise<\n\t\tVideoResponseFor<VideoDetailsData>\n\t>;\n}\n\nexport function transcript(\n\tclient: Client,\n\tvideoUrl: string,\n): Promise<VideoResponseFor<TranscriptResult>> {\n\treturn video(client, { type: \"transcript\", videoUrl }) as Promise<\n\t\tVideoResponseFor<TranscriptResult>\n\t>;\n}\n\nexport function comments(\n\tclient: Client,\n\tvideoUrl: string,\n\toptions: CommentsOptions = {},\n): Promise<VideoResponseFor<CommentsData>> {\n\treturn video(client, {\n\t\ttype: \"comments\",\n\t\tvideoUrl,\n\t\t...options,\n\t}) as Promise<VideoResponseFor<CommentsData>>;\n}\n\nexport function replies(\n\tclient: Client,\n\tcontinuationToken: string,\n): Promise<VideoResponseFor<CommentsData>> {\n\treturn video(client, {\n\t\ttype: \"replies\",\n\t\tcontinuationToken,\n\t}) as Promise<VideoResponseFor<CommentsData>>;\n}\n\nexport function liveChat(\n\tclient: Client,\n\tvideoUrl: string,\n\toptions: LiveChatOptions = {},\n): Promise<VideoResponseFor<LiveChatData>> {\n\treturn video(client, {\n\t\ttype: \"livechat\",\n\t\tvideoUrl,\n\t\t...options,\n\t}) as Promise<VideoResponseFor<LiveChatData>>;\n}\n","import type { Client } from \"@hey-api/client-fetch\";\nimport type {\n\tCommentsData,\n\tGetChannelData,\n\tGetChannelResponse,\n\tGetCreditsResponse,\n\tGetLogsData,\n\tGetLogsResponse,\n\tGetPlaylistData,\n\tGetPlaylistResponse,\n\tGetSuggestionsData,\n\tGetSuggestionsResponse,\n\tGetUsageData,\n\tGetUsageResponse,\n\tGetVideoData,\n\tGetVideoResponse,\n\tLiveChatData,\n\tSearchVideosData,\n\tSearchVideosResponse,\n\tTranscriptResult,\n\tVideoDetailsData,\n} from \"./generated/types.gen\";\nimport * as accountMethods from \"./methods/account\";\nimport { type ChannelOptions, channel as getChannel } from \"./methods/channel\";\nimport {\n\tplaylist as getPlaylist,\n\ttype PlaylistOptions,\n} from \"./methods/playlist\";\nimport { type SearchOptions, search as searchVideos } from \"./methods/search\";\nimport {\n\tsuggest as getSuggestions,\n\ttype SuggestOptions,\n} from \"./methods/suggest\";\nimport type {\n\tCommentsOptions,\n\tLiveChatOptions,\n\tVideoResponseFor,\n} from \"./methods/video\";\nimport * as videoMethods from \"./methods/video\";\nimport { createTransport } from \"./transport\";\n\nexport interface StophyOptions {\n\t/** Defaults to `STOPHY_API_KEY`. */\n\tapiKey?: string;\n\t/** Defaults to `STOPHY_BASE_URL` or `https://api.stophy.dev`. */\n\tbaseUrl?: string;\n\tfetch?: typeof globalThis.fetch;\n\theaders?: Record<string, string>;\n\tmaxRetries?: number;\n\tretryInitialDelayMs?: number;\n}\n\nexport type StophyClientInput = StophyOptions | string;\n\nfunction env(name: string): string | undefined {\n\treturn typeof process === \"undefined\" ? undefined : process.env[name];\n}\n\n/** Typed client for the Stophy API. */\nexport class Stophy {\n\treadonly client: Client;\n\n\tconstructor(input: StophyClientInput = {}) {\n\t\tconst options = typeof input === \"string\" ? { apiKey: input } : input;\n\t\tconst apiKey = options.apiKey?.trim() || env(\"STOPHY_API_KEY\")?.trim();\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Stophy: provide `apiKey` or set the STOPHY_API_KEY environment variable.\",\n\t\t\t);\n\t\t}\n\n\t\tthis.client = createTransport({\n\t\t\t...options,\n\t\t\tapiKey,\n\t\t\tbaseUrl: options.baseUrl ?? env(\"STOPHY_BASE_URL\"),\n\t\t});\n\t}\n\n\tasync video(\n\t\tbody: GetVideoData[\"body\"] & { type: \"details\" },\n\t): Promise<VideoResponseFor<VideoDetailsData>>;\n\tasync video(\n\t\tbody: GetVideoData[\"body\"] & { type: \"transcript\" },\n\t): Promise<VideoResponseFor<TranscriptResult>>;\n\tasync video(\n\t\tbody: GetVideoData[\"body\"] & { type: \"comments\" | \"replies\" },\n\t): Promise<VideoResponseFor<CommentsData>>;\n\tasync video(\n\t\tbody: GetVideoData[\"body\"] & { type: \"livechat\" },\n\t): Promise<VideoResponseFor<LiveChatData>>;\n\tasync video(body: GetVideoData[\"body\"]): Promise<GetVideoResponse>;\n\tasync video(body: GetVideoData[\"body\"]): Promise<GetVideoResponse> {\n\t\treturn videoMethods.video(this.client, body);\n\t}\n\n\tvideoDetails(videoUrl: string): Promise<VideoResponseFor<VideoDetailsData>> {\n\t\treturn videoMethods.videoDetails(this.client, videoUrl);\n\t}\n\n\ttranscript(videoUrl: string): Promise<VideoResponseFor<TranscriptResult>> {\n\t\treturn videoMethods.transcript(this.client, videoUrl);\n\t}\n\n\tcomments(\n\t\tvideoUrl: string,\n\t\toptions?: CommentsOptions,\n\t): Promise<VideoResponseFor<CommentsData>> {\n\t\treturn videoMethods.comments(this.client, videoUrl, options);\n\t}\n\n\treplies(continuationToken: string): Promise<VideoResponseFor<CommentsData>> {\n\t\treturn videoMethods.replies(this.client, continuationToken);\n\t}\n\n\tliveChat(\n\t\tvideoUrl: string,\n\t\toptions?: LiveChatOptions,\n\t): Promise<VideoResponseFor<LiveChatData>> {\n\t\treturn videoMethods.liveChat(this.client, videoUrl, options);\n\t}\n\n\tasync search(body: SearchVideosData[\"body\"]): Promise<SearchVideosResponse>;\n\tasync search(\n\t\tquery: string,\n\t\toptions?: SearchOptions,\n\t): Promise<SearchVideosResponse>;\n\tasync search(\n\t\tqueryOrBody: string | SearchVideosData[\"body\"],\n\t\toptions?: SearchOptions,\n\t): Promise<SearchVideosResponse> {\n\t\treturn searchVideos(this.client, queryOrBody, options);\n\t}\n\n\tasync channel(body: GetChannelData[\"body\"]): Promise<GetChannelResponse>;\n\tasync channel(\n\t\tchannelUrl: string,\n\t\toptions?: ChannelOptions,\n\t): Promise<GetChannelResponse>;\n\tasync channel(\n\t\turlOrBody: string | GetChannelData[\"body\"],\n\t\toptions?: ChannelOptions,\n\t): Promise<GetChannelResponse> {\n\t\treturn getChannel(this.client, urlOrBody, options);\n\t}\n\n\tasync playlist(body: GetPlaylistData[\"body\"]): Promise<GetPlaylistResponse>;\n\tasync playlist(\n\t\tplaylistUrl: string,\n\t\toptions?: PlaylistOptions,\n\t): Promise<GetPlaylistResponse>;\n\tasync playlist(\n\t\turlOrBody: string | GetPlaylistData[\"body\"],\n\t\toptions?: PlaylistOptions,\n\t): Promise<GetPlaylistResponse> {\n\t\treturn getPlaylist(this.client, urlOrBody, options);\n\t}\n\n\tasync suggest(\n\t\tquery: GetSuggestionsData[\"query\"],\n\t): Promise<GetSuggestionsResponse>;\n\tasync suggest(\n\t\tquery: string,\n\t\toptions?: SuggestOptions,\n\t): Promise<GetSuggestionsResponse>;\n\tasync suggest(\n\t\tqueryOrOptions: string | GetSuggestionsData[\"query\"],\n\t\toptions?: SuggestOptions,\n\t): Promise<GetSuggestionsResponse> {\n\t\treturn getSuggestions(this.client, queryOrOptions, options);\n\t}\n\n\tcredits(): Promise<GetCreditsResponse> {\n\t\treturn accountMethods.credits(this.client);\n\t}\n\n\tlogs(query?: GetLogsData[\"query\"]): Promise<GetLogsResponse> {\n\t\treturn accountMethods.logs(this.client, query);\n\t}\n\n\tusage(query?: GetUsageData[\"query\"]): Promise<GetUsageResponse> {\n\t\treturn accountMethods.usage(this.client, query);\n\t}\n}\n"]}