@supadata/js 1.3.2 → 1.4.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 CHANGED
@@ -21,6 +21,8 @@ npm install @supadata/js
21
21
  import {
22
22
  Crawl,
23
23
  CrawlJob,
24
+ ExtractJobResult,
25
+ JobId,
24
26
  JobResult,
25
27
  Map,
26
28
  Metadata,
@@ -84,6 +86,43 @@ if ('jobId' in transcriptResult) {
84
86
  }
85
87
  ```
86
88
 
89
+ ### Extract
90
+
91
+ ```typescript
92
+ // Extract structured data from video content using AI
93
+ // With a prompt (AI determines the schema)
94
+ const job = await supadata.extract({
95
+ url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
96
+ prompt: 'Extract the main topics and key takeaways',
97
+ });
98
+ console.log(`Started extract job: ${job.jobId}`);
99
+
100
+ // With a JSON Schema (for structured output)
101
+ const jobWithSchema = await supadata.extract({
102
+ url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
103
+ schema: {
104
+ type: 'object',
105
+ properties: {
106
+ topics: { type: 'array', items: { type: 'string' } },
107
+ summary: { type: 'string' },
108
+ },
109
+ required: ['topics', 'summary'],
110
+ },
111
+ });
112
+
113
+ // Poll for results
114
+ const result = await supadata.extract.getResults(job.jobId);
115
+ if (result.status === 'completed') {
116
+ console.log('Extracted data:', result.data);
117
+ // If no schema was provided, the AI-generated schema is available:
118
+ console.log('Generated schema:', result.schema);
119
+ } else if (result.status === 'failed') {
120
+ console.error('Extract failed:', result.error);
121
+ } else {
122
+ console.log('Job status:', result.status); // 'queued' or 'active'
123
+ }
124
+ ```
125
+
87
126
  ### YouTube
88
127
 
89
128
  ```typescript
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var x=require('cross-fetch');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var x__default=/*#__PURE__*/_interopDefault(x);var h=fetch||x__default.default;var r=class extends Error{error;details;documentationUrl;constructor(e){super(e.message||"An unexpected error occurred"),this.error=e.error||"internal-error",this.details=e.details||"An unexpected error occurred",this.documentationUrl=e.documentationUrl||"",this.name="SupadataError";}};var g={version:"1.3.2"};var T=`supadata-js/${g.version}`,s=class{config;constructor(e){this.config=e;}async fetch(e,t={},a="GET"){let n=`${this.config.baseUrl||"https://api.supadata.ai/v1"}${e.startsWith("/")?e:`/${e}`}`;if(a==="GET"&&Object.keys(t).length>0){let u=new URLSearchParams;Object.entries(t).forEach(([o,p])=>{p!=null&&(Array.isArray(p)?p.forEach(y=>u.append(o,String(y))):u.append(o,String(p)));}),n+=`?${u.toString()}`;}return this.fetchUrl(n,a,t)}async fetchUrl(e,t="GET",a){let i={method:t,headers:{"x-api-key":this.config.apiKey,"Content-Type":"application/json","User-Agent":T}};t==="POST"&&a&&(i.body=JSON.stringify(a));let n=await h(e,i),u=n.headers.get("content-type");if(!n.ok)if(u?.includes("application/json")){let o=await n.json();throw new r(o)}else throw new r({error:"internal-error",message:"Unexpected error response format",details:await n.text()});try{if(!u?.includes("application/json"))throw new r({error:"internal-error",message:"Invalid response format",details:"Expected JSON response but received different content type"});return await n.json()}catch(o){throw new r({error:"internal-error",message:"Failed to parse response",details:o instanceof Error?o.message:"Unknown error"})}}};var m=class extends s{transcript=Object.assign(async e=>this.fetch("/youtube/transcript",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/transcript/batch",e,"POST"))});video=Object.assign(async e=>this.fetch("/youtube/video",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/video/batch",e,"POST"))});channel=Object.assign(async e=>this.fetch("/youtube/channel",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/channel/videos",e))});playlist=Object.assign(async e=>this.fetch("/youtube/playlist",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/playlist/videos",e))});batch={getBatchResults:async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get batch results."});return this.fetch(`/youtube/batch/${e}`)}};translate=async e=>this.fetch("/youtube/transcript/translate",e);search=async e=>{if(!e.query)throw new r({error:"invalid-request",message:"Missing query parameter",details:"The query parameter is required for search."});return this.validateLimit(e,1,5e3,"search"),this.fetch("/youtube/search",e)};validateLimit(e,t=1,a=5e3,i="operation"){if(e.limit!=null&&e.limit!=null&&(e.limit<t||e.limit>a))throw new r({error:"invalid-request",message:`Invalid limit for ${i}.`,details:`The limit must be between ${t} and ${a}.`})}};var b=class extends s{async scrape(e){return this.fetch("/web/scrape",{url:e})}async map(e){return this.fetch("/web/map",{url:e})}async crawl(e){return this.fetch("/web/crawl",e,"POST")}async getCrawlResults(e){let t,a=[],i;do t=await(i?this.fetchUrl(i):this.fetch(`/web/crawl/${e}`)),t.pages&&(a=[...a,...t.pages]),i=t.next;while(i);return t}};var l=class extends s{get=async e=>this.fetch("/transcript",e);getJobStatus=async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get transcript job status."});return this.fetch(`/transcript/${e}`)}};var f=class extends s{youtube;web;_transcriptService;constructor(e){super(e),this.youtube=new m(e),this.web=new b(e),this._transcriptService=new l(e);}transcript=Object.assign(async e=>this._transcriptService.get(e),{getJobStatus:e=>this._transcriptService.getJobStatus(e)});metadata=async e=>this.fetch("/metadata",e)};
2
- exports.BaseClient=s;exports.Supadata=f;exports.SupadataError=r;exports.TranscriptService=l;exports.WebService=b;exports.YouTubeService=m;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var S=require('cross-fetch');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var S__default=/*#__PURE__*/_interopDefault(S);var h=fetch||S__default.default;var r=class extends Error{error;details;documentationUrl;constructor(e){super(e.message||"An unexpected error occurred"),this.error=e.error||"internal-error",this.details=e.details||"An unexpected error occurred",this.documentationUrl=e.documentationUrl||"",this.name="SupadataError";}};var f={version:"1.4.0"};var P=`supadata-js/${f.version}`,a=class{config;constructor(e){this.config=e;}async fetch(e,t={},s="GET"){let n=`${this.config.baseUrl||"https://api.supadata.ai/v1"}${e.startsWith("/")?e:`/${e}`}`;if(s==="GET"&&Object.keys(t).length>0){let d=new URLSearchParams;Object.entries(t).forEach(([o,l])=>{l!=null&&(Array.isArray(l)?l.forEach(x=>d.append(o,String(x))):d.append(o,String(l)));}),n+=`?${d.toString()}`;}return this.fetchUrl(n,s,t)}async fetchUrl(e,t="GET",s){let i={method:t,headers:{"x-api-key":this.config.apiKey,"Content-Type":"application/json","User-Agent":P}};t==="POST"&&s&&(i.body=JSON.stringify(s));let n=await h(e,i),d=n.headers.get("content-type");if(!n.ok)if(d?.includes("application/json")){let o=await n.json();throw new r(o)}else throw new r({error:"internal-error",message:"Unexpected error response format",details:await n.text()});try{if(!d?.includes("application/json"))throw new r({error:"internal-error",message:"Invalid response format",details:"Expected JSON response but received different content type"});return await n.json()}catch(o){throw new r({error:"internal-error",message:"Failed to parse response",details:o instanceof Error?o.message:"Unknown error"})}}};var b=class extends a{transcript=Object.assign(async e=>this.fetch("/youtube/transcript",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/transcript/batch",e,"POST"))});video=Object.assign(async e=>this.fetch("/youtube/video",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/video/batch",e,"POST"))});channel=Object.assign(async e=>this.fetch("/youtube/channel",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/channel/videos",e))});playlist=Object.assign(async e=>this.fetch("/youtube/playlist",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/playlist/videos",e))});batch={getBatchResults:async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get batch results."});return this.fetch(`/youtube/batch/${e}`)}};translate=async e=>this.fetch("/youtube/transcript/translate",e);search=async e=>{if(!e.query)throw new r({error:"invalid-request",message:"Missing query parameter",details:"The query parameter is required for search."});return this.validateLimit(e,1,5e3,"search"),this.fetch("/youtube/search",e)};validateLimit(e,t=1,s=5e3,i="operation"){if(e.limit!=null&&e.limit!=null&&(e.limit<t||e.limit>s))throw new r({error:"invalid-request",message:`Invalid limit for ${i}.`,details:`The limit must be between ${t} and ${s}.`})}};var g=class extends a{async scrape(e){return this.fetch("/web/scrape",{url:e})}async map(e){return this.fetch("/web/map",{url:e})}async crawl(e){return this.fetch("/web/crawl",e,"POST")}async getCrawlResults(e){let t,s=[],i;do t=await(i?this.fetchUrl(i):this.fetch(`/web/crawl/${e}`)),t.pages&&(s=[...s,...t.pages]),i=t.next;while(i);return t}};var p=class extends a{get=async e=>this.fetch("/transcript",e);getJobStatus=async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get transcript job status."});return this.fetch(`/transcript/${e}`)}};var m=class extends a{get=async e=>this.fetch("/extract",e,"POST");getResults=async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get extract job results."});return this.fetch(`/extract/${e}`)}};var y=class extends a{youtube;web;_transcriptService;_extractService;constructor(e){super(e),this.youtube=new b(e),this.web=new g(e),this._transcriptService=new p(e),this._extractService=new m(e);}transcript=Object.assign(async e=>this._transcriptService.get(e),{getJobStatus:e=>this._transcriptService.getJobStatus(e)});metadata=async e=>this.fetch("/metadata",e);extract=Object.assign(async e=>this._extractService.get(e),{getResults:e=>this._extractService.getResults(e)})};
2
+ exports.BaseClient=a;exports.ExtractService=m;exports.Supadata=y;exports.SupadataError=r;exports.TranscriptService=p;exports.WebService=g;exports.YouTubeService=b;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/polly-fetch.ts","../src/types.ts","../package.json","../src/client.ts","../src/services/youtube.ts","../src/services/web.ts","../src/services/transcript.ts","../src/index.ts"],"names":["polly_fetch_default","crossFetch","SupadataError","error","package_default","USER_AGENT","BaseClient","config","endpoint","params","method","url","queryParams","key","value","item","body","options","response","contentType","errorData","YouTubeService","jobId","min","max","operation","WebService","request","pages","nextUrl","TranscriptService","Supadata"],"mappings":"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","file":"index.cjs","sourcesContent":["import crossFetch from 'cross-fetch';\n\nexport default fetch || crossFetch","export interface TranscriptChunk {\n text: string;\n offset: number;\n duration: number;\n lang: string;\n}\n\nexport interface Transcript {\n content: TranscriptChunk[] | string;\n lang: string;\n availableLangs: string[];\n}\n\nexport interface TranslatedTranscript {\n content: TranscriptChunk[] | string;\n lang: string;\n}\n\nexport interface Scrape {\n url: string;\n content: string;\n name: string;\n description: string;\n ogUrl: string;\n countCharacters: number;\n urls: string[];\n}\n\nexport interface SiteMap {\n urls: string[];\n}\n\nexport interface CrawlRequest {\n url: string;\n limit?: number;\n}\n\nexport interface CrawlJob {\n status: 'scraping' | 'completed' | 'failed' | 'cancelled';\n pages?: Scrape[];\n next?: string;\n}\n\nexport interface SupadataConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class SupadataError extends Error {\n error:\n | 'invalid-request'\n | 'internal-error'\n | 'transcript-unavailable'\n | 'not-found'\n | 'unauthorized'\n | 'upgrade-required'\n | 'limit-exceeded';\n details: string;\n documentationUrl: string;\n\n constructor(error: {\n error: SupadataError['error'];\n message?: string;\n details?: string;\n documentationUrl?: string;\n }) {\n super(error.message || 'An unexpected error occurred');\n this.error = error.error || 'internal-error';\n this.details = error.details || 'An unexpected error occurred';\n this.documentationUrl = error.documentationUrl || '';\n this.name = 'SupadataError';\n }\n}\n\nexport interface YoutubeVideo {\n id: string;\n title: string;\n description: string;\n duration: number;\n channel: {\n id: string;\n name: string;\n };\n tags: string[];\n thumbnail: string;\n uploadDate: string;\n viewCount: number;\n likeCount: number;\n transcriptLanguages: string[];\n}\n\nexport interface YoutubeChannel {\n id: string;\n name: string;\n handle: string;\n description: string;\n subscriberCount: number;\n videoCount: number;\n thumbnail: string;\n banner: string;\n}\n\nexport interface YoutubePlaylist {\n id: string;\n title: string;\n videoCount: number;\n viewCount: number;\n lastUpdated: string;\n description: string;\n thumbnail: string;\n}\n\nexport interface YoutubeBatchSource {\n videoIds?: string[];\n playlistId?: string;\n channelId?: string;\n limit?: number;\n}\n\nexport interface YoutubeTranscriptBatchRequest extends YoutubeBatchSource {\n lang?: string;\n text?: boolean;\n}\n\nexport interface YoutubeVideoBatchRequest extends YoutubeBatchSource {}\n\nexport interface JobId {\n jobId: string;\n}\n\nexport interface YoutubeBatchJob extends JobId {}\n\nexport type JobStatus = 'queued' | 'active' | 'completed' | 'failed';\n\nexport type YoutubeBatchJobStatus = JobStatus;\n\nexport interface YoutubeBatchResultItem {\n videoId: string;\n transcript?: Transcript;\n video?: YoutubeVideo;\n errorCode?: string;\n}\n\nexport interface YoutubeBatchStats {\n total: number;\n succeeded: number;\n failed: number;\n}\n\nexport interface YoutubeBatchResults {\n status: YoutubeBatchJobStatus;\n results?: YoutubeBatchResultItem[];\n stats?: YoutubeBatchStats;\n completedAt?: string;\n}\n\nexport type TranscriptOrJobId = Transcript | JobId;\n\nexport interface JobResult<T = any> {\n status: JobStatus;\n result?: T | null;\n error?: {\n error: SupadataError['error'];\n message: string;\n details: string;\n documentationUrl?: string;\n } | null;\n}\n\n// YouTube Search Types\nexport type YoutubeSearchUploadDate =\n | 'all'\n | 'hour'\n | 'today'\n | 'week'\n | 'month'\n | 'year';\nexport type YoutubeSearchType =\n | 'all'\n | 'video'\n | 'channel'\n | 'playlist'\n | 'movie';\nexport type YoutubeSearchDuration = 'all' | 'short' | 'medium' | 'long';\nexport type YoutubeSearchSortBy = 'relevance' | 'rating' | 'date' | 'views';\n\nexport interface YoutubeSearchParams {\n query: string;\n uploadDate?: YoutubeSearchUploadDate;\n type?: YoutubeSearchType;\n duration?: YoutubeSearchDuration;\n sortBy?: YoutubeSearchSortBy;\n features?: string[];\n limit?: number;\n nextPageToken?: string;\n}\n\nexport interface YoutubeSearchVideoResult {\n type: 'video';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n duration: number;\n viewCount: number;\n uploadDate: string;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport interface YoutubeSearchChannelResult {\n type: 'channel';\n id: string;\n name: string;\n handle: string;\n description: string;\n thumbnail: string;\n subscriberCount: number;\n videoCount: number;\n}\n\nexport interface YoutubeSearchPlaylistResult {\n type: 'playlist';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n videoCount: number;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport type YoutubeSearchResult =\n | YoutubeSearchVideoResult\n | YoutubeSearchChannelResult\n | YoutubeSearchPlaylistResult;\n\nexport interface YoutubeSearchResponse {\n query: string;\n results: YoutubeSearchResult[];\n totalResults: number;\n nextPageToken?: string;\n}\n\n// Metadata Types\nexport type MetadataPlatform = 'youtube' | 'tiktok' | 'instagram' | 'twitter';\nexport type MetadataType = 'video' | 'image' | 'carousel' | 'post';\n\nexport interface MetadataAuthor {\n username: string;\n displayName: string;\n avatarUrl: string;\n verified: boolean;\n}\n\nexport interface MetadataStats {\n views: number | null;\n likes: number | null;\n comments: number | null;\n shares: number | null;\n}\n\nexport interface VideoMedia {\n type: 'video';\n url: string;\n duration: number;\n width: number;\n height: number;\n thumbnailUrl: string;\n}\n\nexport interface ImageMedia {\n type: 'image';\n url: string;\n width: number;\n height: number;\n}\n\nexport interface CarouselMedia {\n type: 'carousel';\n items: Array<VideoMedia | ImageMedia>;\n}\n\nexport interface PostMedia {\n type: 'post';\n text: string;\n}\n\nexport type Media = VideoMedia | ImageMedia | CarouselMedia | PostMedia;\n\nexport interface Metadata {\n platform: MetadataPlatform;\n type: MetadataType;\n id: string;\n url: string;\n title: string | null;\n description: string | null;\n author: MetadataAuthor;\n stats: MetadataStats;\n media: Media;\n tags: string[];\n createdAt: string;\n additionalData: Record<string, any>;\n}\n","{\n \"name\": \"@supadata/js\",\n \"version\": \"1.3.2\",\n \"description\": \"TypeScript / JavaScript SDK for Supadata API\",\n \"homepage\": \"https://supadata.ai\",\n \"repository\": \"https://github.com/supadata-ai/js\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\",\n \"default\": \"./dist/index.mjs\"\n }\n },\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"test\": \"node --experimental-vm-modules node_modules/jest/bin/jest.js\",\n \"prepare\": \"npm run build\",\n \"format\": \"prettier --write \\\"src/**/*.{js,ts}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{js,ts}\\\"\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"keywords\": [\n \"supadata\",\n \"api\",\n \"sdk\",\n \"typescript\",\n \"youtube\",\n \"tiktok\",\n \"instagram\",\n \"twitter\",\n \"transcript\",\n \"web scraping\"\n ],\n \"author\": \"Supadata AI\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"dependencies\": {\n \"cross-fetch\": \"^4.0.0\"\n },\n \"devDependencies\": {\n \"@types/jest\": \"^29.5.14\",\n \"@types/node\": \"^22.10.10\",\n \"jest\": \"^29.7.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.4.2\",\n \"ts-jest\": \"^29.2.5\",\n \"typescript\": \"^5.7.3\",\n \"tsup\": \"^8.3.6\"\n }\n}","import fetch from './polly-fetch';\nimport { SupadataConfig, SupadataError } from './types.js';\n// @ts-expect-error: Non-TS import for version from package.json\nimport pkg from '../package.json';\n\nconst USER_AGENT = `supadata-js/${pkg.version}`;\n\nexport class BaseClient {\n protected config: SupadataConfig;\n\n constructor(config: SupadataConfig) {\n this.config = config;\n }\n\n protected async fetch<T>(\n endpoint: string,\n params: Record<string, any> = {},\n method: 'GET' | 'POST' = 'GET'\n ): Promise<T> {\n const baseUrl = this.config.baseUrl || 'https://api.supadata.ai/v1';\n let url = `${baseUrl}${\n endpoint.startsWith('/') ? endpoint : `/${endpoint}`\n }`;\n\n if (method === 'GET' && Object.keys(params).length > 0) {\n const queryParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => queryParams.append(key, String(item)));\n } else {\n queryParams.append(key, String(value));\n }\n }\n });\n url += `?${queryParams.toString()}`;\n }\n\n return this.fetchUrl<T>(url, method, params);\n }\n\n protected async fetchUrl<T>(\n url: string,\n method: 'GET' | 'POST' = 'GET',\n body?: Record<string, any>\n ): Promise<T> {\n const options: RequestInit = {\n method,\n headers: {\n 'x-api-key': this.config.apiKey,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n };\n\n if (method === 'POST' && body) {\n options.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, options);\n\n const contentType = response.headers.get('content-type');\n\n if (!response.ok) {\n // Handle standard API errors\n if (contentType?.includes('application/json')) {\n const errorData = await response.json();\n throw new SupadataError(errorData);\n } else {\n // Fallback for unexpected non-JSON errors\n throw new SupadataError({\n error: 'internal-error',\n message: 'Unexpected error response format',\n details: await response.text(),\n });\n }\n }\n\n try {\n if (!contentType?.includes('application/json')) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Invalid response format',\n details: 'Expected JSON response but received different content type',\n });\n }\n\n return (await response.json()) as T;\n } catch (error) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Failed to parse response',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n SupadataError,\n Transcript,\n TranslatedTranscript,\n YoutubeBatchJob,\n YoutubeBatchResults,\n YoutubeChannel,\n YoutubePlaylist,\n YoutubeTranscriptBatchRequest,\n YoutubeVideo,\n YoutubeVideoBatchRequest,\n YoutubeSearchParams,\n YoutubeSearchResponse,\n} from '../types.js';\n\n/**\n * Ensures exactly one property from the specified keys is provided.\n * @example\n * // Valid: { url: \"...\" } or { videoId: \"...\" }\n * // Invalid: {} or { url: \"...\", videoId: \"...\" }\n */\ntype ExactlyOne<T, Keys extends keyof T> = {\n [K in Keys]: { [P in K]-?: T[P] } & { [P in Exclude<Keys, K>]?: never };\n}[Keys] &\n Omit<T, Keys>;\n\nexport type TranscriptParams = {\n lang?: string;\n text?: boolean;\n} & ExactlyOne<{ videoId: string; url: string }, 'videoId' | 'url'>;\n\nexport interface TranslateParams extends Omit<TranscriptParams, 'lang'> {\n lang: string;\n}\n\nexport interface ResourceParams {\n id: string;\n}\n\nexport interface ChannelVideosParams extends ResourceParams {\n limit?: number;\n type?: 'video' | 'short' | 'live' | 'all';\n}\n\nexport interface PlaylistVideosParams extends ResourceParams {\n limit?: number;\n}\n\nexport interface VideoIds {\n videoIds: string[];\n shortIds: string[];\n liveIds: string[];\n}\n\nexport class YouTubeService extends BaseClient {\n /**\n * Handles YouTube Transcript operations.\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n transcript = Object.assign(\n /**\n * Fetches a transcript for a YouTube video.\n * @param params - Parameters for fetching the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The language code for the transcript (optional)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a Transcript object\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n async (params: TranscriptParams): Promise<Transcript> => {\n return this.fetch<Transcript>('/youtube/transcript', params);\n },\n {\n /**\n * Batch fetches transcripts for multiple YouTube videos.\n * @param params - Parameters for the transcript batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch transcripts for\n * @param params.lang - The language code for the transcripts (optional)\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeTranscriptBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/transcript/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube video operations.\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n video = Object.assign(\n /**\n * Fetches a YouTube video based on the provided parameters.\n * @param params - The parameters required to fetch the YouTube video\n * @param params.id - The YouTube video ID\n * @returns A promise that resolves to a YoutubeVideo object\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n async (params: ResourceParams): Promise<YoutubeVideo> => {\n return this.fetch<YoutubeVideo>('/youtube/video', params);\n },\n {\n /**\n * Batch fetches metadata for multiple YouTube videos.\n * @param params - Parameters for the video metadata batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch metadata for\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeVideoBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/video/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube channel operations.\n */\n channel = Object.assign(\n /**\n * Fetches YouTube channel information.\n * @param params - The parameters required to fetch the YouTube channel information\n * @param params.id - The YouTube channel ID\n * @returns A promise that resolves to a YoutubeChannel object containing the channel information\n */\n async (params: ResourceParams): Promise<YoutubeChannel> => {\n return this.fetch<YoutubeChannel>('/youtube/channel', params);\n },\n {\n /**\n * Fetches the videos of a YouTube channel.\n * @param params - The parameters required to fetch the YouTube channel videos\n * @param params.id - The YouTube channel ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @param params.type - The type of videos to fetch ('video', 'short', 'live', or 'all', default: 'video')\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: ChannelVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/channel/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube playlist operations.\n */\n playlist = Object.assign(\n /**\n * Fetches a YouTube playlist.\n * @param params - The parameters required to fetch the playlist\n * @param params.id - The YouTube playlist ID\n * @returns A promise that resolves to a YoutubePlaylist object\n */\n async (params: ResourceParams): Promise<YoutubePlaylist> => {\n return this.fetch<YoutubePlaylist>('/youtube/playlist', params);\n },\n {\n /**\n * Fetches the videos of a YouTube playlist.\n * @param params - The parameters required to fetch the playlist videos\n * @param params.id - The YouTube playlist ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: PlaylistVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/playlist/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube batch operations.\n */\n batch = {\n /**\n * Retrieves the status and results of a batch job.\n * @param jobId - The ID of the batch job\n * @returns A promise that resolves to the YoutubeBatchResults containing job status and results\n * @throws {SupadataError} If jobId is not provided\n */\n getBatchResults: async (jobId: string): Promise<YoutubeBatchResults> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details: 'The jobId parameter is required to get batch results.',\n });\n }\n return this.fetch<YoutubeBatchResults>(`/youtube/batch/${jobId}`);\n },\n };\n\n /**\n * Translates a YouTube video transcript to a specified language.\n * @param params - Parameters for translating the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The target language code for translation\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a TranslatedTranscript object\n */\n translate = async (\n params: TranslateParams\n ): Promise<TranslatedTranscript> => {\n return this.fetch<TranslatedTranscript>(\n '/youtube/transcript/translate',\n params\n );\n };\n\n /**\n * Search YouTube for videos, channels, and playlists with advanced filters.\n * @param params - Parameters for the search\n * @param params.query - The search query string\n * @param params.uploadDate - Filter by upload date (\"all\", \"hour\", \"today\", \"week\", \"month\", \"year\")\n * @param params.type - Filter by content type (\"all\", \"video\", \"channel\", \"playlist\", \"movie\")\n * @param params.duration - Filter video length (\"all\", \"short\", \"medium\", \"long\")\n * @param params.sortBy - Sort results by (\"relevance\", \"rating\", \"date\", \"views\")\n * @param params.features - Array of special video features\n * @param params.limit - Maximum results to return\n * @param params.nextPageToken - Token for pagination\n * @returns A promise that resolves to a YoutubeSearchResponse object\n */\n search = async (\n params: YoutubeSearchParams\n ): Promise<YoutubeSearchResponse> => {\n if (!params.query) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing query parameter',\n details: 'The query parameter is required for search.',\n });\n }\n\n this.validateLimit(params, 1, 5000, 'search');\n\n return this.fetch<YoutubeSearchResponse>('/youtube/search', params);\n };\n\n private validateLimit(\n params: { limit?: number },\n min: number = 1,\n max: number = 5000,\n operation: string = 'operation'\n ) {\n if (\n params.limit != undefined &&\n params.limit != null &&\n (params.limit < min || params.limit > max)\n ) {\n throw new SupadataError({\n error: 'invalid-request',\n message: `Invalid limit for ${operation}.`,\n details: `The limit must be between ${min} and ${max}.`,\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport { CrawlJob, CrawlRequest, JobId, Scrape, SiteMap } from '../types.js';\n\nexport class WebService extends BaseClient {\n /**\n * Extract content from any web page to Markdown format.\n *\n * @param url - URL of the webpage to scrape\n * @returns A promise that resolves to the scraped content\n */\n async scrape(url: string): Promise<Scrape> {\n return this.fetch<Scrape>('/web/scrape', { url });\n }\n\n /**\n * Extract all links found on a webpage.\n *\n * @param url - URL of the webpage to map\n * @returns A promise that resolves to a map of URLs found on the page\n */\n async map(url: string): Promise<SiteMap> {\n return this.fetch<SiteMap>('/web/map', { url });\n }\n\n /**\n * Create a crawl job to extract content from all pages on a website.\n *\n * @param request - Crawl request parameters\n * @param request.url - URL of the website to crawl\n * @param request.limit - Maximum number of pages to crawl (default: 100, max: 5000)\n * @returns A promise that resolves to the crawl job id\n */\n async crawl(request: CrawlRequest): Promise<JobId> {\n return this.fetch<JobId>('/web/crawl', request, 'POST');\n }\n\n /**\n * Get the status and results of a crawl job.\n * Automatically handles pagination to retrieve all pages from the crawl.\n *\n * @param jobId - The ID of the crawl job to retrieve\n * @returns A promise that resolves to the complete crawl job results\n */\n async getCrawlResults(jobId: string): Promise<CrawlJob> {\n let response: CrawlJob;\n let pages: Scrape[] = [];\n let nextUrl: string | undefined;\n\n do {\n response = await (nextUrl\n ? this.fetchUrl<CrawlJob>(nextUrl)\n : this.fetch<CrawlJob>(`/web/crawl/${jobId}`));\n\n if (response.pages) {\n pages = [...pages, ...response.pages];\n }\n nextUrl = response.next;\n } while (nextUrl);\n\n return response;\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n JobId,\n JobResult,\n SupadataError,\n Transcript,\n TranscriptOrJobId,\n} from '../types.js';\n\nexport interface GeneralTranscriptParams {\n url: string;\n lang?: string;\n text?: boolean;\n chunkSize?: number;\n mode?: 'native' | 'auto' | 'generate';\n}\n\nexport class TranscriptService extends BaseClient {\n /**\n * Get transcript from a supported video platform or file URL.\n * @param params - Parameters for fetching the transcript\n * @returns A promise that resolves to either a Transcript or JobId for async processing\n */\n get = async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this.fetch<TranscriptOrJobId>('/transcript', params);\n };\n\n /**\n * Get results for a transcript job by job ID.\n * @param jobId - The ID of the transcript job\n * @returns A promise that resolves to the job result containing status and transcript if completed\n * @throws {SupadataError} If jobId is not provided\n */\n getJobStatus = async (jobId: string): Promise<JobResult<Transcript>> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details:\n 'The jobId parameter is required to get transcript job status.',\n });\n }\n return this.fetch<JobResult<Transcript>>(`/transcript/${jobId}`);\n };\n}\n","import {\n JobResult,\n Metadata,\n SupadataConfig,\n Transcript,\n TranscriptOrJobId,\n} from './types.js';\nimport { YouTubeService } from './services/youtube.js';\nimport { WebService } from './services/web.js';\nimport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\nimport { BaseClient } from './client.js';\n\nexport * from './types.js';\nexport * from './client.js';\nexport * from './services/youtube.js';\nexport * from './services/web.js';\nexport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\n\nexport interface MetadataParams {\n url: string;\n}\n\nexport class Supadata extends BaseClient {\n readonly youtube: YouTubeService;\n readonly web: WebService;\n private _transcriptService: TranscriptService;\n\n constructor(config: SupadataConfig) {\n super(config);\n this.youtube = new YouTubeService(config);\n this.web = new WebService(config);\n this._transcriptService = new TranscriptService(config);\n }\n\n /**\n * Get transcript from a supported video platform (YouTube, TikTok, Instagram, Twitter) or file URL.\n * If the video is too large to return transcript immediately, request returns a job ID.\n */\n transcript = Object.assign(\n async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this._transcriptService.get(params);\n },\n {\n getJobStatus: (jobId: string): Promise<JobResult<Transcript>> => {\n return this._transcriptService.getJobStatus(jobId);\n },\n }\n );\n\n /**\n * Get metadata from any supported platform (YouTube, TikTok, Instagram, Twitter).\n * @param params - Parameters for fetching metadata\n * @param params.url - Media URL from YouTube, TikTok, Instagram, or Twitter\n * @returns A promise that resolves to a Metadata object\n */\n metadata = async (params: MetadataParams): Promise<Metadata> => {\n return this.fetch<Metadata>('/metadata', params);\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/polly-fetch.ts","../src/types.ts","../package.json","../src/client.ts","../src/services/youtube.ts","../src/services/web.ts","../src/services/transcript.ts","../src/services/extract.ts","../src/index.ts"],"names":["polly_fetch_default","crossFetch","SupadataError","error","package_default","USER_AGENT","BaseClient","config","endpoint","params","method","url","queryParams","key","value","item","body","options","response","contentType","errorData","YouTubeService","jobId","min","max","operation","WebService","request","pages","nextUrl","TranscriptService","ExtractService","Supadata"],"mappings":"0JAEA,IAAOA,CAAAA,CAAQ,OAASC,kBC8CjB,CAAA,IAAMC,CAAN,CAAA,cAA4B,KAAM,CACvC,MAQA,OACA,CAAA,gBAAA,CAEA,WAAYC,CAAAA,CAAAA,CAKT,CACD,KAAA,CAAMA,EAAM,OAAW,EAAA,8BAA8B,CACrD,CAAA,IAAA,CAAK,KAAQA,CAAAA,CAAAA,CAAM,OAAS,gBAC5B,CAAA,IAAA,CAAK,QAAUA,CAAM,CAAA,OAAA,EAAW,+BAChC,IAAK,CAAA,gBAAA,CAAmBA,CAAM,CAAA,gBAAA,EAAoB,EAClD,CAAA,IAAA,CAAK,KAAO,gBACd,CACF,ECxEA,IAAAC,CAAA,CAAA,CAEE,OAAA,CAAW,OAyDb,CAAA,CCtDMC,IAAAA,CAAAA,CAAa,CAAeD,YAAAA,EAAAA,CAAAA,CAAI,OAAO,CAEhCE,CAAAA,CAAAA,CAAAA,CAAN,KAAiB,CACZ,MAEV,CAAA,WAAA,CAAYC,EAAwB,CAClC,IAAA,CAAK,MAASA,CAAAA,EAChB,CAEA,MAAgB,MACdC,CACAC,CAAAA,CAAAA,CAA8B,EAC9BC,CAAAA,CAAAA,CAAyB,MACb,CAEZ,IAAIC,CAAM,CAAA,CAAA,EADM,IAAK,CAAA,MAAA,CAAO,SAAW,4BACnB,CAAA,EAClBH,CAAS,CAAA,UAAA,CAAW,GAAG,CAAA,CAAIA,EAAW,CAAIA,CAAAA,EAAAA,CAAQ,CACpD,CAAA,CAAA,CAAA,CAEA,GAAIE,CAAAA,GAAW,OAAS,MAAO,CAAA,IAAA,CAAKD,CAAM,CAAA,CAAE,MAAS,CAAA,CAAA,CAAG,CACtD,IAAMG,CAAAA,CAAc,IAAI,eAAA,CACxB,MAAO,CAAA,OAAA,CAAQH,CAAM,CAAE,CAAA,OAAA,CAAQ,CAAC,CAACI,CAAKC,CAAAA,CAAK,IAAM,CACpBA,CAAAA,EAAU,IAC/B,GAAA,KAAA,CAAM,OAAQA,CAAAA,CAAK,EACrBA,CAAM,CAAA,OAAA,CAASC,GAASH,CAAY,CAAA,MAAA,CAAOC,EAAK,MAAOE,CAAAA,CAAI,CAAC,CAAC,CAE7DH,CAAAA,CAAAA,CAAY,OAAOC,CAAK,CAAA,MAAA,CAAOC,CAAK,CAAC,CAG3C,EAAA,CAAC,EACDH,CAAO,EAAA,CAAA,CAAA,EAAIC,CAAY,CAAA,QAAA,EAAU,CAAA,EACnC,CAEA,OAAO,IAAA,CAAK,SAAYD,CAAKD,CAAAA,CAAAA,CAAQD,CAAM,CAC7C,CAEA,MAAgB,QAAA,CACdE,CACAD,CAAAA,CAAAA,CAAyB,MACzBM,CACY,CAAA,CACZ,IAAMC,CAAAA,CAAuB,CAC3B,MAAA,CAAAP,EACA,OAAS,CAAA,CACP,WAAa,CAAA,IAAA,CAAK,MAAO,CAAA,MAAA,CACzB,eAAgB,kBAChB,CAAA,YAAA,CAAcL,CAChB,CACF,CAAA,CAEIK,IAAW,MAAUM,EAAAA,CAAAA,GACvBC,CAAQ,CAAA,IAAA,CAAO,IAAK,CAAA,SAAA,CAAUD,CAAI,CAGpC,CAAA,CAAA,IAAME,CAAW,CAAA,MAAMlB,CAAMW,CAAAA,CAAAA,CAAKM,CAAO,CAEnCE,CAAAA,CAAAA,CAAcD,CAAS,CAAA,OAAA,CAAQ,GAAI,CAAA,cAAc,EAEvD,GAAI,CAACA,EAAS,EAEZ,CAAA,GAAIC,GAAa,QAAS,CAAA,kBAAkB,CAAG,CAAA,CAC7C,IAAMC,CAAAA,CAAY,MAAMF,CAAS,CAAA,IAAA,EACjC,CAAA,MAAM,IAAIhB,CAAAA,CAAckB,CAAS,CACnC,CAAA,KAEQ,MAAA,IAAIlB,CAAc,CAAA,CACtB,MAAO,gBACP,CAAA,OAAA,CAAS,mCACT,OAAS,CAAA,MAAMgB,EAAS,IAAK,EAC/B,CAAC,CAAA,CAIL,GAAI,CACF,GAAI,CAACC,CAAAA,EAAa,QAAS,CAAA,kBAAkB,CAC3C,CAAA,MAAM,IAAIjB,CAAc,CAAA,CACtB,KAAO,CAAA,gBAAA,CACP,OAAS,CAAA,yBAAA,CACT,QAAS,4DACX,CAAC,EAGH,OAAQ,MAAMgB,EAAS,IAAK,EAC9B,CAASf,MAAAA,CAAAA,CAAO,CACd,MAAM,IAAID,CAAc,CAAA,CACtB,KAAO,CAAA,gBAAA,CACP,OAAS,CAAA,0BAAA,CACT,QAASC,CAAiB,YAAA,KAAA,CAAQA,CAAM,CAAA,OAAA,CAAU,eACpD,CAAC,CACH,CACF,CACF,ECzCakB,IAAAA,CAAAA,CAAN,cAA6Bf,CAAW,CAK7C,UAAa,CAAA,MAAA,CAAO,MAWlB,CAAA,MAAOG,GACE,IAAK,CAAA,KAAA,CAAkB,qBAAuBA,CAAAA,CAAM,CAE7D,CAAA,CAUE,MAAO,MACLA,CAAAA,GAEA,IAAK,CAAA,aAAA,CAAcA,CAAQ,CAAA,CAAA,CAAG,IAAM,iBAAiB,CAAA,CAC9C,IAAK,CAAA,KAAA,CACV,2BACAA,CAAAA,CAAAA,CACA,MACF,CAEJ,CAAA,CACF,CAMA,CAAA,KAAA,CAAQ,MAAO,CAAA,MAAA,CAQb,MAAOA,CACE,EAAA,IAAA,CAAK,KAAoB,CAAA,gBAAA,CAAkBA,CAAM,CAAA,CAE1D,CAQE,KAAO,CAAA,MACLA,CAEA,GAAA,IAAA,CAAK,aAAcA,CAAAA,CAAAA,CAAQ,EAAG,GAAM,CAAA,iBAAiB,EAC9C,IAAK,CAAA,KAAA,CACV,uBACAA,CACA,CAAA,MACF,CAEJ,CAAA,CACF,CAKA,CAAA,OAAA,CAAU,OAAO,MAOf,CAAA,MAAOA,CACE,EAAA,IAAA,CAAK,KAAsB,CAAA,kBAAA,CAAoBA,CAAM,CAE9D,CAAA,CAUE,MAAQ,CAAA,MAAOA,CACb,GAAA,IAAA,CAAK,cAAcA,CAAM,CAAA,CAClB,KAAK,KAAgB,CAAA,yBAAA,CAA2BA,CAAM,CAEjE,CAAA,CACF,CAKA,CAAA,QAAA,CAAW,MAAO,CAAA,MAAA,CAOhB,MAAOA,CACE,EAAA,IAAA,CAAK,KAAuB,CAAA,mBAAA,CAAqBA,CAAM,CAAA,CAEhE,CASE,MAAQ,CAAA,MAAOA,CACb,GAAA,IAAA,CAAK,aAAcA,CAAAA,CAAM,EAClB,IAAK,CAAA,KAAA,CAAgB,2BAA4BA,CAAM,CAAA,CAElE,CACF,CAKA,CAAA,KAAA,CAAQ,CAON,eAAA,CAAiB,MAAOa,CAAAA,EAAgD,CACtE,GAAI,CAACA,CACH,CAAA,MAAM,IAAIpB,CAAAA,CAAc,CACtB,KAAO,CAAA,iBAAA,CACP,OAAS,CAAA,eAAA,CACT,OAAS,CAAA,uDACX,CAAC,CAEH,CAAA,OAAO,KAAK,KAA2B,CAAA,CAAA,eAAA,EAAkBoB,CAAK,CAAE,CAAA,CAClE,CACF,CAAA,CAWA,SAAY,CAAA,MACVb,GAEO,IAAK,CAAA,KAAA,CACV,+BACAA,CAAAA,CACF,CAgBF,CAAA,MAAA,CAAS,MACPA,CACmC,EAAA,CACnC,GAAI,CAACA,CAAO,CAAA,KAAA,CACV,MAAM,IAAIP,CAAAA,CAAc,CACtB,KAAO,CAAA,iBAAA,CACP,QAAS,yBACT,CAAA,OAAA,CAAS,6CACX,CAAC,CAGH,CAAA,OAAA,IAAA,CAAK,cAAcO,CAAQ,CAAA,CAAA,CAAG,GAAM,CAAA,QAAQ,CAErC,CAAA,IAAA,CAAK,MAA6B,iBAAmBA,CAAAA,CAAM,CACpE,CAAA,CAEQ,aACNA,CAAAA,CAAAA,CACAc,EAAc,CACdC,CAAAA,CAAAA,CAAc,IACdC,CAAoB,CAAA,WAAA,CACpB,CACA,GACEhB,CAAAA,CAAO,KAAS,EAAA,IAAA,EAChBA,CAAO,CAAA,KAAA,EAAS,OACfA,CAAO,CAAA,KAAA,CAAQc,CAAOd,EAAAA,CAAAA,CAAO,KAAQe,CAAAA,CAAAA,CAAAA,CAEtC,MAAM,IAAItB,CAAAA,CAAc,CACtB,KAAA,CAAO,iBACP,CAAA,OAAA,CAAS,qBAAqBuB,CAAS,CAAA,CAAA,CAAA,CACvC,QAAS,CAA6BF,0BAAAA,EAAAA,CAAG,QAAQC,CAAG,CAAA,CAAA,CACtD,CAAC,CAEL,CACF,MCpRaE,CAAN,CAAA,cAAyBpB,CAAW,CAOzC,MAAM,MAAA,CAAOK,EAA8B,CACzC,OAAO,IAAK,CAAA,KAAA,CAAc,aAAe,CAAA,CAAE,IAAAA,CAAI,CAAC,CAClD,CAQA,MAAM,GAAA,CAAIA,EAA+B,CACvC,OAAO,IAAK,CAAA,KAAA,CAAe,UAAY,CAAA,CAAE,IAAAA,CAAI,CAAC,CAChD,CAUA,MAAM,KAAA,CAAMgB,EAAuC,CACjD,OAAO,IAAK,CAAA,KAAA,CAAa,YAAcA,CAAAA,CAAAA,CAAS,MAAM,CACxD,CASA,MAAM,eAAgBL,CAAAA,CAAAA,CAAkC,CACtD,IAAIJ,CAAAA,CACAU,CAAkB,CAAA,EAClBC,CAAAA,CAAAA,CAEJ,GACEX,CAAW,CAAA,MAAOW,CACd,CAAA,IAAA,CAAK,QAAmBA,CAAAA,CAAO,EAC/B,IAAK,CAAA,KAAA,CAAgB,CAAcP,WAAAA,EAAAA,CAAK,CAAE,CAAA,CAAA,CAAA,CAE1CJ,EAAS,KACXU,GAAAA,CAAAA,CAAQ,CAAC,GAAGA,CAAAA,CAAO,GAAGV,CAAS,CAAA,KAAK,CAEtCW,CAAAA,CAAAA,CAAAA,CAAUX,CAAS,CAAA,IAAA,CAAA,MACZW,GAET,OAAOX,CACT,CACF,EC5CaY,IAAAA,CAAAA,CAAN,cAAgCxB,CAAW,CAMhD,GAAM,CAAA,MAAOG,CACJ,EAAA,IAAA,CAAK,MAAyB,aAAeA,CAAAA,CAAM,EAS5D,YAAe,CAAA,MAAOa,GAAkD,CACtE,GAAI,CAACA,CAAAA,CACH,MAAM,IAAIpB,EAAc,CACtB,KAAA,CAAO,iBACP,CAAA,OAAA,CAAS,eACT,CAAA,OAAA,CACE,+DACJ,CAAC,CAAA,CAEH,OAAO,IAAA,CAAK,KAA6B,CAAA,CAAA,YAAA,EAAeoB,CAAK,CAAE,CAAA,CACjE,CACF,ECpCO,IAAMS,EAAN,cAA6BzB,CAAW,CAM7C,GAAA,CAAM,MAAOG,CAAAA,EACJ,KAAK,KAAa,CAAA,UAAA,CAAYA,CAAQ,CAAA,MAAM,CASrD,CAAA,UAAA,CAAa,MAAOa,CAA6C,EAAA,CAC/D,GAAI,CAACA,CACH,CAAA,MAAM,IAAIpB,CAAc,CAAA,CACtB,MAAO,iBACP,CAAA,OAAA,CAAS,gBACT,OACE,CAAA,6DACJ,CAAC,CAAA,CAEH,OAAO,IAAA,CAAK,MAAwB,CAAYoB,SAAAA,EAAAA,CAAK,CAAE,CAAA,CACzD,CACF,MCFaU,CAAN,CAAA,cAAuB1B,CAAW,CAC9B,OACA,CAAA,GAAA,CACD,mBACA,eAER,CAAA,WAAA,CAAYC,EAAwB,CAClC,KAAA,CAAMA,CAAM,CACZ,CAAA,IAAA,CAAK,OAAU,CAAA,IAAIc,CAAed,CAAAA,CAAM,EACxC,IAAK,CAAA,GAAA,CAAM,IAAImB,CAAAA,CAAWnB,CAAM,CAAA,CAChC,KAAK,kBAAqB,CAAA,IAAIuB,CAAkBvB,CAAAA,CAAM,CACtD,CAAA,IAAA,CAAK,gBAAkB,IAAIwB,CAAAA,CAAexB,CAAM,EAClD,CAMA,WAAa,MAAO,CAAA,MAAA,CAClB,MAAOE,CAAAA,EACE,IAAK,CAAA,kBAAA,CAAmB,IAAIA,CAAM,CAAA,CAE3C,CACE,YAAA,CAAea,CACN,EAAA,IAAA,CAAK,mBAAmB,YAAaA,CAAAA,CAAK,CAErD,CACF,CAQA,CAAA,QAAA,CAAW,MAAOb,CACT,EAAA,IAAA,CAAK,KAAgB,CAAA,WAAA,CAAaA,CAAM,CAAA,CAQjD,QAAU,MAAO,CAAA,MAAA,CACf,MAAOA,CAAAA,EACE,IAAK,CAAA,eAAA,CAAgB,IAAIA,CAAM,CAAA,CAExC,CACE,UAAA,CAAaa,CACJ,EAAA,IAAA,CAAK,gBAAgB,UAAWA,CAAAA,CAAK,CAEhD,CACF,CACF","file":"index.cjs","sourcesContent":["import crossFetch from 'cross-fetch';\n\nexport default fetch || crossFetch","export interface TranscriptChunk {\n text: string;\n offset: number;\n duration: number;\n lang: string;\n}\n\nexport interface Transcript {\n content: TranscriptChunk[] | string;\n lang: string;\n availableLangs: string[];\n}\n\nexport interface TranslatedTranscript {\n content: TranscriptChunk[] | string;\n lang: string;\n}\n\nexport interface Scrape {\n url: string;\n content: string;\n name: string;\n description: string;\n ogUrl: string;\n countCharacters: number;\n urls: string[];\n}\n\nexport interface SiteMap {\n urls: string[];\n}\n\nexport interface CrawlRequest {\n url: string;\n limit?: number;\n}\n\nexport interface CrawlJob {\n status: 'scraping' | 'completed' | 'failed' | 'cancelled';\n pages?: Scrape[];\n next?: string;\n}\n\nexport interface SupadataConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class SupadataError extends Error {\n error:\n | 'invalid-request'\n | 'internal-error'\n | 'transcript-unavailable'\n | 'not-found'\n | 'unauthorized'\n | 'upgrade-required'\n | 'limit-exceeded';\n details: string;\n documentationUrl: string;\n\n constructor(error: {\n error: SupadataError['error'];\n message?: string;\n details?: string;\n documentationUrl?: string;\n }) {\n super(error.message || 'An unexpected error occurred');\n this.error = error.error || 'internal-error';\n this.details = error.details || 'An unexpected error occurred';\n this.documentationUrl = error.documentationUrl || '';\n this.name = 'SupadataError';\n }\n}\n\nexport interface YoutubeVideo {\n id: string;\n title: string;\n description: string;\n duration: number;\n channel: {\n id: string;\n name: string;\n };\n tags: string[];\n thumbnail: string;\n uploadDate: string;\n viewCount: number;\n likeCount: number;\n transcriptLanguages: string[];\n}\n\nexport interface YoutubeChannel {\n id: string;\n name: string;\n handle: string;\n description: string;\n subscriberCount: number;\n videoCount: number;\n thumbnail: string;\n banner: string;\n}\n\nexport interface YoutubePlaylist {\n id: string;\n title: string;\n videoCount: number;\n viewCount: number;\n lastUpdated: string;\n description: string;\n thumbnail: string;\n}\n\nexport interface YoutubeBatchSource {\n videoIds?: string[];\n playlistId?: string;\n channelId?: string;\n limit?: number;\n}\n\nexport interface YoutubeTranscriptBatchRequest extends YoutubeBatchSource {\n lang?: string;\n text?: boolean;\n}\n\nexport interface YoutubeVideoBatchRequest extends YoutubeBatchSource {}\n\nexport interface JobId {\n jobId: string;\n}\n\nexport interface YoutubeBatchJob extends JobId {}\n\nexport type JobStatus = 'queued' | 'active' | 'completed' | 'failed';\n\nexport type YoutubeBatchJobStatus = JobStatus;\n\nexport interface YoutubeBatchResultItem {\n videoId: string;\n transcript?: Transcript;\n video?: YoutubeVideo;\n errorCode?: string;\n}\n\nexport interface YoutubeBatchStats {\n total: number;\n succeeded: number;\n failed: number;\n}\n\nexport interface YoutubeBatchResults {\n status: YoutubeBatchJobStatus;\n results?: YoutubeBatchResultItem[];\n stats?: YoutubeBatchStats;\n completedAt?: string;\n}\n\nexport type TranscriptOrJobId = Transcript | JobId;\n\nexport interface JobResult<T = any> {\n status: JobStatus;\n result?: T | null;\n error?: {\n error: SupadataError['error'];\n message: string;\n details: string;\n documentationUrl?: string;\n } | null;\n}\n\n// YouTube Search Types\nexport type YoutubeSearchUploadDate =\n | 'all'\n | 'hour'\n | 'today'\n | 'week'\n | 'month'\n | 'year';\nexport type YoutubeSearchType =\n | 'all'\n | 'video'\n | 'channel'\n | 'playlist'\n | 'movie';\nexport type YoutubeSearchDuration = 'all' | 'short' | 'medium' | 'long';\nexport type YoutubeSearchSortBy = 'relevance' | 'rating' | 'date' | 'views';\n\nexport interface YoutubeSearchParams {\n query: string;\n uploadDate?: YoutubeSearchUploadDate;\n type?: YoutubeSearchType;\n duration?: YoutubeSearchDuration;\n sortBy?: YoutubeSearchSortBy;\n features?: string[];\n limit?: number;\n nextPageToken?: string;\n}\n\nexport interface YoutubeSearchVideoResult {\n type: 'video';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n duration: number;\n viewCount: number;\n uploadDate: string;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport interface YoutubeSearchChannelResult {\n type: 'channel';\n id: string;\n name: string;\n handle: string;\n description: string;\n thumbnail: string;\n subscriberCount: number;\n videoCount: number;\n}\n\nexport interface YoutubeSearchPlaylistResult {\n type: 'playlist';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n videoCount: number;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport type YoutubeSearchResult =\n | YoutubeSearchVideoResult\n | YoutubeSearchChannelResult\n | YoutubeSearchPlaylistResult;\n\nexport interface YoutubeSearchResponse {\n query: string;\n results: YoutubeSearchResult[];\n totalResults: number;\n nextPageToken?: string;\n}\n\n// Metadata Types\nexport type MetadataPlatform = 'youtube' | 'tiktok' | 'instagram' | 'twitter';\nexport type MetadataType = 'video' | 'image' | 'carousel' | 'post';\n\nexport interface MetadataAuthor {\n username: string;\n displayName: string;\n avatarUrl: string;\n verified: boolean;\n}\n\nexport interface MetadataStats {\n views: number | null;\n likes: number | null;\n comments: number | null;\n shares: number | null;\n}\n\nexport interface VideoMedia {\n type: 'video';\n url: string;\n duration: number;\n width: number;\n height: number;\n thumbnailUrl: string;\n}\n\nexport interface ImageMedia {\n type: 'image';\n url: string;\n width: number;\n height: number;\n}\n\nexport interface CarouselMedia {\n type: 'carousel';\n items: Array<VideoMedia | ImageMedia>;\n}\n\nexport interface PostMedia {\n type: 'post';\n text: string;\n}\n\nexport type Media = VideoMedia | ImageMedia | CarouselMedia | PostMedia;\n\nexport interface Metadata {\n platform: MetadataPlatform;\n type: MetadataType;\n id: string;\n url: string;\n title: string | null;\n description: string | null;\n author: MetadataAuthor;\n stats: MetadataStats;\n media: Media;\n tags: string[];\n createdAt: string;\n additionalData: Record<string, any>;\n}\n\n// Extract Types\nexport interface ExtractParams {\n url: string;\n prompt?: string;\n schema?: Record<string, any>;\n}\n\nexport interface ExtractJobResult {\n status: JobStatus;\n error?: {\n error: SupadataError['error'];\n message: string;\n details: string;\n documentationUrl?: string;\n } | null;\n data?: Record<string, any>;\n schema?: Record<string, any>;\n}\n","{\n \"name\": \"@supadata/js\",\n \"version\": \"1.4.0\",\n \"description\": \"TypeScript / JavaScript SDK for Supadata API\",\n \"homepage\": \"https://supadata.ai\",\n \"repository\": \"https://github.com/supadata-ai/js\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\",\n \"default\": \"./dist/index.mjs\"\n }\n },\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"test\": \"node --experimental-vm-modules node_modules/jest/bin/jest.js\",\n \"prepare\": \"npm run build\",\n \"format\": \"prettier --write \\\"src/**/*.{js,ts}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{js,ts}\\\"\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"keywords\": [\n \"supadata\",\n \"api\",\n \"sdk\",\n \"typescript\",\n \"youtube\",\n \"tiktok\",\n \"instagram\",\n \"twitter\",\n \"transcript\",\n \"web scraping\"\n ],\n \"author\": \"Supadata AI\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"dependencies\": {\n \"cross-fetch\": \"^4.0.0\"\n },\n \"devDependencies\": {\n \"@types/jest\": \"^29.5.14\",\n \"@types/node\": \"^22.10.10\",\n \"jest\": \"^29.7.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.4.2\",\n \"ts-jest\": \"^29.2.5\",\n \"typescript\": \"^5.7.3\",\n \"tsup\": \"^8.3.6\"\n }\n}","import fetch from './polly-fetch';\nimport { SupadataConfig, SupadataError } from './types.js';\n// @ts-expect-error: Non-TS import for version from package.json\nimport pkg from '../package.json';\n\nconst USER_AGENT = `supadata-js/${pkg.version}`;\n\nexport class BaseClient {\n protected config: SupadataConfig;\n\n constructor(config: SupadataConfig) {\n this.config = config;\n }\n\n protected async fetch<T>(\n endpoint: string,\n params: Record<string, any> = {},\n method: 'GET' | 'POST' = 'GET'\n ): Promise<T> {\n const baseUrl = this.config.baseUrl || 'https://api.supadata.ai/v1';\n let url = `${baseUrl}${\n endpoint.startsWith('/') ? endpoint : `/${endpoint}`\n }`;\n\n if (method === 'GET' && Object.keys(params).length > 0) {\n const queryParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => queryParams.append(key, String(item)));\n } else {\n queryParams.append(key, String(value));\n }\n }\n });\n url += `?${queryParams.toString()}`;\n }\n\n return this.fetchUrl<T>(url, method, params);\n }\n\n protected async fetchUrl<T>(\n url: string,\n method: 'GET' | 'POST' = 'GET',\n body?: Record<string, any>\n ): Promise<T> {\n const options: RequestInit = {\n method,\n headers: {\n 'x-api-key': this.config.apiKey,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n };\n\n if (method === 'POST' && body) {\n options.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, options);\n\n const contentType = response.headers.get('content-type');\n\n if (!response.ok) {\n // Handle standard API errors\n if (contentType?.includes('application/json')) {\n const errorData = await response.json();\n throw new SupadataError(errorData);\n } else {\n // Fallback for unexpected non-JSON errors\n throw new SupadataError({\n error: 'internal-error',\n message: 'Unexpected error response format',\n details: await response.text(),\n });\n }\n }\n\n try {\n if (!contentType?.includes('application/json')) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Invalid response format',\n details: 'Expected JSON response but received different content type',\n });\n }\n\n return (await response.json()) as T;\n } catch (error) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Failed to parse response',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n SupadataError,\n Transcript,\n TranslatedTranscript,\n YoutubeBatchJob,\n YoutubeBatchResults,\n YoutubeChannel,\n YoutubePlaylist,\n YoutubeTranscriptBatchRequest,\n YoutubeVideo,\n YoutubeVideoBatchRequest,\n YoutubeSearchParams,\n YoutubeSearchResponse,\n} from '../types.js';\n\n/**\n * Ensures exactly one property from the specified keys is provided.\n * @example\n * // Valid: { url: \"...\" } or { videoId: \"...\" }\n * // Invalid: {} or { url: \"...\", videoId: \"...\" }\n */\ntype ExactlyOne<T, Keys extends keyof T> = {\n [K in Keys]: { [P in K]-?: T[P] } & { [P in Exclude<Keys, K>]?: never };\n}[Keys] &\n Omit<T, Keys>;\n\nexport type TranscriptParams = {\n lang?: string;\n text?: boolean;\n} & ExactlyOne<{ videoId: string; url: string }, 'videoId' | 'url'>;\n\nexport interface TranslateParams extends Omit<TranscriptParams, 'lang'> {\n lang: string;\n}\n\nexport interface ResourceParams {\n id: string;\n}\n\nexport interface ChannelVideosParams extends ResourceParams {\n limit?: number;\n type?: 'video' | 'short' | 'live' | 'all';\n}\n\nexport interface PlaylistVideosParams extends ResourceParams {\n limit?: number;\n}\n\nexport interface VideoIds {\n videoIds: string[];\n shortIds: string[];\n liveIds: string[];\n}\n\nexport class YouTubeService extends BaseClient {\n /**\n * Handles YouTube Transcript operations.\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n transcript = Object.assign(\n /**\n * Fetches a transcript for a YouTube video.\n * @param params - Parameters for fetching the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The language code for the transcript (optional)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a Transcript object\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n async (params: TranscriptParams): Promise<Transcript> => {\n return this.fetch<Transcript>('/youtube/transcript', params);\n },\n {\n /**\n * Batch fetches transcripts for multiple YouTube videos.\n * @param params - Parameters for the transcript batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch transcripts for\n * @param params.lang - The language code for the transcripts (optional)\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeTranscriptBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/transcript/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube video operations.\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n video = Object.assign(\n /**\n * Fetches a YouTube video based on the provided parameters.\n * @param params - The parameters required to fetch the YouTube video\n * @param params.id - The YouTube video ID\n * @returns A promise that resolves to a YoutubeVideo object\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n async (params: ResourceParams): Promise<YoutubeVideo> => {\n return this.fetch<YoutubeVideo>('/youtube/video', params);\n },\n {\n /**\n * Batch fetches metadata for multiple YouTube videos.\n * @param params - Parameters for the video metadata batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch metadata for\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeVideoBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/video/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube channel operations.\n */\n channel = Object.assign(\n /**\n * Fetches YouTube channel information.\n * @param params - The parameters required to fetch the YouTube channel information\n * @param params.id - The YouTube channel ID\n * @returns A promise that resolves to a YoutubeChannel object containing the channel information\n */\n async (params: ResourceParams): Promise<YoutubeChannel> => {\n return this.fetch<YoutubeChannel>('/youtube/channel', params);\n },\n {\n /**\n * Fetches the videos of a YouTube channel.\n * @param params - The parameters required to fetch the YouTube channel videos\n * @param params.id - The YouTube channel ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @param params.type - The type of videos to fetch ('video', 'short', 'live', or 'all', default: 'video')\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: ChannelVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/channel/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube playlist operations.\n */\n playlist = Object.assign(\n /**\n * Fetches a YouTube playlist.\n * @param params - The parameters required to fetch the playlist\n * @param params.id - The YouTube playlist ID\n * @returns A promise that resolves to a YoutubePlaylist object\n */\n async (params: ResourceParams): Promise<YoutubePlaylist> => {\n return this.fetch<YoutubePlaylist>('/youtube/playlist', params);\n },\n {\n /**\n * Fetches the videos of a YouTube playlist.\n * @param params - The parameters required to fetch the playlist videos\n * @param params.id - The YouTube playlist ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: PlaylistVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/playlist/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube batch operations.\n */\n batch = {\n /**\n * Retrieves the status and results of a batch job.\n * @param jobId - The ID of the batch job\n * @returns A promise that resolves to the YoutubeBatchResults containing job status and results\n * @throws {SupadataError} If jobId is not provided\n */\n getBatchResults: async (jobId: string): Promise<YoutubeBatchResults> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details: 'The jobId parameter is required to get batch results.',\n });\n }\n return this.fetch<YoutubeBatchResults>(`/youtube/batch/${jobId}`);\n },\n };\n\n /**\n * Translates a YouTube video transcript to a specified language.\n * @param params - Parameters for translating the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The target language code for translation\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a TranslatedTranscript object\n */\n translate = async (\n params: TranslateParams\n ): Promise<TranslatedTranscript> => {\n return this.fetch<TranslatedTranscript>(\n '/youtube/transcript/translate',\n params\n );\n };\n\n /**\n * Search YouTube for videos, channels, and playlists with advanced filters.\n * @param params - Parameters for the search\n * @param params.query - The search query string\n * @param params.uploadDate - Filter by upload date (\"all\", \"hour\", \"today\", \"week\", \"month\", \"year\")\n * @param params.type - Filter by content type (\"all\", \"video\", \"channel\", \"playlist\", \"movie\")\n * @param params.duration - Filter video length (\"all\", \"short\", \"medium\", \"long\")\n * @param params.sortBy - Sort results by (\"relevance\", \"rating\", \"date\", \"views\")\n * @param params.features - Array of special video features\n * @param params.limit - Maximum results to return\n * @param params.nextPageToken - Token for pagination\n * @returns A promise that resolves to a YoutubeSearchResponse object\n */\n search = async (\n params: YoutubeSearchParams\n ): Promise<YoutubeSearchResponse> => {\n if (!params.query) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing query parameter',\n details: 'The query parameter is required for search.',\n });\n }\n\n this.validateLimit(params, 1, 5000, 'search');\n\n return this.fetch<YoutubeSearchResponse>('/youtube/search', params);\n };\n\n private validateLimit(\n params: { limit?: number },\n min: number = 1,\n max: number = 5000,\n operation: string = 'operation'\n ) {\n if (\n params.limit != undefined &&\n params.limit != null &&\n (params.limit < min || params.limit > max)\n ) {\n throw new SupadataError({\n error: 'invalid-request',\n message: `Invalid limit for ${operation}.`,\n details: `The limit must be between ${min} and ${max}.`,\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport { CrawlJob, CrawlRequest, JobId, Scrape, SiteMap } from '../types.js';\n\nexport class WebService extends BaseClient {\n /**\n * Extract content from any web page to Markdown format.\n *\n * @param url - URL of the webpage to scrape\n * @returns A promise that resolves to the scraped content\n */\n async scrape(url: string): Promise<Scrape> {\n return this.fetch<Scrape>('/web/scrape', { url });\n }\n\n /**\n * Extract all links found on a webpage.\n *\n * @param url - URL of the webpage to map\n * @returns A promise that resolves to a map of URLs found on the page\n */\n async map(url: string): Promise<SiteMap> {\n return this.fetch<SiteMap>('/web/map', { url });\n }\n\n /**\n * Create a crawl job to extract content from all pages on a website.\n *\n * @param request - Crawl request parameters\n * @param request.url - URL of the website to crawl\n * @param request.limit - Maximum number of pages to crawl (default: 100, max: 5000)\n * @returns A promise that resolves to the crawl job id\n */\n async crawl(request: CrawlRequest): Promise<JobId> {\n return this.fetch<JobId>('/web/crawl', request, 'POST');\n }\n\n /**\n * Get the status and results of a crawl job.\n * Automatically handles pagination to retrieve all pages from the crawl.\n *\n * @param jobId - The ID of the crawl job to retrieve\n * @returns A promise that resolves to the complete crawl job results\n */\n async getCrawlResults(jobId: string): Promise<CrawlJob> {\n let response: CrawlJob;\n let pages: Scrape[] = [];\n let nextUrl: string | undefined;\n\n do {\n response = await (nextUrl\n ? this.fetchUrl<CrawlJob>(nextUrl)\n : this.fetch<CrawlJob>(`/web/crawl/${jobId}`));\n\n if (response.pages) {\n pages = [...pages, ...response.pages];\n }\n nextUrl = response.next;\n } while (nextUrl);\n\n return response;\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n JobId,\n JobResult,\n SupadataError,\n Transcript,\n TranscriptOrJobId,\n} from '../types.js';\n\nexport interface GeneralTranscriptParams {\n url: string;\n lang?: string;\n text?: boolean;\n chunkSize?: number;\n mode?: 'native' | 'auto' | 'generate';\n}\n\nexport class TranscriptService extends BaseClient {\n /**\n * Get transcript from a supported video platform or file URL.\n * @param params - Parameters for fetching the transcript\n * @returns A promise that resolves to either a Transcript or JobId for async processing\n */\n get = async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this.fetch<TranscriptOrJobId>('/transcript', params);\n };\n\n /**\n * Get results for a transcript job by job ID.\n * @param jobId - The ID of the transcript job\n * @returns A promise that resolves to the job result containing status and transcript if completed\n * @throws {SupadataError} If jobId is not provided\n */\n getJobStatus = async (jobId: string): Promise<JobResult<Transcript>> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details:\n 'The jobId parameter is required to get transcript job status.',\n });\n }\n return this.fetch<JobResult<Transcript>>(`/transcript/${jobId}`);\n };\n}\n","import { BaseClient } from '../client.js';\nimport {\n ExtractJobResult,\n ExtractParams,\n JobId,\n SupadataError,\n} from '../types.js';\n\nexport class ExtractService extends BaseClient {\n /**\n * Start an extract job to analyze video content and extract structured data.\n * @param params - Parameters for the extract job\n * @returns A promise that resolves to a JobId for async processing\n */\n get = async (params: ExtractParams): Promise<JobId> => {\n return this.fetch<JobId>('/extract', params, 'POST');\n };\n\n /**\n * Get results for an extract job by job ID.\n * @param jobId - The ID of the extract job\n * @returns A promise that resolves to the extract job result\n * @throws {SupadataError} If jobId is not provided\n */\n getResults = async (jobId: string): Promise<ExtractJobResult> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details:\n 'The jobId parameter is required to get extract job results.',\n });\n }\n return this.fetch<ExtractJobResult>(`/extract/${jobId}`);\n };\n}\n","import {\n ExtractJobResult,\n ExtractParams,\n JobId,\n JobResult,\n Metadata,\n SupadataConfig,\n Transcript,\n TranscriptOrJobId,\n} from './types.js';\nimport { YouTubeService } from './services/youtube.js';\nimport { WebService } from './services/web.js';\nimport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\nimport { ExtractService } from './services/extract.js';\nimport { BaseClient } from './client.js';\n\nexport * from './types.js';\nexport * from './client.js';\nexport * from './services/youtube.js';\nexport * from './services/web.js';\nexport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\nexport { ExtractService } from './services/extract.js';\n\nexport interface MetadataParams {\n url: string;\n}\n\nexport class Supadata extends BaseClient {\n readonly youtube: YouTubeService;\n readonly web: WebService;\n private _transcriptService: TranscriptService;\n private _extractService: ExtractService;\n\n constructor(config: SupadataConfig) {\n super(config);\n this.youtube = new YouTubeService(config);\n this.web = new WebService(config);\n this._transcriptService = new TranscriptService(config);\n this._extractService = new ExtractService(config);\n }\n\n /**\n * Get transcript from a supported video platform (YouTube, TikTok, Instagram, Twitter) or file URL.\n * If the video is too large to return transcript immediately, request returns a job ID.\n */\n transcript = Object.assign(\n async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this._transcriptService.get(params);\n },\n {\n getJobStatus: (jobId: string): Promise<JobResult<Transcript>> => {\n return this._transcriptService.getJobStatus(jobId);\n },\n }\n );\n\n /**\n * Get metadata from any supported platform (YouTube, TikTok, Instagram, Twitter).\n * @param params - Parameters for fetching metadata\n * @param params.url - Media URL from YouTube, TikTok, Instagram, or Twitter\n * @returns A promise that resolves to a Metadata object\n */\n metadata = async (params: MetadataParams): Promise<Metadata> => {\n return this.fetch<Metadata>('/metadata', params);\n };\n\n /**\n * Extract structured data from video content using AI.\n * Returns a job ID for asynchronous processing.\n * Use extract.getResults(jobId) to poll for results.\n */\n extract = Object.assign(\n async (params: ExtractParams): Promise<JobId> => {\n return this._extractService.get(params);\n },\n {\n getResults: (jobId: string): Promise<ExtractJobResult> => {\n return this._extractService.getResults(jobId);\n },\n }\n );\n}\n"]}
package/dist/index.d.mts CHANGED
@@ -239,6 +239,22 @@ interface Metadata {
239
239
  createdAt: string;
240
240
  additionalData: Record<string, any>;
241
241
  }
242
+ interface ExtractParams {
243
+ url: string;
244
+ prompt?: string;
245
+ schema?: Record<string, any>;
246
+ }
247
+ interface ExtractJobResult {
248
+ status: JobStatus;
249
+ error?: {
250
+ error: SupadataError['error'];
251
+ message: string;
252
+ details: string;
253
+ documentationUrl?: string;
254
+ } | null;
255
+ data?: Record<string, any>;
256
+ schema?: Record<string, any>;
257
+ }
242
258
 
243
259
  declare class BaseClient {
244
260
  protected config: SupadataConfig;
@@ -441,6 +457,22 @@ declare class TranscriptService extends BaseClient {
441
457
  getJobStatus: (jobId: string) => Promise<JobResult<Transcript>>;
442
458
  }
443
459
 
460
+ declare class ExtractService extends BaseClient {
461
+ /**
462
+ * Start an extract job to analyze video content and extract structured data.
463
+ * @param params - Parameters for the extract job
464
+ * @returns A promise that resolves to a JobId for async processing
465
+ */
466
+ get: (params: ExtractParams) => Promise<JobId>;
467
+ /**
468
+ * Get results for an extract job by job ID.
469
+ * @param jobId - The ID of the extract job
470
+ * @returns A promise that resolves to the extract job result
471
+ * @throws {SupadataError} If jobId is not provided
472
+ */
473
+ getResults: (jobId: string) => Promise<ExtractJobResult>;
474
+ }
475
+
444
476
  interface MetadataParams {
445
477
  url: string;
446
478
  }
@@ -448,6 +480,7 @@ declare class Supadata extends BaseClient {
448
480
  readonly youtube: YouTubeService;
449
481
  readonly web: WebService;
450
482
  private _transcriptService;
483
+ private _extractService;
451
484
  constructor(config: SupadataConfig);
452
485
  /**
453
486
  * Get transcript from a supported video platform (YouTube, TikTok, Instagram, Twitter) or file URL.
@@ -463,6 +496,14 @@ declare class Supadata extends BaseClient {
463
496
  * @returns A promise that resolves to a Metadata object
464
497
  */
465
498
  metadata: (params: MetadataParams) => Promise<Metadata>;
499
+ /**
500
+ * Extract structured data from video content using AI.
501
+ * Returns a job ID for asynchronous processing.
502
+ * Use extract.getResults(jobId) to poll for results.
503
+ */
504
+ extract: ((params: ExtractParams) => Promise<JobId>) & {
505
+ getResults: (jobId: string) => Promise<ExtractJobResult>;
506
+ };
466
507
  }
467
508
 
468
- export { BaseClient, type CarouselMedia, type ChannelVideosParams, type CrawlJob, type CrawlRequest, type GeneralTranscriptParams, type ImageMedia, type JobId, type JobResult, type JobStatus, type Media, type Metadata, type MetadataAuthor, type MetadataParams, type MetadataPlatform, type MetadataStats, type MetadataType, type PlaylistVideosParams, type PostMedia, type ResourceParams, type Scrape, type SiteMap, Supadata, type SupadataConfig, SupadataError, type Transcript, type TranscriptChunk, type TranscriptOrJobId, type TranscriptParams, TranscriptService, type TranslateParams, type TranslatedTranscript, type VideoIds, type VideoMedia, WebService, YouTubeService, type YoutubeBatchJob, type YoutubeBatchJobStatus, type YoutubeBatchResultItem, type YoutubeBatchResults, type YoutubeBatchSource, type YoutubeBatchStats, type YoutubeChannel, type YoutubePlaylist, type YoutubeSearchChannelResult, type YoutubeSearchDuration, type YoutubeSearchParams, type YoutubeSearchPlaylistResult, type YoutubeSearchResponse, type YoutubeSearchResult, type YoutubeSearchSortBy, type YoutubeSearchType, type YoutubeSearchUploadDate, type YoutubeSearchVideoResult, type YoutubeTranscriptBatchRequest, type YoutubeVideo, type YoutubeVideoBatchRequest };
509
+ export { BaseClient, type CarouselMedia, type ChannelVideosParams, type CrawlJob, type CrawlRequest, type ExtractJobResult, type ExtractParams, ExtractService, type GeneralTranscriptParams, type ImageMedia, type JobId, type JobResult, type JobStatus, type Media, type Metadata, type MetadataAuthor, type MetadataParams, type MetadataPlatform, type MetadataStats, type MetadataType, type PlaylistVideosParams, type PostMedia, type ResourceParams, type Scrape, type SiteMap, Supadata, type SupadataConfig, SupadataError, type Transcript, type TranscriptChunk, type TranscriptOrJobId, type TranscriptParams, TranscriptService, type TranslateParams, type TranslatedTranscript, type VideoIds, type VideoMedia, WebService, YouTubeService, type YoutubeBatchJob, type YoutubeBatchJobStatus, type YoutubeBatchResultItem, type YoutubeBatchResults, type YoutubeBatchSource, type YoutubeBatchStats, type YoutubeChannel, type YoutubePlaylist, type YoutubeSearchChannelResult, type YoutubeSearchDuration, type YoutubeSearchParams, type YoutubeSearchPlaylistResult, type YoutubeSearchResponse, type YoutubeSearchResult, type YoutubeSearchSortBy, type YoutubeSearchType, type YoutubeSearchUploadDate, type YoutubeSearchVideoResult, type YoutubeTranscriptBatchRequest, type YoutubeVideo, type YoutubeVideoBatchRequest };
package/dist/index.d.ts CHANGED
@@ -239,6 +239,22 @@ interface Metadata {
239
239
  createdAt: string;
240
240
  additionalData: Record<string, any>;
241
241
  }
242
+ interface ExtractParams {
243
+ url: string;
244
+ prompt?: string;
245
+ schema?: Record<string, any>;
246
+ }
247
+ interface ExtractJobResult {
248
+ status: JobStatus;
249
+ error?: {
250
+ error: SupadataError['error'];
251
+ message: string;
252
+ details: string;
253
+ documentationUrl?: string;
254
+ } | null;
255
+ data?: Record<string, any>;
256
+ schema?: Record<string, any>;
257
+ }
242
258
 
243
259
  declare class BaseClient {
244
260
  protected config: SupadataConfig;
@@ -441,6 +457,22 @@ declare class TranscriptService extends BaseClient {
441
457
  getJobStatus: (jobId: string) => Promise<JobResult<Transcript>>;
442
458
  }
443
459
 
460
+ declare class ExtractService extends BaseClient {
461
+ /**
462
+ * Start an extract job to analyze video content and extract structured data.
463
+ * @param params - Parameters for the extract job
464
+ * @returns A promise that resolves to a JobId for async processing
465
+ */
466
+ get: (params: ExtractParams) => Promise<JobId>;
467
+ /**
468
+ * Get results for an extract job by job ID.
469
+ * @param jobId - The ID of the extract job
470
+ * @returns A promise that resolves to the extract job result
471
+ * @throws {SupadataError} If jobId is not provided
472
+ */
473
+ getResults: (jobId: string) => Promise<ExtractJobResult>;
474
+ }
475
+
444
476
  interface MetadataParams {
445
477
  url: string;
446
478
  }
@@ -448,6 +480,7 @@ declare class Supadata extends BaseClient {
448
480
  readonly youtube: YouTubeService;
449
481
  readonly web: WebService;
450
482
  private _transcriptService;
483
+ private _extractService;
451
484
  constructor(config: SupadataConfig);
452
485
  /**
453
486
  * Get transcript from a supported video platform (YouTube, TikTok, Instagram, Twitter) or file URL.
@@ -463,6 +496,14 @@ declare class Supadata extends BaseClient {
463
496
  * @returns A promise that resolves to a Metadata object
464
497
  */
465
498
  metadata: (params: MetadataParams) => Promise<Metadata>;
499
+ /**
500
+ * Extract structured data from video content using AI.
501
+ * Returns a job ID for asynchronous processing.
502
+ * Use extract.getResults(jobId) to poll for results.
503
+ */
504
+ extract: ((params: ExtractParams) => Promise<JobId>) & {
505
+ getResults: (jobId: string) => Promise<ExtractJobResult>;
506
+ };
466
507
  }
467
508
 
468
- export { BaseClient, type CarouselMedia, type ChannelVideosParams, type CrawlJob, type CrawlRequest, type GeneralTranscriptParams, type ImageMedia, type JobId, type JobResult, type JobStatus, type Media, type Metadata, type MetadataAuthor, type MetadataParams, type MetadataPlatform, type MetadataStats, type MetadataType, type PlaylistVideosParams, type PostMedia, type ResourceParams, type Scrape, type SiteMap, Supadata, type SupadataConfig, SupadataError, type Transcript, type TranscriptChunk, type TranscriptOrJobId, type TranscriptParams, TranscriptService, type TranslateParams, type TranslatedTranscript, type VideoIds, type VideoMedia, WebService, YouTubeService, type YoutubeBatchJob, type YoutubeBatchJobStatus, type YoutubeBatchResultItem, type YoutubeBatchResults, type YoutubeBatchSource, type YoutubeBatchStats, type YoutubeChannel, type YoutubePlaylist, type YoutubeSearchChannelResult, type YoutubeSearchDuration, type YoutubeSearchParams, type YoutubeSearchPlaylistResult, type YoutubeSearchResponse, type YoutubeSearchResult, type YoutubeSearchSortBy, type YoutubeSearchType, type YoutubeSearchUploadDate, type YoutubeSearchVideoResult, type YoutubeTranscriptBatchRequest, type YoutubeVideo, type YoutubeVideoBatchRequest };
509
+ export { BaseClient, type CarouselMedia, type ChannelVideosParams, type CrawlJob, type CrawlRequest, type ExtractJobResult, type ExtractParams, ExtractService, type GeneralTranscriptParams, type ImageMedia, type JobId, type JobResult, type JobStatus, type Media, type Metadata, type MetadataAuthor, type MetadataParams, type MetadataPlatform, type MetadataStats, type MetadataType, type PlaylistVideosParams, type PostMedia, type ResourceParams, type Scrape, type SiteMap, Supadata, type SupadataConfig, SupadataError, type Transcript, type TranscriptChunk, type TranscriptOrJobId, type TranscriptParams, TranscriptService, type TranslateParams, type TranslatedTranscript, type VideoIds, type VideoMedia, WebService, YouTubeService, type YoutubeBatchJob, type YoutubeBatchJobStatus, type YoutubeBatchResultItem, type YoutubeBatchResults, type YoutubeBatchSource, type YoutubeBatchStats, type YoutubeChannel, type YoutubePlaylist, type YoutubeSearchChannelResult, type YoutubeSearchDuration, type YoutubeSearchParams, type YoutubeSearchPlaylistResult, type YoutubeSearchResponse, type YoutubeSearchResult, type YoutubeSearchSortBy, type YoutubeSearchType, type YoutubeSearchUploadDate, type YoutubeSearchVideoResult, type YoutubeTranscriptBatchRequest, type YoutubeVideo, type YoutubeVideoBatchRequest };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import S from'cross-fetch';var g=fetch||S;var r=class extends Error{error;details;documentationUrl;constructor(e){super(e.message||"An unexpected error occurred"),this.error=e.error||"internal-error",this.details=e.details||"An unexpected error occurred",this.documentationUrl=e.documentationUrl||"",this.name="SupadataError";}};var f={version:"1.3.2"};var P=`supadata-js/${f.version}`,s=class{config;constructor(e){this.config=e;}async fetch(e,t={},a="GET"){let n=`${this.config.baseUrl||"https://api.supadata.ai/v1"}${e.startsWith("/")?e:`/${e}`}`;if(a==="GET"&&Object.keys(t).length>0){let u=new URLSearchParams;Object.entries(t).forEach(([o,l])=>{l!=null&&(Array.isArray(l)?l.forEach(x=>u.append(o,String(x))):u.append(o,String(l)));}),n+=`?${u.toString()}`;}return this.fetchUrl(n,a,t)}async fetchUrl(e,t="GET",a){let i={method:t,headers:{"x-api-key":this.config.apiKey,"Content-Type":"application/json","User-Agent":P}};t==="POST"&&a&&(i.body=JSON.stringify(a));let n=await g(e,i),u=n.headers.get("content-type");if(!n.ok)if(u?.includes("application/json")){let o=await n.json();throw new r(o)}else throw new r({error:"internal-error",message:"Unexpected error response format",details:await n.text()});try{if(!u?.includes("application/json"))throw new r({error:"internal-error",message:"Invalid response format",details:"Expected JSON response but received different content type"});return await n.json()}catch(o){throw new r({error:"internal-error",message:"Failed to parse response",details:o instanceof Error?o.message:"Unknown error"})}}};var b=class extends s{transcript=Object.assign(async e=>this.fetch("/youtube/transcript",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/transcript/batch",e,"POST"))});video=Object.assign(async e=>this.fetch("/youtube/video",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/video/batch",e,"POST"))});channel=Object.assign(async e=>this.fetch("/youtube/channel",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/channel/videos",e))});playlist=Object.assign(async e=>this.fetch("/youtube/playlist",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/playlist/videos",e))});batch={getBatchResults:async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get batch results."});return this.fetch(`/youtube/batch/${e}`)}};translate=async e=>this.fetch("/youtube/transcript/translate",e);search=async e=>{if(!e.query)throw new r({error:"invalid-request",message:"Missing query parameter",details:"The query parameter is required for search."});return this.validateLimit(e,1,5e3,"search"),this.fetch("/youtube/search",e)};validateLimit(e,t=1,a=5e3,i="operation"){if(e.limit!=null&&e.limit!=null&&(e.limit<t||e.limit>a))throw new r({error:"invalid-request",message:`Invalid limit for ${i}.`,details:`The limit must be between ${t} and ${a}.`})}};var h=class extends s{async scrape(e){return this.fetch("/web/scrape",{url:e})}async map(e){return this.fetch("/web/map",{url:e})}async crawl(e){return this.fetch("/web/crawl",e,"POST")}async getCrawlResults(e){let t,a=[],i;do t=await(i?this.fetchUrl(i):this.fetch(`/web/crawl/${e}`)),t.pages&&(a=[...a,...t.pages]),i=t.next;while(i);return t}};var m=class extends s{get=async e=>this.fetch("/transcript",e);getJobStatus=async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get transcript job status."});return this.fetch(`/transcript/${e}`)}};var y=class extends s{youtube;web;_transcriptService;constructor(e){super(e),this.youtube=new b(e),this.web=new h(e),this._transcriptService=new m(e);}transcript=Object.assign(async e=>this._transcriptService.get(e),{getJobStatus:e=>this._transcriptService.getJobStatus(e)});metadata=async e=>this.fetch("/metadata",e)};
2
- export{s as BaseClient,y as Supadata,r as SupadataError,m as TranscriptService,h as WebService,b as YouTubeService};//# sourceMappingURL=index.mjs.map
1
+ import T from'cross-fetch';var f=fetch||T;var r=class extends Error{error;details;documentationUrl;constructor(e){super(e.message||"An unexpected error occurred"),this.error=e.error||"internal-error",this.details=e.details||"An unexpected error occurred",this.documentationUrl=e.documentationUrl||"",this.name="SupadataError";}};var y={version:"1.4.0"};var v=`supadata-js/${y.version}`,a=class{config;constructor(e){this.config=e;}async fetch(e,t={},s="GET"){let n=`${this.config.baseUrl||"https://api.supadata.ai/v1"}${e.startsWith("/")?e:`/${e}`}`;if(s==="GET"&&Object.keys(t).length>0){let l=new URLSearchParams;Object.entries(t).forEach(([o,p])=>{p!=null&&(Array.isArray(p)?p.forEach(S=>l.append(o,String(S))):l.append(o,String(p)));}),n+=`?${l.toString()}`;}return this.fetchUrl(n,s,t)}async fetchUrl(e,t="GET",s){let i={method:t,headers:{"x-api-key":this.config.apiKey,"Content-Type":"application/json","User-Agent":v}};t==="POST"&&s&&(i.body=JSON.stringify(s));let n=await f(e,i),l=n.headers.get("content-type");if(!n.ok)if(l?.includes("application/json")){let o=await n.json();throw new r(o)}else throw new r({error:"internal-error",message:"Unexpected error response format",details:await n.text()});try{if(!l?.includes("application/json"))throw new r({error:"internal-error",message:"Invalid response format",details:"Expected JSON response but received different content type"});return await n.json()}catch(o){throw new r({error:"internal-error",message:"Failed to parse response",details:o instanceof Error?o.message:"Unknown error"})}}};var g=class extends a{transcript=Object.assign(async e=>this.fetch("/youtube/transcript",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/transcript/batch",e,"POST"))});video=Object.assign(async e=>this.fetch("/youtube/video",e),{batch:async e=>(this.validateLimit(e,1,5e3,"batch operation"),this.fetch("/youtube/video/batch",e,"POST"))});channel=Object.assign(async e=>this.fetch("/youtube/channel",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/channel/videos",e))});playlist=Object.assign(async e=>this.fetch("/youtube/playlist",e),{videos:async e=>(this.validateLimit(e),this.fetch("/youtube/playlist/videos",e))});batch={getBatchResults:async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get batch results."});return this.fetch(`/youtube/batch/${e}`)}};translate=async e=>this.fetch("/youtube/transcript/translate",e);search=async e=>{if(!e.query)throw new r({error:"invalid-request",message:"Missing query parameter",details:"The query parameter is required for search."});return this.validateLimit(e,1,5e3,"search"),this.fetch("/youtube/search",e)};validateLimit(e,t=1,s=5e3,i="operation"){if(e.limit!=null&&e.limit!=null&&(e.limit<t||e.limit>s))throw new r({error:"invalid-request",message:`Invalid limit for ${i}.`,details:`The limit must be between ${t} and ${s}.`})}};var h=class extends a{async scrape(e){return this.fetch("/web/scrape",{url:e})}async map(e){return this.fetch("/web/map",{url:e})}async crawl(e){return this.fetch("/web/crawl",e,"POST")}async getCrawlResults(e){let t,s=[],i;do t=await(i?this.fetchUrl(i):this.fetch(`/web/crawl/${e}`)),t.pages&&(s=[...s,...t.pages]),i=t.next;while(i);return t}};var m=class extends a{get=async e=>this.fetch("/transcript",e);getJobStatus=async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get transcript job status."});return this.fetch(`/transcript/${e}`)}};var b=class extends a{get=async e=>this.fetch("/extract",e,"POST");getResults=async e=>{if(!e)throw new r({error:"invalid-request",message:"Missing jobId",details:"The jobId parameter is required to get extract job results."});return this.fetch(`/extract/${e}`)}};var x=class extends a{youtube;web;_transcriptService;_extractService;constructor(e){super(e),this.youtube=new g(e),this.web=new h(e),this._transcriptService=new m(e),this._extractService=new b(e);}transcript=Object.assign(async e=>this._transcriptService.get(e),{getJobStatus:e=>this._transcriptService.getJobStatus(e)});metadata=async e=>this.fetch("/metadata",e);extract=Object.assign(async e=>this._extractService.get(e),{getResults:e=>this._extractService.getResults(e)})};
2
+ export{a as BaseClient,b as ExtractService,x as Supadata,r as SupadataError,m as TranscriptService,h as WebService,g as YouTubeService};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/polly-fetch.ts","../src/types.ts","../package.json","../src/client.ts","../src/services/youtube.ts","../src/services/web.ts","../src/services/transcript.ts","../src/index.ts"],"names":["polly_fetch_default","crossFetch","SupadataError","error","package_default","USER_AGENT","BaseClient","config","endpoint","params","method","url","queryParams","key","value","item","body","options","response","contentType","errorData","YouTubeService","jobId","min","max","operation","WebService","request","pages","nextUrl","TranscriptService","Supadata"],"mappings":"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","file":"index.mjs","sourcesContent":["import crossFetch from 'cross-fetch';\n\nexport default fetch || crossFetch","export interface TranscriptChunk {\n text: string;\n offset: number;\n duration: number;\n lang: string;\n}\n\nexport interface Transcript {\n content: TranscriptChunk[] | string;\n lang: string;\n availableLangs: string[];\n}\n\nexport interface TranslatedTranscript {\n content: TranscriptChunk[] | string;\n lang: string;\n}\n\nexport interface Scrape {\n url: string;\n content: string;\n name: string;\n description: string;\n ogUrl: string;\n countCharacters: number;\n urls: string[];\n}\n\nexport interface SiteMap {\n urls: string[];\n}\n\nexport interface CrawlRequest {\n url: string;\n limit?: number;\n}\n\nexport interface CrawlJob {\n status: 'scraping' | 'completed' | 'failed' | 'cancelled';\n pages?: Scrape[];\n next?: string;\n}\n\nexport interface SupadataConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class SupadataError extends Error {\n error:\n | 'invalid-request'\n | 'internal-error'\n | 'transcript-unavailable'\n | 'not-found'\n | 'unauthorized'\n | 'upgrade-required'\n | 'limit-exceeded';\n details: string;\n documentationUrl: string;\n\n constructor(error: {\n error: SupadataError['error'];\n message?: string;\n details?: string;\n documentationUrl?: string;\n }) {\n super(error.message || 'An unexpected error occurred');\n this.error = error.error || 'internal-error';\n this.details = error.details || 'An unexpected error occurred';\n this.documentationUrl = error.documentationUrl || '';\n this.name = 'SupadataError';\n }\n}\n\nexport interface YoutubeVideo {\n id: string;\n title: string;\n description: string;\n duration: number;\n channel: {\n id: string;\n name: string;\n };\n tags: string[];\n thumbnail: string;\n uploadDate: string;\n viewCount: number;\n likeCount: number;\n transcriptLanguages: string[];\n}\n\nexport interface YoutubeChannel {\n id: string;\n name: string;\n handle: string;\n description: string;\n subscriberCount: number;\n videoCount: number;\n thumbnail: string;\n banner: string;\n}\n\nexport interface YoutubePlaylist {\n id: string;\n title: string;\n videoCount: number;\n viewCount: number;\n lastUpdated: string;\n description: string;\n thumbnail: string;\n}\n\nexport interface YoutubeBatchSource {\n videoIds?: string[];\n playlistId?: string;\n channelId?: string;\n limit?: number;\n}\n\nexport interface YoutubeTranscriptBatchRequest extends YoutubeBatchSource {\n lang?: string;\n text?: boolean;\n}\n\nexport interface YoutubeVideoBatchRequest extends YoutubeBatchSource {}\n\nexport interface JobId {\n jobId: string;\n}\n\nexport interface YoutubeBatchJob extends JobId {}\n\nexport type JobStatus = 'queued' | 'active' | 'completed' | 'failed';\n\nexport type YoutubeBatchJobStatus = JobStatus;\n\nexport interface YoutubeBatchResultItem {\n videoId: string;\n transcript?: Transcript;\n video?: YoutubeVideo;\n errorCode?: string;\n}\n\nexport interface YoutubeBatchStats {\n total: number;\n succeeded: number;\n failed: number;\n}\n\nexport interface YoutubeBatchResults {\n status: YoutubeBatchJobStatus;\n results?: YoutubeBatchResultItem[];\n stats?: YoutubeBatchStats;\n completedAt?: string;\n}\n\nexport type TranscriptOrJobId = Transcript | JobId;\n\nexport interface JobResult<T = any> {\n status: JobStatus;\n result?: T | null;\n error?: {\n error: SupadataError['error'];\n message: string;\n details: string;\n documentationUrl?: string;\n } | null;\n}\n\n// YouTube Search Types\nexport type YoutubeSearchUploadDate =\n | 'all'\n | 'hour'\n | 'today'\n | 'week'\n | 'month'\n | 'year';\nexport type YoutubeSearchType =\n | 'all'\n | 'video'\n | 'channel'\n | 'playlist'\n | 'movie';\nexport type YoutubeSearchDuration = 'all' | 'short' | 'medium' | 'long';\nexport type YoutubeSearchSortBy = 'relevance' | 'rating' | 'date' | 'views';\n\nexport interface YoutubeSearchParams {\n query: string;\n uploadDate?: YoutubeSearchUploadDate;\n type?: YoutubeSearchType;\n duration?: YoutubeSearchDuration;\n sortBy?: YoutubeSearchSortBy;\n features?: string[];\n limit?: number;\n nextPageToken?: string;\n}\n\nexport interface YoutubeSearchVideoResult {\n type: 'video';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n duration: number;\n viewCount: number;\n uploadDate: string;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport interface YoutubeSearchChannelResult {\n type: 'channel';\n id: string;\n name: string;\n handle: string;\n description: string;\n thumbnail: string;\n subscriberCount: number;\n videoCount: number;\n}\n\nexport interface YoutubeSearchPlaylistResult {\n type: 'playlist';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n videoCount: number;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport type YoutubeSearchResult =\n | YoutubeSearchVideoResult\n | YoutubeSearchChannelResult\n | YoutubeSearchPlaylistResult;\n\nexport interface YoutubeSearchResponse {\n query: string;\n results: YoutubeSearchResult[];\n totalResults: number;\n nextPageToken?: string;\n}\n\n// Metadata Types\nexport type MetadataPlatform = 'youtube' | 'tiktok' | 'instagram' | 'twitter';\nexport type MetadataType = 'video' | 'image' | 'carousel' | 'post';\n\nexport interface MetadataAuthor {\n username: string;\n displayName: string;\n avatarUrl: string;\n verified: boolean;\n}\n\nexport interface MetadataStats {\n views: number | null;\n likes: number | null;\n comments: number | null;\n shares: number | null;\n}\n\nexport interface VideoMedia {\n type: 'video';\n url: string;\n duration: number;\n width: number;\n height: number;\n thumbnailUrl: string;\n}\n\nexport interface ImageMedia {\n type: 'image';\n url: string;\n width: number;\n height: number;\n}\n\nexport interface CarouselMedia {\n type: 'carousel';\n items: Array<VideoMedia | ImageMedia>;\n}\n\nexport interface PostMedia {\n type: 'post';\n text: string;\n}\n\nexport type Media = VideoMedia | ImageMedia | CarouselMedia | PostMedia;\n\nexport interface Metadata {\n platform: MetadataPlatform;\n type: MetadataType;\n id: string;\n url: string;\n title: string | null;\n description: string | null;\n author: MetadataAuthor;\n stats: MetadataStats;\n media: Media;\n tags: string[];\n createdAt: string;\n additionalData: Record<string, any>;\n}\n","{\n \"name\": \"@supadata/js\",\n \"version\": \"1.3.2\",\n \"description\": \"TypeScript / JavaScript SDK for Supadata API\",\n \"homepage\": \"https://supadata.ai\",\n \"repository\": \"https://github.com/supadata-ai/js\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\",\n \"default\": \"./dist/index.mjs\"\n }\n },\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"test\": \"node --experimental-vm-modules node_modules/jest/bin/jest.js\",\n \"prepare\": \"npm run build\",\n \"format\": \"prettier --write \\\"src/**/*.{js,ts}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{js,ts}\\\"\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"keywords\": [\n \"supadata\",\n \"api\",\n \"sdk\",\n \"typescript\",\n \"youtube\",\n \"tiktok\",\n \"instagram\",\n \"twitter\",\n \"transcript\",\n \"web scraping\"\n ],\n \"author\": \"Supadata AI\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"dependencies\": {\n \"cross-fetch\": \"^4.0.0\"\n },\n \"devDependencies\": {\n \"@types/jest\": \"^29.5.14\",\n \"@types/node\": \"^22.10.10\",\n \"jest\": \"^29.7.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.4.2\",\n \"ts-jest\": \"^29.2.5\",\n \"typescript\": \"^5.7.3\",\n \"tsup\": \"^8.3.6\"\n }\n}","import fetch from './polly-fetch';\nimport { SupadataConfig, SupadataError } from './types.js';\n// @ts-expect-error: Non-TS import for version from package.json\nimport pkg from '../package.json';\n\nconst USER_AGENT = `supadata-js/${pkg.version}`;\n\nexport class BaseClient {\n protected config: SupadataConfig;\n\n constructor(config: SupadataConfig) {\n this.config = config;\n }\n\n protected async fetch<T>(\n endpoint: string,\n params: Record<string, any> = {},\n method: 'GET' | 'POST' = 'GET'\n ): Promise<T> {\n const baseUrl = this.config.baseUrl || 'https://api.supadata.ai/v1';\n let url = `${baseUrl}${\n endpoint.startsWith('/') ? endpoint : `/${endpoint}`\n }`;\n\n if (method === 'GET' && Object.keys(params).length > 0) {\n const queryParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => queryParams.append(key, String(item)));\n } else {\n queryParams.append(key, String(value));\n }\n }\n });\n url += `?${queryParams.toString()}`;\n }\n\n return this.fetchUrl<T>(url, method, params);\n }\n\n protected async fetchUrl<T>(\n url: string,\n method: 'GET' | 'POST' = 'GET',\n body?: Record<string, any>\n ): Promise<T> {\n const options: RequestInit = {\n method,\n headers: {\n 'x-api-key': this.config.apiKey,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n };\n\n if (method === 'POST' && body) {\n options.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, options);\n\n const contentType = response.headers.get('content-type');\n\n if (!response.ok) {\n // Handle standard API errors\n if (contentType?.includes('application/json')) {\n const errorData = await response.json();\n throw new SupadataError(errorData);\n } else {\n // Fallback for unexpected non-JSON errors\n throw new SupadataError({\n error: 'internal-error',\n message: 'Unexpected error response format',\n details: await response.text(),\n });\n }\n }\n\n try {\n if (!contentType?.includes('application/json')) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Invalid response format',\n details: 'Expected JSON response but received different content type',\n });\n }\n\n return (await response.json()) as T;\n } catch (error) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Failed to parse response',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n SupadataError,\n Transcript,\n TranslatedTranscript,\n YoutubeBatchJob,\n YoutubeBatchResults,\n YoutubeChannel,\n YoutubePlaylist,\n YoutubeTranscriptBatchRequest,\n YoutubeVideo,\n YoutubeVideoBatchRequest,\n YoutubeSearchParams,\n YoutubeSearchResponse,\n} from '../types.js';\n\n/**\n * Ensures exactly one property from the specified keys is provided.\n * @example\n * // Valid: { url: \"...\" } or { videoId: \"...\" }\n * // Invalid: {} or { url: \"...\", videoId: \"...\" }\n */\ntype ExactlyOne<T, Keys extends keyof T> = {\n [K in Keys]: { [P in K]-?: T[P] } & { [P in Exclude<Keys, K>]?: never };\n}[Keys] &\n Omit<T, Keys>;\n\nexport type TranscriptParams = {\n lang?: string;\n text?: boolean;\n} & ExactlyOne<{ videoId: string; url: string }, 'videoId' | 'url'>;\n\nexport interface TranslateParams extends Omit<TranscriptParams, 'lang'> {\n lang: string;\n}\n\nexport interface ResourceParams {\n id: string;\n}\n\nexport interface ChannelVideosParams extends ResourceParams {\n limit?: number;\n type?: 'video' | 'short' | 'live' | 'all';\n}\n\nexport interface PlaylistVideosParams extends ResourceParams {\n limit?: number;\n}\n\nexport interface VideoIds {\n videoIds: string[];\n shortIds: string[];\n liveIds: string[];\n}\n\nexport class YouTubeService extends BaseClient {\n /**\n * Handles YouTube Transcript operations.\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n transcript = Object.assign(\n /**\n * Fetches a transcript for a YouTube video.\n * @param params - Parameters for fetching the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The language code for the transcript (optional)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a Transcript object\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n async (params: TranscriptParams): Promise<Transcript> => {\n return this.fetch<Transcript>('/youtube/transcript', params);\n },\n {\n /**\n * Batch fetches transcripts for multiple YouTube videos.\n * @param params - Parameters for the transcript batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch transcripts for\n * @param params.lang - The language code for the transcripts (optional)\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeTranscriptBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/transcript/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube video operations.\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n video = Object.assign(\n /**\n * Fetches a YouTube video based on the provided parameters.\n * @param params - The parameters required to fetch the YouTube video\n * @param params.id - The YouTube video ID\n * @returns A promise that resolves to a YoutubeVideo object\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n async (params: ResourceParams): Promise<YoutubeVideo> => {\n return this.fetch<YoutubeVideo>('/youtube/video', params);\n },\n {\n /**\n * Batch fetches metadata for multiple YouTube videos.\n * @param params - Parameters for the video metadata batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch metadata for\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeVideoBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/video/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube channel operations.\n */\n channel = Object.assign(\n /**\n * Fetches YouTube channel information.\n * @param params - The parameters required to fetch the YouTube channel information\n * @param params.id - The YouTube channel ID\n * @returns A promise that resolves to a YoutubeChannel object containing the channel information\n */\n async (params: ResourceParams): Promise<YoutubeChannel> => {\n return this.fetch<YoutubeChannel>('/youtube/channel', params);\n },\n {\n /**\n * Fetches the videos of a YouTube channel.\n * @param params - The parameters required to fetch the YouTube channel videos\n * @param params.id - The YouTube channel ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @param params.type - The type of videos to fetch ('video', 'short', 'live', or 'all', default: 'video')\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: ChannelVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/channel/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube playlist operations.\n */\n playlist = Object.assign(\n /**\n * Fetches a YouTube playlist.\n * @param params - The parameters required to fetch the playlist\n * @param params.id - The YouTube playlist ID\n * @returns A promise that resolves to a YoutubePlaylist object\n */\n async (params: ResourceParams): Promise<YoutubePlaylist> => {\n return this.fetch<YoutubePlaylist>('/youtube/playlist', params);\n },\n {\n /**\n * Fetches the videos of a YouTube playlist.\n * @param params - The parameters required to fetch the playlist videos\n * @param params.id - The YouTube playlist ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: PlaylistVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/playlist/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube batch operations.\n */\n batch = {\n /**\n * Retrieves the status and results of a batch job.\n * @param jobId - The ID of the batch job\n * @returns A promise that resolves to the YoutubeBatchResults containing job status and results\n * @throws {SupadataError} If jobId is not provided\n */\n getBatchResults: async (jobId: string): Promise<YoutubeBatchResults> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details: 'The jobId parameter is required to get batch results.',\n });\n }\n return this.fetch<YoutubeBatchResults>(`/youtube/batch/${jobId}`);\n },\n };\n\n /**\n * Translates a YouTube video transcript to a specified language.\n * @param params - Parameters for translating the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The target language code for translation\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a TranslatedTranscript object\n */\n translate = async (\n params: TranslateParams\n ): Promise<TranslatedTranscript> => {\n return this.fetch<TranslatedTranscript>(\n '/youtube/transcript/translate',\n params\n );\n };\n\n /**\n * Search YouTube for videos, channels, and playlists with advanced filters.\n * @param params - Parameters for the search\n * @param params.query - The search query string\n * @param params.uploadDate - Filter by upload date (\"all\", \"hour\", \"today\", \"week\", \"month\", \"year\")\n * @param params.type - Filter by content type (\"all\", \"video\", \"channel\", \"playlist\", \"movie\")\n * @param params.duration - Filter video length (\"all\", \"short\", \"medium\", \"long\")\n * @param params.sortBy - Sort results by (\"relevance\", \"rating\", \"date\", \"views\")\n * @param params.features - Array of special video features\n * @param params.limit - Maximum results to return\n * @param params.nextPageToken - Token for pagination\n * @returns A promise that resolves to a YoutubeSearchResponse object\n */\n search = async (\n params: YoutubeSearchParams\n ): Promise<YoutubeSearchResponse> => {\n if (!params.query) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing query parameter',\n details: 'The query parameter is required for search.',\n });\n }\n\n this.validateLimit(params, 1, 5000, 'search');\n\n return this.fetch<YoutubeSearchResponse>('/youtube/search', params);\n };\n\n private validateLimit(\n params: { limit?: number },\n min: number = 1,\n max: number = 5000,\n operation: string = 'operation'\n ) {\n if (\n params.limit != undefined &&\n params.limit != null &&\n (params.limit < min || params.limit > max)\n ) {\n throw new SupadataError({\n error: 'invalid-request',\n message: `Invalid limit for ${operation}.`,\n details: `The limit must be between ${min} and ${max}.`,\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport { CrawlJob, CrawlRequest, JobId, Scrape, SiteMap } from '../types.js';\n\nexport class WebService extends BaseClient {\n /**\n * Extract content from any web page to Markdown format.\n *\n * @param url - URL of the webpage to scrape\n * @returns A promise that resolves to the scraped content\n */\n async scrape(url: string): Promise<Scrape> {\n return this.fetch<Scrape>('/web/scrape', { url });\n }\n\n /**\n * Extract all links found on a webpage.\n *\n * @param url - URL of the webpage to map\n * @returns A promise that resolves to a map of URLs found on the page\n */\n async map(url: string): Promise<SiteMap> {\n return this.fetch<SiteMap>('/web/map', { url });\n }\n\n /**\n * Create a crawl job to extract content from all pages on a website.\n *\n * @param request - Crawl request parameters\n * @param request.url - URL of the website to crawl\n * @param request.limit - Maximum number of pages to crawl (default: 100, max: 5000)\n * @returns A promise that resolves to the crawl job id\n */\n async crawl(request: CrawlRequest): Promise<JobId> {\n return this.fetch<JobId>('/web/crawl', request, 'POST');\n }\n\n /**\n * Get the status and results of a crawl job.\n * Automatically handles pagination to retrieve all pages from the crawl.\n *\n * @param jobId - The ID of the crawl job to retrieve\n * @returns A promise that resolves to the complete crawl job results\n */\n async getCrawlResults(jobId: string): Promise<CrawlJob> {\n let response: CrawlJob;\n let pages: Scrape[] = [];\n let nextUrl: string | undefined;\n\n do {\n response = await (nextUrl\n ? this.fetchUrl<CrawlJob>(nextUrl)\n : this.fetch<CrawlJob>(`/web/crawl/${jobId}`));\n\n if (response.pages) {\n pages = [...pages, ...response.pages];\n }\n nextUrl = response.next;\n } while (nextUrl);\n\n return response;\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n JobId,\n JobResult,\n SupadataError,\n Transcript,\n TranscriptOrJobId,\n} from '../types.js';\n\nexport interface GeneralTranscriptParams {\n url: string;\n lang?: string;\n text?: boolean;\n chunkSize?: number;\n mode?: 'native' | 'auto' | 'generate';\n}\n\nexport class TranscriptService extends BaseClient {\n /**\n * Get transcript from a supported video platform or file URL.\n * @param params - Parameters for fetching the transcript\n * @returns A promise that resolves to either a Transcript or JobId for async processing\n */\n get = async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this.fetch<TranscriptOrJobId>('/transcript', params);\n };\n\n /**\n * Get results for a transcript job by job ID.\n * @param jobId - The ID of the transcript job\n * @returns A promise that resolves to the job result containing status and transcript if completed\n * @throws {SupadataError} If jobId is not provided\n */\n getJobStatus = async (jobId: string): Promise<JobResult<Transcript>> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details:\n 'The jobId parameter is required to get transcript job status.',\n });\n }\n return this.fetch<JobResult<Transcript>>(`/transcript/${jobId}`);\n };\n}\n","import {\n JobResult,\n Metadata,\n SupadataConfig,\n Transcript,\n TranscriptOrJobId,\n} from './types.js';\nimport { YouTubeService } from './services/youtube.js';\nimport { WebService } from './services/web.js';\nimport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\nimport { BaseClient } from './client.js';\n\nexport * from './types.js';\nexport * from './client.js';\nexport * from './services/youtube.js';\nexport * from './services/web.js';\nexport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\n\nexport interface MetadataParams {\n url: string;\n}\n\nexport class Supadata extends BaseClient {\n readonly youtube: YouTubeService;\n readonly web: WebService;\n private _transcriptService: TranscriptService;\n\n constructor(config: SupadataConfig) {\n super(config);\n this.youtube = new YouTubeService(config);\n this.web = new WebService(config);\n this._transcriptService = new TranscriptService(config);\n }\n\n /**\n * Get transcript from a supported video platform (YouTube, TikTok, Instagram, Twitter) or file URL.\n * If the video is too large to return transcript immediately, request returns a job ID.\n */\n transcript = Object.assign(\n async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this._transcriptService.get(params);\n },\n {\n getJobStatus: (jobId: string): Promise<JobResult<Transcript>> => {\n return this._transcriptService.getJobStatus(jobId);\n },\n }\n );\n\n /**\n * Get metadata from any supported platform (YouTube, TikTok, Instagram, Twitter).\n * @param params - Parameters for fetching metadata\n * @param params.url - Media URL from YouTube, TikTok, Instagram, or Twitter\n * @returns A promise that resolves to a Metadata object\n */\n metadata = async (params: MetadataParams): Promise<Metadata> => {\n return this.fetch<Metadata>('/metadata', params);\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/polly-fetch.ts","../src/types.ts","../package.json","../src/client.ts","../src/services/youtube.ts","../src/services/web.ts","../src/services/transcript.ts","../src/services/extract.ts","../src/index.ts"],"names":["polly_fetch_default","crossFetch","SupadataError","error","package_default","USER_AGENT","BaseClient","config","endpoint","params","method","url","queryParams","key","value","item","body","options","response","contentType","errorData","YouTubeService","jobId","min","max","operation","WebService","request","pages","nextUrl","TranscriptService","ExtractService","Supadata"],"mappings":"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","file":"index.mjs","sourcesContent":["import crossFetch from 'cross-fetch';\n\nexport default fetch || crossFetch","export interface TranscriptChunk {\n text: string;\n offset: number;\n duration: number;\n lang: string;\n}\n\nexport interface Transcript {\n content: TranscriptChunk[] | string;\n lang: string;\n availableLangs: string[];\n}\n\nexport interface TranslatedTranscript {\n content: TranscriptChunk[] | string;\n lang: string;\n}\n\nexport interface Scrape {\n url: string;\n content: string;\n name: string;\n description: string;\n ogUrl: string;\n countCharacters: number;\n urls: string[];\n}\n\nexport interface SiteMap {\n urls: string[];\n}\n\nexport interface CrawlRequest {\n url: string;\n limit?: number;\n}\n\nexport interface CrawlJob {\n status: 'scraping' | 'completed' | 'failed' | 'cancelled';\n pages?: Scrape[];\n next?: string;\n}\n\nexport interface SupadataConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class SupadataError extends Error {\n error:\n | 'invalid-request'\n | 'internal-error'\n | 'transcript-unavailable'\n | 'not-found'\n | 'unauthorized'\n | 'upgrade-required'\n | 'limit-exceeded';\n details: string;\n documentationUrl: string;\n\n constructor(error: {\n error: SupadataError['error'];\n message?: string;\n details?: string;\n documentationUrl?: string;\n }) {\n super(error.message || 'An unexpected error occurred');\n this.error = error.error || 'internal-error';\n this.details = error.details || 'An unexpected error occurred';\n this.documentationUrl = error.documentationUrl || '';\n this.name = 'SupadataError';\n }\n}\n\nexport interface YoutubeVideo {\n id: string;\n title: string;\n description: string;\n duration: number;\n channel: {\n id: string;\n name: string;\n };\n tags: string[];\n thumbnail: string;\n uploadDate: string;\n viewCount: number;\n likeCount: number;\n transcriptLanguages: string[];\n}\n\nexport interface YoutubeChannel {\n id: string;\n name: string;\n handle: string;\n description: string;\n subscriberCount: number;\n videoCount: number;\n thumbnail: string;\n banner: string;\n}\n\nexport interface YoutubePlaylist {\n id: string;\n title: string;\n videoCount: number;\n viewCount: number;\n lastUpdated: string;\n description: string;\n thumbnail: string;\n}\n\nexport interface YoutubeBatchSource {\n videoIds?: string[];\n playlistId?: string;\n channelId?: string;\n limit?: number;\n}\n\nexport interface YoutubeTranscriptBatchRequest extends YoutubeBatchSource {\n lang?: string;\n text?: boolean;\n}\n\nexport interface YoutubeVideoBatchRequest extends YoutubeBatchSource {}\n\nexport interface JobId {\n jobId: string;\n}\n\nexport interface YoutubeBatchJob extends JobId {}\n\nexport type JobStatus = 'queued' | 'active' | 'completed' | 'failed';\n\nexport type YoutubeBatchJobStatus = JobStatus;\n\nexport interface YoutubeBatchResultItem {\n videoId: string;\n transcript?: Transcript;\n video?: YoutubeVideo;\n errorCode?: string;\n}\n\nexport interface YoutubeBatchStats {\n total: number;\n succeeded: number;\n failed: number;\n}\n\nexport interface YoutubeBatchResults {\n status: YoutubeBatchJobStatus;\n results?: YoutubeBatchResultItem[];\n stats?: YoutubeBatchStats;\n completedAt?: string;\n}\n\nexport type TranscriptOrJobId = Transcript | JobId;\n\nexport interface JobResult<T = any> {\n status: JobStatus;\n result?: T | null;\n error?: {\n error: SupadataError['error'];\n message: string;\n details: string;\n documentationUrl?: string;\n } | null;\n}\n\n// YouTube Search Types\nexport type YoutubeSearchUploadDate =\n | 'all'\n | 'hour'\n | 'today'\n | 'week'\n | 'month'\n | 'year';\nexport type YoutubeSearchType =\n | 'all'\n | 'video'\n | 'channel'\n | 'playlist'\n | 'movie';\nexport type YoutubeSearchDuration = 'all' | 'short' | 'medium' | 'long';\nexport type YoutubeSearchSortBy = 'relevance' | 'rating' | 'date' | 'views';\n\nexport interface YoutubeSearchParams {\n query: string;\n uploadDate?: YoutubeSearchUploadDate;\n type?: YoutubeSearchType;\n duration?: YoutubeSearchDuration;\n sortBy?: YoutubeSearchSortBy;\n features?: string[];\n limit?: number;\n nextPageToken?: string;\n}\n\nexport interface YoutubeSearchVideoResult {\n type: 'video';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n duration: number;\n viewCount: number;\n uploadDate: string;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport interface YoutubeSearchChannelResult {\n type: 'channel';\n id: string;\n name: string;\n handle: string;\n description: string;\n thumbnail: string;\n subscriberCount: number;\n videoCount: number;\n}\n\nexport interface YoutubeSearchPlaylistResult {\n type: 'playlist';\n id: string;\n title: string;\n description: string;\n thumbnail: string;\n videoCount: number;\n channel: {\n id: string;\n name: string;\n };\n}\n\nexport type YoutubeSearchResult =\n | YoutubeSearchVideoResult\n | YoutubeSearchChannelResult\n | YoutubeSearchPlaylistResult;\n\nexport interface YoutubeSearchResponse {\n query: string;\n results: YoutubeSearchResult[];\n totalResults: number;\n nextPageToken?: string;\n}\n\n// Metadata Types\nexport type MetadataPlatform = 'youtube' | 'tiktok' | 'instagram' | 'twitter';\nexport type MetadataType = 'video' | 'image' | 'carousel' | 'post';\n\nexport interface MetadataAuthor {\n username: string;\n displayName: string;\n avatarUrl: string;\n verified: boolean;\n}\n\nexport interface MetadataStats {\n views: number | null;\n likes: number | null;\n comments: number | null;\n shares: number | null;\n}\n\nexport interface VideoMedia {\n type: 'video';\n url: string;\n duration: number;\n width: number;\n height: number;\n thumbnailUrl: string;\n}\n\nexport interface ImageMedia {\n type: 'image';\n url: string;\n width: number;\n height: number;\n}\n\nexport interface CarouselMedia {\n type: 'carousel';\n items: Array<VideoMedia | ImageMedia>;\n}\n\nexport interface PostMedia {\n type: 'post';\n text: string;\n}\n\nexport type Media = VideoMedia | ImageMedia | CarouselMedia | PostMedia;\n\nexport interface Metadata {\n platform: MetadataPlatform;\n type: MetadataType;\n id: string;\n url: string;\n title: string | null;\n description: string | null;\n author: MetadataAuthor;\n stats: MetadataStats;\n media: Media;\n tags: string[];\n createdAt: string;\n additionalData: Record<string, any>;\n}\n\n// Extract Types\nexport interface ExtractParams {\n url: string;\n prompt?: string;\n schema?: Record<string, any>;\n}\n\nexport interface ExtractJobResult {\n status: JobStatus;\n error?: {\n error: SupadataError['error'];\n message: string;\n details: string;\n documentationUrl?: string;\n } | null;\n data?: Record<string, any>;\n schema?: Record<string, any>;\n}\n","{\n \"name\": \"@supadata/js\",\n \"version\": \"1.4.0\",\n \"description\": \"TypeScript / JavaScript SDK for Supadata API\",\n \"homepage\": \"https://supadata.ai\",\n \"repository\": \"https://github.com/supadata-ai/js\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\",\n \"default\": \"./dist/index.mjs\"\n }\n },\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"test\": \"node --experimental-vm-modules node_modules/jest/bin/jest.js\",\n \"prepare\": \"npm run build\",\n \"format\": \"prettier --write \\\"src/**/*.{js,ts}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{js,ts}\\\"\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"keywords\": [\n \"supadata\",\n \"api\",\n \"sdk\",\n \"typescript\",\n \"youtube\",\n \"tiktok\",\n \"instagram\",\n \"twitter\",\n \"transcript\",\n \"web scraping\"\n ],\n \"author\": \"Supadata AI\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"dependencies\": {\n \"cross-fetch\": \"^4.0.0\"\n },\n \"devDependencies\": {\n \"@types/jest\": \"^29.5.14\",\n \"@types/node\": \"^22.10.10\",\n \"jest\": \"^29.7.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.4.2\",\n \"ts-jest\": \"^29.2.5\",\n \"typescript\": \"^5.7.3\",\n \"tsup\": \"^8.3.6\"\n }\n}","import fetch from './polly-fetch';\nimport { SupadataConfig, SupadataError } from './types.js';\n// @ts-expect-error: Non-TS import for version from package.json\nimport pkg from '../package.json';\n\nconst USER_AGENT = `supadata-js/${pkg.version}`;\n\nexport class BaseClient {\n protected config: SupadataConfig;\n\n constructor(config: SupadataConfig) {\n this.config = config;\n }\n\n protected async fetch<T>(\n endpoint: string,\n params: Record<string, any> = {},\n method: 'GET' | 'POST' = 'GET'\n ): Promise<T> {\n const baseUrl = this.config.baseUrl || 'https://api.supadata.ai/v1';\n let url = `${baseUrl}${\n endpoint.startsWith('/') ? endpoint : `/${endpoint}`\n }`;\n\n if (method === 'GET' && Object.keys(params).length > 0) {\n const queryParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => queryParams.append(key, String(item)));\n } else {\n queryParams.append(key, String(value));\n }\n }\n });\n url += `?${queryParams.toString()}`;\n }\n\n return this.fetchUrl<T>(url, method, params);\n }\n\n protected async fetchUrl<T>(\n url: string,\n method: 'GET' | 'POST' = 'GET',\n body?: Record<string, any>\n ): Promise<T> {\n const options: RequestInit = {\n method,\n headers: {\n 'x-api-key': this.config.apiKey,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n };\n\n if (method === 'POST' && body) {\n options.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, options);\n\n const contentType = response.headers.get('content-type');\n\n if (!response.ok) {\n // Handle standard API errors\n if (contentType?.includes('application/json')) {\n const errorData = await response.json();\n throw new SupadataError(errorData);\n } else {\n // Fallback for unexpected non-JSON errors\n throw new SupadataError({\n error: 'internal-error',\n message: 'Unexpected error response format',\n details: await response.text(),\n });\n }\n }\n\n try {\n if (!contentType?.includes('application/json')) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Invalid response format',\n details: 'Expected JSON response but received different content type',\n });\n }\n\n return (await response.json()) as T;\n } catch (error) {\n throw new SupadataError({\n error: 'internal-error',\n message: 'Failed to parse response',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n SupadataError,\n Transcript,\n TranslatedTranscript,\n YoutubeBatchJob,\n YoutubeBatchResults,\n YoutubeChannel,\n YoutubePlaylist,\n YoutubeTranscriptBatchRequest,\n YoutubeVideo,\n YoutubeVideoBatchRequest,\n YoutubeSearchParams,\n YoutubeSearchResponse,\n} from '../types.js';\n\n/**\n * Ensures exactly one property from the specified keys is provided.\n * @example\n * // Valid: { url: \"...\" } or { videoId: \"...\" }\n * // Invalid: {} or { url: \"...\", videoId: \"...\" }\n */\ntype ExactlyOne<T, Keys extends keyof T> = {\n [K in Keys]: { [P in K]-?: T[P] } & { [P in Exclude<Keys, K>]?: never };\n}[Keys] &\n Omit<T, Keys>;\n\nexport type TranscriptParams = {\n lang?: string;\n text?: boolean;\n} & ExactlyOne<{ videoId: string; url: string }, 'videoId' | 'url'>;\n\nexport interface TranslateParams extends Omit<TranscriptParams, 'lang'> {\n lang: string;\n}\n\nexport interface ResourceParams {\n id: string;\n}\n\nexport interface ChannelVideosParams extends ResourceParams {\n limit?: number;\n type?: 'video' | 'short' | 'live' | 'all';\n}\n\nexport interface PlaylistVideosParams extends ResourceParams {\n limit?: number;\n}\n\nexport interface VideoIds {\n videoIds: string[];\n shortIds: string[];\n liveIds: string[];\n}\n\nexport class YouTubeService extends BaseClient {\n /**\n * Handles YouTube Transcript operations.\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n transcript = Object.assign(\n /**\n * Fetches a transcript for a YouTube video.\n * @param params - Parameters for fetching the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The language code for the transcript (optional)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a Transcript object\n * @deprecated Use `supadata.transcript()` instead for multi-platform support\n */\n async (params: TranscriptParams): Promise<Transcript> => {\n return this.fetch<Transcript>('/youtube/transcript', params);\n },\n {\n /**\n * Batch fetches transcripts for multiple YouTube videos.\n * @param params - Parameters for the transcript batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch transcripts for\n * @param params.lang - The language code for the transcripts (optional)\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeTranscriptBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/transcript/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube video operations.\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n video = Object.assign(\n /**\n * Fetches a YouTube video based on the provided parameters.\n * @param params - The parameters required to fetch the YouTube video\n * @param params.id - The YouTube video ID\n * @returns A promise that resolves to a YoutubeVideo object\n * @deprecated Use `supadata.metadata()` instead for multi-platform support\n */\n async (params: ResourceParams): Promise<YoutubeVideo> => {\n return this.fetch<YoutubeVideo>('/youtube/video', params);\n },\n {\n /**\n * Batch fetches metadata for multiple YouTube videos.\n * @param params - Parameters for the video metadata batch job\n * @param params.videoIds - Array of YouTube video IDs to fetch metadata for\n * @param params.limit - Maximum number of videos to process (optional, default: 10, max: 5000)\n * @returns A promise that resolves to a YoutubeBatchJob object with the job ID\n */\n batch: async (\n params: YoutubeVideoBatchRequest\n ): Promise<YoutubeBatchJob> => {\n this.validateLimit(params, 1, 5000, 'batch operation');\n return this.fetch<YoutubeBatchJob>(\n '/youtube/video/batch',\n params,\n 'POST'\n );\n },\n }\n );\n\n /**\n * Handles YouTube channel operations.\n */\n channel = Object.assign(\n /**\n * Fetches YouTube channel information.\n * @param params - The parameters required to fetch the YouTube channel information\n * @param params.id - The YouTube channel ID\n * @returns A promise that resolves to a YoutubeChannel object containing the channel information\n */\n async (params: ResourceParams): Promise<YoutubeChannel> => {\n return this.fetch<YoutubeChannel>('/youtube/channel', params);\n },\n {\n /**\n * Fetches the videos of a YouTube channel.\n * @param params - The parameters required to fetch the YouTube channel videos\n * @param params.id - The YouTube channel ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @param params.type - The type of videos to fetch ('video', 'short', 'live', or 'all', default: 'video')\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: ChannelVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/channel/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube playlist operations.\n */\n playlist = Object.assign(\n /**\n * Fetches a YouTube playlist.\n * @param params - The parameters required to fetch the playlist\n * @param params.id - The YouTube playlist ID\n * @returns A promise that resolves to a YoutubePlaylist object\n */\n async (params: ResourceParams): Promise<YoutubePlaylist> => {\n return this.fetch<YoutubePlaylist>('/youtube/playlist', params);\n },\n {\n /**\n * Fetches the videos of a YouTube playlist.\n * @param params - The parameters required to fetch the playlist videos\n * @param params.id - The YouTube playlist ID\n * @param params.limit - The maximum number of videos to fetch (default: 30, max: 5000)\n * @returns A promise that resolves to an object containing arrays of video IDs, short IDs, and live IDs\n * @throws {SupadataError} If the limit is invalid (less than 1 or greater than 5000)\n */\n videos: async (params: PlaylistVideosParams): Promise<VideoIds> => {\n this.validateLimit(params);\n return this.fetch<VideoIds>('/youtube/playlist/videos', params);\n },\n }\n );\n\n /**\n * Handles YouTube batch operations.\n */\n batch = {\n /**\n * Retrieves the status and results of a batch job.\n * @param jobId - The ID of the batch job\n * @returns A promise that resolves to the YoutubeBatchResults containing job status and results\n * @throws {SupadataError} If jobId is not provided\n */\n getBatchResults: async (jobId: string): Promise<YoutubeBatchResults> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details: 'The jobId parameter is required to get batch results.',\n });\n }\n return this.fetch<YoutubeBatchResults>(`/youtube/batch/${jobId}`);\n },\n };\n\n /**\n * Translates a YouTube video transcript to a specified language.\n * @param params - Parameters for translating the transcript\n * @param params.videoId - The YouTube video ID (mutually exclusive with url)\n * @param params.url - The YouTube video URL (mutually exclusive with videoId)\n * @param params.lang - The target language code for translation\n * @param params.text - Whether to return only the text content (optional)\n * @returns A promise that resolves to a TranslatedTranscript object\n */\n translate = async (\n params: TranslateParams\n ): Promise<TranslatedTranscript> => {\n return this.fetch<TranslatedTranscript>(\n '/youtube/transcript/translate',\n params\n );\n };\n\n /**\n * Search YouTube for videos, channels, and playlists with advanced filters.\n * @param params - Parameters for the search\n * @param params.query - The search query string\n * @param params.uploadDate - Filter by upload date (\"all\", \"hour\", \"today\", \"week\", \"month\", \"year\")\n * @param params.type - Filter by content type (\"all\", \"video\", \"channel\", \"playlist\", \"movie\")\n * @param params.duration - Filter video length (\"all\", \"short\", \"medium\", \"long\")\n * @param params.sortBy - Sort results by (\"relevance\", \"rating\", \"date\", \"views\")\n * @param params.features - Array of special video features\n * @param params.limit - Maximum results to return\n * @param params.nextPageToken - Token for pagination\n * @returns A promise that resolves to a YoutubeSearchResponse object\n */\n search = async (\n params: YoutubeSearchParams\n ): Promise<YoutubeSearchResponse> => {\n if (!params.query) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing query parameter',\n details: 'The query parameter is required for search.',\n });\n }\n\n this.validateLimit(params, 1, 5000, 'search');\n\n return this.fetch<YoutubeSearchResponse>('/youtube/search', params);\n };\n\n private validateLimit(\n params: { limit?: number },\n min: number = 1,\n max: number = 5000,\n operation: string = 'operation'\n ) {\n if (\n params.limit != undefined &&\n params.limit != null &&\n (params.limit < min || params.limit > max)\n ) {\n throw new SupadataError({\n error: 'invalid-request',\n message: `Invalid limit for ${operation}.`,\n details: `The limit must be between ${min} and ${max}.`,\n });\n }\n }\n}\n","import { BaseClient } from '../client.js';\nimport { CrawlJob, CrawlRequest, JobId, Scrape, SiteMap } from '../types.js';\n\nexport class WebService extends BaseClient {\n /**\n * Extract content from any web page to Markdown format.\n *\n * @param url - URL of the webpage to scrape\n * @returns A promise that resolves to the scraped content\n */\n async scrape(url: string): Promise<Scrape> {\n return this.fetch<Scrape>('/web/scrape', { url });\n }\n\n /**\n * Extract all links found on a webpage.\n *\n * @param url - URL of the webpage to map\n * @returns A promise that resolves to a map of URLs found on the page\n */\n async map(url: string): Promise<SiteMap> {\n return this.fetch<SiteMap>('/web/map', { url });\n }\n\n /**\n * Create a crawl job to extract content from all pages on a website.\n *\n * @param request - Crawl request parameters\n * @param request.url - URL of the website to crawl\n * @param request.limit - Maximum number of pages to crawl (default: 100, max: 5000)\n * @returns A promise that resolves to the crawl job id\n */\n async crawl(request: CrawlRequest): Promise<JobId> {\n return this.fetch<JobId>('/web/crawl', request, 'POST');\n }\n\n /**\n * Get the status and results of a crawl job.\n * Automatically handles pagination to retrieve all pages from the crawl.\n *\n * @param jobId - The ID of the crawl job to retrieve\n * @returns A promise that resolves to the complete crawl job results\n */\n async getCrawlResults(jobId: string): Promise<CrawlJob> {\n let response: CrawlJob;\n let pages: Scrape[] = [];\n let nextUrl: string | undefined;\n\n do {\n response = await (nextUrl\n ? this.fetchUrl<CrawlJob>(nextUrl)\n : this.fetch<CrawlJob>(`/web/crawl/${jobId}`));\n\n if (response.pages) {\n pages = [...pages, ...response.pages];\n }\n nextUrl = response.next;\n } while (nextUrl);\n\n return response;\n }\n}\n","import { BaseClient } from '../client.js';\nimport {\n JobId,\n JobResult,\n SupadataError,\n Transcript,\n TranscriptOrJobId,\n} from '../types.js';\n\nexport interface GeneralTranscriptParams {\n url: string;\n lang?: string;\n text?: boolean;\n chunkSize?: number;\n mode?: 'native' | 'auto' | 'generate';\n}\n\nexport class TranscriptService extends BaseClient {\n /**\n * Get transcript from a supported video platform or file URL.\n * @param params - Parameters for fetching the transcript\n * @returns A promise that resolves to either a Transcript or JobId for async processing\n */\n get = async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this.fetch<TranscriptOrJobId>('/transcript', params);\n };\n\n /**\n * Get results for a transcript job by job ID.\n * @param jobId - The ID of the transcript job\n * @returns A promise that resolves to the job result containing status and transcript if completed\n * @throws {SupadataError} If jobId is not provided\n */\n getJobStatus = async (jobId: string): Promise<JobResult<Transcript>> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details:\n 'The jobId parameter is required to get transcript job status.',\n });\n }\n return this.fetch<JobResult<Transcript>>(`/transcript/${jobId}`);\n };\n}\n","import { BaseClient } from '../client.js';\nimport {\n ExtractJobResult,\n ExtractParams,\n JobId,\n SupadataError,\n} from '../types.js';\n\nexport class ExtractService extends BaseClient {\n /**\n * Start an extract job to analyze video content and extract structured data.\n * @param params - Parameters for the extract job\n * @returns A promise that resolves to a JobId for async processing\n */\n get = async (params: ExtractParams): Promise<JobId> => {\n return this.fetch<JobId>('/extract', params, 'POST');\n };\n\n /**\n * Get results for an extract job by job ID.\n * @param jobId - The ID of the extract job\n * @returns A promise that resolves to the extract job result\n * @throws {SupadataError} If jobId is not provided\n */\n getResults = async (jobId: string): Promise<ExtractJobResult> => {\n if (!jobId) {\n throw new SupadataError({\n error: 'invalid-request',\n message: 'Missing jobId',\n details:\n 'The jobId parameter is required to get extract job results.',\n });\n }\n return this.fetch<ExtractJobResult>(`/extract/${jobId}`);\n };\n}\n","import {\n ExtractJobResult,\n ExtractParams,\n JobId,\n JobResult,\n Metadata,\n SupadataConfig,\n Transcript,\n TranscriptOrJobId,\n} from './types.js';\nimport { YouTubeService } from './services/youtube.js';\nimport { WebService } from './services/web.js';\nimport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\nimport { ExtractService } from './services/extract.js';\nimport { BaseClient } from './client.js';\n\nexport * from './types.js';\nexport * from './client.js';\nexport * from './services/youtube.js';\nexport * from './services/web.js';\nexport {\n TranscriptService,\n GeneralTranscriptParams,\n} from './services/transcript.js';\nexport { ExtractService } from './services/extract.js';\n\nexport interface MetadataParams {\n url: string;\n}\n\nexport class Supadata extends BaseClient {\n readonly youtube: YouTubeService;\n readonly web: WebService;\n private _transcriptService: TranscriptService;\n private _extractService: ExtractService;\n\n constructor(config: SupadataConfig) {\n super(config);\n this.youtube = new YouTubeService(config);\n this.web = new WebService(config);\n this._transcriptService = new TranscriptService(config);\n this._extractService = new ExtractService(config);\n }\n\n /**\n * Get transcript from a supported video platform (YouTube, TikTok, Instagram, Twitter) or file URL.\n * If the video is too large to return transcript immediately, request returns a job ID.\n */\n transcript = Object.assign(\n async (params: GeneralTranscriptParams): Promise<TranscriptOrJobId> => {\n return this._transcriptService.get(params);\n },\n {\n getJobStatus: (jobId: string): Promise<JobResult<Transcript>> => {\n return this._transcriptService.getJobStatus(jobId);\n },\n }\n );\n\n /**\n * Get metadata from any supported platform (YouTube, TikTok, Instagram, Twitter).\n * @param params - Parameters for fetching metadata\n * @param params.url - Media URL from YouTube, TikTok, Instagram, or Twitter\n * @returns A promise that resolves to a Metadata object\n */\n metadata = async (params: MetadataParams): Promise<Metadata> => {\n return this.fetch<Metadata>('/metadata', params);\n };\n\n /**\n * Extract structured data from video content using AI.\n * Returns a job ID for asynchronous processing.\n * Use extract.getResults(jobId) to poll for results.\n */\n extract = Object.assign(\n async (params: ExtractParams): Promise<JobId> => {\n return this._extractService.get(params);\n },\n {\n getResults: (jobId: string): Promise<ExtractJobResult> => {\n return this._extractService.getResults(jobId);\n },\n }\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supadata/js",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "description": "TypeScript / JavaScript SDK for Supadata API",
5
5
  "homepage": "https://supadata.ai",
6
6
  "repository": "https://github.com/supadata-ai/js",