@supadata/js 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,11 @@
1
- # @supadata/ts
1
+ # Supadata JS SDK
2
2
 
3
- Official TypeScript/JavaScript SDK for the Supadata API.
3
+ [![NPM package](https://img.shields.io/npm/v/@supadata/js.svg?branch=main)](https://www.npmjs.com/package/@supadata/js)
4
+ [![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](http://opensource.org/licenses/MIT)
5
+
6
+ The official TypeScript/JavaScript SDK for Supadata.
7
+
8
+ Get your free API key at [supadata.ai](https://supadata.ai) and start scraping data in minutes.
4
9
 
5
10
  ## Installation
6
11
 
@@ -11,29 +16,29 @@ npm install @supadata/js
11
16
  ## Usage
12
17
 
13
18
  ```typescript
14
- import { Supadata, Transcript } from "@supadata/js";
19
+ import { Supadata, Transcript } from '@supadata/js';
15
20
 
16
21
  // Initialize the client
17
22
  const supadata = new Supadata({
18
- apiKey: "YOUR_API_KEY",
23
+ apiKey: 'YOUR_API_KEY',
19
24
  });
20
25
 
21
26
  // Get YouTube transcript
22
27
  const transcript = await supadata.youtube.transcript({
23
- videoId: "VIDEO_ID",
28
+ videoId: 'VIDEO_ID',
24
29
  });
25
30
 
26
31
  // Translate YouTube transcript
27
32
  const translated = await supadata.youtube.translate({
28
- videoId: "VIDEO_ID",
29
- lang: "es",
33
+ videoId: 'VIDEO_ID',
34
+ lang: 'es',
30
35
  });
31
36
 
32
37
  // Scrape web content
33
- const webContent = await supadata.web.scrape("https://supadata.ai");
38
+ const webContent = await supadata.web.scrape('https://supadata.ai');
34
39
 
35
40
  // Map website URLs
36
- const siteMap = await supadata.web.map("https://supadata.ai");
41
+ const siteMap = await supadata.web.map('https://supadata.ai');
37
42
  ```
38
43
 
39
44
  ## Error Handling
@@ -41,18 +46,18 @@ const siteMap = await supadata.web.map("https://supadata.ai");
41
46
  The SDK throws `SupadataError` for API-related errors. You can catch and handle these errors as follows:
42
47
 
43
48
  ```typescript
44
- import { SupadataError } from "@supadata/js";
49
+ import { SupadataError } from '@supadata/js';
45
50
 
46
51
  try {
47
52
  const transcript = await supadata.youtube.transcript({
48
- videoId: "INVALID_ID",
53
+ videoId: 'INVALID_ID',
49
54
  });
50
- } catch (error) {
51
- if (error instanceof SupadataError) {
52
- console.error(error.code); // e.g., 'video-not-found'
53
- console.error(error.title); // Human readable error title
54
- console.error(error.message); // Detailed error description
55
- console.error(error.documentationUrl); // Link to error documentation
55
+ } catch (e) {
56
+ if (e instanceof SupadataError) {
57
+ console.error(e.error); // e.g., 'video-not-found'
58
+ console.error(e.message); // Human readable error message
59
+ console.error(e.details); // Detailed error description
60
+ console.error(e.documentationUrl); // Link to error documentation (optional)
56
61
  }
57
62
  }
58
63
  ```
package/dist/index.cjs ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';var t=class extends Error{error;details;documentationUrl;constructor(r){super(r.message||"An unexpected error occurred"),this.error=r.error||"internal-error",this.details=r.details||"An unexpected error occurred",this.documentationUrl=r.documentationUrl||"",this.name="SupadataError";}};var x={"endpoint is not configured":{error:"invalid-request",message:"The requested endpoint is not configured",details:"The API endpoint you are trying to access does not exist"},"No valid access key found":{error:"invalid-request",message:"Invalid or missing API key",details:"Please ensure you have provided a valid API key"},"quota exceeded":{error:"quota-exceeded",message:"API quota exceeded",details:"You have exceeded your API quota for the current period"}},g=(s,r)=>{let o=Object.entries(x).find(([u])=>r.includes(u));return o?new t(o[1]):new t({error:"internal-error",message:"An unexpected error occurred",details:r})};var n=class{config;constructor(r){this.config=r;}async fetch(r,o){let l=`${this.config.baseUrl||"https://api.supadata.ai/v1"}${r.startsWith("/")?r:`/${r}`}`;if(o){let e=new URLSearchParams;Object.entries(o).forEach(([h,d])=>{d!=null&&e.append(h,String(d));}),l+=`?${e.toString()}`;}let a=await fetch(l,{method:"GET",headers:{"x-api-key":this.config.apiKey,"Content-Type":"application/json"}}),m=a.headers.get("content-type");if(!a.ok)if(m?.includes("application/json")){let e=await a.json();throw new t(e)}else {let e=await a.text();throw g(a.status,e)}try{if(!m?.includes("application/json"))throw new t({error:"internal-error",message:"Invalid response format",details:"Expected JSON response but received different content type"});return await a.json()}catch(e){throw new t({error:"internal-error",message:"Failed to parse response",details:e instanceof Error?e.message:"Unknown error"})}}};var c=class extends n{async transcript(r){return this.fetch("/youtube/transcript",r)}async translate(r){return this.fetch("/youtube/transcript/translate",r)}};var p=class extends n{async scrape(r){return this.fetch("/web/scrape",{url:r})}async map(r){return this.fetch("/web/map",{url:r})}};var f=class{youtube;web;constructor(r){this.youtube=new c(r),this.web=new p(r);}};
2
+ exports.BaseClient=n;exports.Supadata=f;exports.SupadataError=t;exports.WebService=p;exports.YouTubeService=c;//# sourceMappingURL=index.cjs.map
3
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/gateway-error-mapper.ts","../src/client.ts","../src/services/youtube.ts","../src/services/web.ts","../src/index.ts"],"names":["SupadataError","error","GATEWAY_ERROR_PATTERNS","mapGatewayError","statusCode","errorText","matchedError","pattern","BaseClient","config","endpoint","params","url","queryParams","key","value","response","contentType","errorData","YouTubeService","WebService","Supadata"],"mappings":"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","file":"index.cjs","sourcesContent":["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 Map {\n urls: 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 | 'missing-parameters'\n | 'internal-error'\n | 'transcript-unavailable'\n | 'video-not-found'\n | 'video-id-invalid'\n | 'youtube-api-error'\n | 'quota-exceeded'\n | 'rate-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","import { SupadataError } from './types';\n\n/*\nThe API gateway returns errors in text/plain content type. \nAs a temporary workaround we're mapping them to SupadataError.\n*/\n\nconst GATEWAY_ERROR_PATTERNS = {\n 'endpoint is not configured': {\n error: 'invalid-request' as const,\n message: 'The requested endpoint is not configured',\n details: 'The API endpoint you are trying to access does not exist',\n },\n 'No valid access key found': {\n error: 'invalid-request' as const,\n message: 'Invalid or missing API key',\n details: 'Please ensure you have provided a valid API key',\n },\n 'quota exceeded': {\n error: 'quota-exceeded' as const,\n message: 'API quota exceeded',\n details: 'You have exceeded your API quota for the current period',\n },\n};\n\nexport const mapGatewayError = (\n statusCode: number,\n errorText: string\n): SupadataError => {\n const matchedError = Object.entries(GATEWAY_ERROR_PATTERNS).find(\n ([pattern]) => errorText.includes(pattern)\n );\n\n if (matchedError) {\n return new SupadataError(matchedError[1]);\n }\n\n // Default error if no pattern matches\n return new SupadataError({\n error: 'internal-error',\n message: 'An unexpected error occurred',\n details: errorText,\n });\n};\n","import { SupadataConfig, SupadataError } from './types.js';\nimport { mapGatewayError } from './gateway-error-mapper.js';\n\nexport class BaseClient {\n protected config: SupadataConfig;\n\n constructor(config: SupadataConfig) {\n this.config = config;\n }\n\n async fetch<T>(\n endpoint: string,\n params: Record<string, unknown> | object\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 (params) {\n const queryParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n queryParams.append(key, String(value));\n }\n });\n url += `?${queryParams.toString()}`;\n }\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'x-api-key': this.config.apiKey,\n 'Content-Type': 'application/json',\n },\n });\n\n const contentType = response.headers.get('content-type');\n\n if (!response.ok) {\n if (contentType?.includes('application/json')) {\n const errorData = await response.json();\n throw new SupadataError(errorData);\n } else {\n const errorText = await response.text();\n throw mapGatewayError(response.status, errorText);\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 { Transcript, TranslatedTranscript } from \"../types.js\";\n\nexport interface TranscriptParams {\n videoId: string;\n lang?: string;\n text?: boolean;\n}\n\nexport interface TranslateParams extends TranscriptParams {\n lang: string;\n}\n\nexport class YouTubeService extends BaseClient {\n async transcript(params: TranscriptParams): Promise<Transcript> {\n return this.fetch<Transcript>(\"/youtube/transcript\", params);\n }\n\n async translate(params: TranslateParams): Promise<TranslatedTranscript> {\n return this.fetch<TranslatedTranscript>(\n \"/youtube/transcript/translate\",\n params\n );\n }\n}\n","import { BaseClient } from '../client.js';\nimport { Scrape, Map } from '../types.js';\n\nexport class WebService extends BaseClient {\n async scrape(url: string): Promise<Scrape> {\n return this.fetch<Scrape>('/web/scrape', { url });\n }\n\n async map(url: string): Promise<Map> {\n return this.fetch<Map>('/web/map', { url });\n }\n}","import { SupadataConfig } from './types.js';\nimport { YouTubeService } from './services/youtube.js';\nimport { WebService } from './services/web.js';\n\nexport * from './types.js';\nexport * from './client.js';\nexport * from './services/youtube.js';\nexport * from './services/web.js';\n\nexport class Supadata {\n readonly youtube: YouTubeService;\n readonly web: WebService;\n\n constructor(config: SupadataConfig) {\n this.youtube = new YouTubeService(config);\n this.web = new WebService(config);\n }\n}"]}
@@ -0,0 +1,74 @@
1
+ interface TranscriptChunk {
2
+ text: string;
3
+ offset: number;
4
+ duration: number;
5
+ lang: string;
6
+ }
7
+ interface Transcript {
8
+ content: TranscriptChunk[] | string;
9
+ lang: string;
10
+ availableLangs: string[];
11
+ }
12
+ interface TranslatedTranscript {
13
+ content: TranscriptChunk[] | string;
14
+ lang: string;
15
+ }
16
+ interface Scrape {
17
+ url: string;
18
+ content: string;
19
+ name: string;
20
+ description: string;
21
+ ogUrl: string;
22
+ countCharacters: number;
23
+ urls: string[];
24
+ }
25
+ interface Map {
26
+ urls: string[];
27
+ }
28
+ interface SupadataConfig {
29
+ apiKey: string;
30
+ baseUrl?: string;
31
+ }
32
+ declare class SupadataError extends Error {
33
+ error: 'invalid-request' | 'missing-parameters' | 'internal-error' | 'transcript-unavailable' | 'video-not-found' | 'video-id-invalid' | 'youtube-api-error' | 'quota-exceeded' | 'rate-limit-exceeded';
34
+ details: string;
35
+ documentationUrl: string;
36
+ constructor(error: {
37
+ error: SupadataError['error'];
38
+ message?: string;
39
+ details?: string;
40
+ documentationUrl?: string;
41
+ });
42
+ }
43
+
44
+ declare class BaseClient {
45
+ protected config: SupadataConfig;
46
+ constructor(config: SupadataConfig);
47
+ fetch<T>(endpoint: string, params: Record<string, unknown> | object): Promise<T>;
48
+ }
49
+
50
+ interface TranscriptParams {
51
+ videoId: string;
52
+ lang?: string;
53
+ text?: boolean;
54
+ }
55
+ interface TranslateParams extends TranscriptParams {
56
+ lang: string;
57
+ }
58
+ declare class YouTubeService extends BaseClient {
59
+ transcript(params: TranscriptParams): Promise<Transcript>;
60
+ translate(params: TranslateParams): Promise<TranslatedTranscript>;
61
+ }
62
+
63
+ declare class WebService extends BaseClient {
64
+ scrape(url: string): Promise<Scrape>;
65
+ map(url: string): Promise<Map>;
66
+ }
67
+
68
+ declare class Supadata {
69
+ readonly youtube: YouTubeService;
70
+ readonly web: WebService;
71
+ constructor(config: SupadataConfig);
72
+ }
73
+
74
+ export { BaseClient, type Map, type Scrape, Supadata, type SupadataConfig, SupadataError, type Transcript, type TranscriptChunk, type TranscriptParams, type TranslateParams, type TranslatedTranscript, WebService, YouTubeService };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,74 @@
1
- import { SupadataConfig } from './types.js';
2
- import { YouTubeService } from './services/youtube.js';
3
- import { WebService } from './services/web.js';
4
- export * from './types.js';
5
- export * from './client.js';
6
- export * from './services/youtube.js';
7
- export * from './services/web.js';
8
- export declare class Supadata {
1
+ interface TranscriptChunk {
2
+ text: string;
3
+ offset: number;
4
+ duration: number;
5
+ lang: string;
6
+ }
7
+ interface Transcript {
8
+ content: TranscriptChunk[] | string;
9
+ lang: string;
10
+ availableLangs: string[];
11
+ }
12
+ interface TranslatedTranscript {
13
+ content: TranscriptChunk[] | string;
14
+ lang: string;
15
+ }
16
+ interface Scrape {
17
+ url: string;
18
+ content: string;
19
+ name: string;
20
+ description: string;
21
+ ogUrl: string;
22
+ countCharacters: number;
23
+ urls: string[];
24
+ }
25
+ interface Map {
26
+ urls: string[];
27
+ }
28
+ interface SupadataConfig {
29
+ apiKey: string;
30
+ baseUrl?: string;
31
+ }
32
+ declare class SupadataError extends Error {
33
+ error: 'invalid-request' | 'missing-parameters' | 'internal-error' | 'transcript-unavailable' | 'video-not-found' | 'video-id-invalid' | 'youtube-api-error' | 'quota-exceeded' | 'rate-limit-exceeded';
34
+ details: string;
35
+ documentationUrl: string;
36
+ constructor(error: {
37
+ error: SupadataError['error'];
38
+ message?: string;
39
+ details?: string;
40
+ documentationUrl?: string;
41
+ });
42
+ }
43
+
44
+ declare class BaseClient {
45
+ protected config: SupadataConfig;
46
+ constructor(config: SupadataConfig);
47
+ fetch<T>(endpoint: string, params: Record<string, unknown> | object): Promise<T>;
48
+ }
49
+
50
+ interface TranscriptParams {
51
+ videoId: string;
52
+ lang?: string;
53
+ text?: boolean;
54
+ }
55
+ interface TranslateParams extends TranscriptParams {
56
+ lang: string;
57
+ }
58
+ declare class YouTubeService extends BaseClient {
59
+ transcript(params: TranscriptParams): Promise<Transcript>;
60
+ translate(params: TranslateParams): Promise<TranslatedTranscript>;
61
+ }
62
+
63
+ declare class WebService extends BaseClient {
64
+ scrape(url: string): Promise<Scrape>;
65
+ map(url: string): Promise<Map>;
66
+ }
67
+
68
+ declare class Supadata {
9
69
  readonly youtube: YouTubeService;
10
70
  readonly web: WebService;
11
71
  constructor(config: SupadataConfig);
12
72
  }
73
+
74
+ export { BaseClient, type Map, type Scrape, Supadata, type SupadataConfig, SupadataError, type Transcript, type TranscriptChunk, type TranscriptParams, type TranslateParams, type TranslatedTranscript, WebService, YouTubeService };
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ var t=class extends Error{error;details;documentationUrl;constructor(r){super(r.message||"An unexpected error occurred"),this.error=r.error||"internal-error",this.details=r.details||"An unexpected error occurred",this.documentationUrl=r.documentationUrl||"",this.name="SupadataError";}};var T={"endpoint is not configured":{error:"invalid-request",message:"The requested endpoint is not configured",details:"The API endpoint you are trying to access does not exist"},"No valid access key found":{error:"invalid-request",message:"Invalid or missing API key",details:"Please ensure you have provided a valid API key"},"quota exceeded":{error:"quota-exceeded",message:"API quota exceeded",details:"You have exceeded your API quota for the current period"}},f=(s,r)=>{let o=Object.entries(T).find(([l])=>r.includes(l));return o?new t(o[1]):new t({error:"internal-error",message:"An unexpected error occurred",details:r})};var n=class{config;constructor(r){this.config=r;}async fetch(r,o){let m=`${this.config.baseUrl||"https://api.supadata.ai/v1"}${r.startsWith("/")?r:`/${r}`}`;if(o){let e=new URLSearchParams;Object.entries(o).forEach(([x,u])=>{u!=null&&e.append(x,String(u));}),m+=`?${e.toString()}`;}let a=await fetch(m,{method:"GET",headers:{"x-api-key":this.config.apiKey,"Content-Type":"application/json"}}),g=a.headers.get("content-type");if(!a.ok)if(g?.includes("application/json")){let e=await a.json();throw new t(e)}else {let e=await a.text();throw f(a.status,e)}try{if(!g?.includes("application/json"))throw new t({error:"internal-error",message:"Invalid response format",details:"Expected JSON response but received different content type"});return await a.json()}catch(e){throw new t({error:"internal-error",message:"Failed to parse response",details:e instanceof Error?e.message:"Unknown error"})}}};var p=class extends n{async transcript(r){return this.fetch("/youtube/transcript",r)}async translate(r){return this.fetch("/youtube/transcript/translate",r)}};var d=class extends n{async scrape(r){return this.fetch("/web/scrape",{url:r})}async map(r){return this.fetch("/web/map",{url:r})}};var h=class{youtube;web;constructor(r){this.youtube=new p(r),this.web=new d(r);}};
2
+ export{n as BaseClient,h as Supadata,t as SupadataError,d as WebService,p as YouTubeService};//# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/gateway-error-mapper.ts","../src/client.ts","../src/services/youtube.ts","../src/services/web.ts","../src/index.ts"],"names":["SupadataError","error","GATEWAY_ERROR_PATTERNS","mapGatewayError","statusCode","errorText","matchedError","pattern","BaseClient","config","endpoint","params","url","queryParams","key","value","response","contentType","errorData","YouTubeService","WebService","Supadata"],"mappings":"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","file":"index.mjs","sourcesContent":["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 Map {\n urls: 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 | 'missing-parameters'\n | 'internal-error'\n | 'transcript-unavailable'\n | 'video-not-found'\n | 'video-id-invalid'\n | 'youtube-api-error'\n | 'quota-exceeded'\n | 'rate-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","import { SupadataError } from './types';\n\n/*\nThe API gateway returns errors in text/plain content type. \nAs a temporary workaround we're mapping them to SupadataError.\n*/\n\nconst GATEWAY_ERROR_PATTERNS = {\n 'endpoint is not configured': {\n error: 'invalid-request' as const,\n message: 'The requested endpoint is not configured',\n details: 'The API endpoint you are trying to access does not exist',\n },\n 'No valid access key found': {\n error: 'invalid-request' as const,\n message: 'Invalid or missing API key',\n details: 'Please ensure you have provided a valid API key',\n },\n 'quota exceeded': {\n error: 'quota-exceeded' as const,\n message: 'API quota exceeded',\n details: 'You have exceeded your API quota for the current period',\n },\n};\n\nexport const mapGatewayError = (\n statusCode: number,\n errorText: string\n): SupadataError => {\n const matchedError = Object.entries(GATEWAY_ERROR_PATTERNS).find(\n ([pattern]) => errorText.includes(pattern)\n );\n\n if (matchedError) {\n return new SupadataError(matchedError[1]);\n }\n\n // Default error if no pattern matches\n return new SupadataError({\n error: 'internal-error',\n message: 'An unexpected error occurred',\n details: errorText,\n });\n};\n","import { SupadataConfig, SupadataError } from './types.js';\nimport { mapGatewayError } from './gateway-error-mapper.js';\n\nexport class BaseClient {\n protected config: SupadataConfig;\n\n constructor(config: SupadataConfig) {\n this.config = config;\n }\n\n async fetch<T>(\n endpoint: string,\n params: Record<string, unknown> | object\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 (params) {\n const queryParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n queryParams.append(key, String(value));\n }\n });\n url += `?${queryParams.toString()}`;\n }\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'x-api-key': this.config.apiKey,\n 'Content-Type': 'application/json',\n },\n });\n\n const contentType = response.headers.get('content-type');\n\n if (!response.ok) {\n if (contentType?.includes('application/json')) {\n const errorData = await response.json();\n throw new SupadataError(errorData);\n } else {\n const errorText = await response.text();\n throw mapGatewayError(response.status, errorText);\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 { Transcript, TranslatedTranscript } from \"../types.js\";\n\nexport interface TranscriptParams {\n videoId: string;\n lang?: string;\n text?: boolean;\n}\n\nexport interface TranslateParams extends TranscriptParams {\n lang: string;\n}\n\nexport class YouTubeService extends BaseClient {\n async transcript(params: TranscriptParams): Promise<Transcript> {\n return this.fetch<Transcript>(\"/youtube/transcript\", params);\n }\n\n async translate(params: TranslateParams): Promise<TranslatedTranscript> {\n return this.fetch<TranslatedTranscript>(\n \"/youtube/transcript/translate\",\n params\n );\n }\n}\n","import { BaseClient } from '../client.js';\nimport { Scrape, Map } from '../types.js';\n\nexport class WebService extends BaseClient {\n async scrape(url: string): Promise<Scrape> {\n return this.fetch<Scrape>('/web/scrape', { url });\n }\n\n async map(url: string): Promise<Map> {\n return this.fetch<Map>('/web/map', { url });\n }\n}","import { SupadataConfig } from './types.js';\nimport { YouTubeService } from './services/youtube.js';\nimport { WebService } from './services/web.js';\n\nexport * from './types.js';\nexport * from './client.js';\nexport * from './services/youtube.js';\nexport * from './services/web.js';\n\nexport class Supadata {\n readonly youtube: YouTubeService;\n readonly web: WebService;\n\n constructor(config: SupadataConfig) {\n this.youtube = new YouTubeService(config);\n this.web = new WebService(config);\n }\n}"]}
package/package.json CHANGED
@@ -1,19 +1,23 @@
1
1
  {
2
2
  "name": "@supadata/js",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "TypeScript / JavaScript SDK for Supadata API",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
5
+ "homepage": "https://supadata.ai",
6
+ "repository": "https://github.com/supadata-ai/js",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.mjs",
8
9
  "types": "./dist/index.d.ts",
9
10
  "exports": {
10
11
  ".": {
11
12
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.cjs",
15
+ "default": "./dist/index.mjs"
13
16
  }
14
17
  },
15
18
  "scripts": {
16
- "build": "tsc",
19
+ "dev": "tsup --watch",
20
+ "build": "tsup",
17
21
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
18
22
  "prepare": "npm run build",
19
23
  "format": "prettier --write \"src/**/*.{js,ts}\"",
@@ -41,6 +45,7 @@
41
45
  "jest-fetch-mock": "^3.0.3",
42
46
  "prettier": "^3.4.2",
43
47
  "ts-jest": "^29.2.5",
44
- "typescript": "^5.7.3"
48
+ "typescript": "^5.7.3",
49
+ "tsup": "^8.3.6"
45
50
  }
46
51
  }
package/dist/client.d.ts DELETED
@@ -1,12 +0,0 @@
1
- import { SupadataConfig, Error } from "./types.js";
2
- export declare class BaseClient {
3
- protected config: SupadataConfig;
4
- constructor(config: SupadataConfig);
5
- fetch<T>(endpoint: string, params: Record<string, unknown> | object): Promise<T>;
6
- }
7
- export declare class SupadataError extends Error {
8
- code: Error["code"];
9
- title: string;
10
- documentationUrl: string;
11
- constructor(error: Error);
12
- }
package/dist/client.js DELETED
@@ -1,43 +0,0 @@
1
- export class BaseClient {
2
- config;
3
- constructor(config) {
4
- this.config = config;
5
- }
6
- async fetch(endpoint, params) {
7
- const baseUrl = this.config.baseUrl || "https://api.supadata.ai/v1";
8
- let url = `${baseUrl}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
9
- if (params) {
10
- const queryParams = new URLSearchParams();
11
- Object.entries(params).forEach(([key, value]) => {
12
- if (value !== undefined && value !== null) {
13
- queryParams.append(key, String(value));
14
- }
15
- });
16
- url += `?${queryParams.toString()}`;
17
- }
18
- const response = await fetch(url, {
19
- method: "GET",
20
- headers: {
21
- "x-api-key": this.config.apiKey,
22
- "Content-Type": "application/json",
23
- },
24
- });
25
- const data = await response.json();
26
- if (!response.ok) {
27
- const error = data;
28
- throw new SupadataError(error);
29
- }
30
- return data;
31
- }
32
- }
33
- export class SupadataError extends Error {
34
- code;
35
- title;
36
- documentationUrl;
37
- constructor(error) {
38
- super(error.description);
39
- this.code = error.code;
40
- this.title = error.title;
41
- this.documentationUrl = error.documentationUrl;
42
- }
43
- }
package/dist/index.js DELETED
@@ -1,14 +0,0 @@
1
- import { YouTubeService } from './services/youtube.js';
2
- import { WebService } from './services/web.js';
3
- export * from './types.js';
4
- export * from './client.js';
5
- export * from './services/youtube.js';
6
- export * from './services/web.js';
7
- export class Supadata {
8
- youtube;
9
- web;
10
- constructor(config) {
11
- this.youtube = new YouTubeService(config);
12
- this.web = new WebService(config);
13
- }
14
- }
@@ -1,6 +0,0 @@
1
- import { BaseClient } from '../client.js';
2
- import { Scrape, Map } from '../types.js';
3
- export declare class WebService extends BaseClient {
4
- scrape(url: string): Promise<Scrape>;
5
- map(url: string): Promise<Map>;
6
- }
@@ -1,9 +0,0 @@
1
- import { BaseClient } from '../client.js';
2
- export class WebService extends BaseClient {
3
- async scrape(url) {
4
- return this.fetch('/web/scrape', { url });
5
- }
6
- async map(url) {
7
- return this.fetch('/web/map', { url });
8
- }
9
- }
@@ -1,14 +0,0 @@
1
- import { BaseClient } from "../client.js";
2
- import { Transcript, TranslatedTranscript } from "../types.js";
3
- export interface TranscriptParams {
4
- videoId: string;
5
- lang?: string;
6
- text?: boolean;
7
- }
8
- export interface TranslateParams extends TranscriptParams {
9
- lang: string;
10
- }
11
- export declare class YouTubeService extends BaseClient {
12
- transcript(params: TranscriptParams): Promise<Transcript>;
13
- translate(params: TranslateParams): Promise<TranslatedTranscript>;
14
- }
@@ -1,9 +0,0 @@
1
- import { BaseClient } from "../client.js";
2
- export class YouTubeService extends BaseClient {
3
- async transcript(params) {
4
- return this.fetch("/youtube/transcript", params);
5
- }
6
- async translate(params) {
7
- return this.fetch("/youtube/transcript/translate", params);
8
- }
9
- }
package/dist/types.d.ts DELETED
@@ -1,37 +0,0 @@
1
- export interface TranscriptChunk {
2
- text: string;
3
- offset: number;
4
- duration: number;
5
- lang: string;
6
- }
7
- export interface Transcript {
8
- content: TranscriptChunk[] | string;
9
- lang: string;
10
- availableLangs: string[];
11
- }
12
- export interface TranslatedTranscript {
13
- content: TranscriptChunk[] | string;
14
- lang: string;
15
- }
16
- export interface Scrape {
17
- url: string;
18
- content: string;
19
- name: string;
20
- description: string;
21
- ogUrl: string;
22
- countCharacters: number;
23
- urls: string[];
24
- }
25
- export interface Map {
26
- urls: string[];
27
- }
28
- export interface SupadataConfig {
29
- apiKey: string;
30
- baseUrl?: string;
31
- }
32
- export interface Error {
33
- code: 'invalid-request' | 'missing-parameters' | 'internal-error' | 'transcript-unavailable' | 'video-not-found' | 'video-id-invalid' | 'youtube-api-error' | 'quota-exceeded' | 'rate-limit-exceeded';
34
- title: string;
35
- description: string;
36
- documentationUrl: string;
37
- }
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- export {};