@monostate/browsernative-client 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.
Files changed (4) hide show
  1. package/README.md +419 -0
  2. package/index.d.ts +190 -0
  3. package/index.js +208 -0
  4. package/package.json +49 -0
package/README.md ADDED
@@ -0,0 +1,419 @@
1
+ # @browsernative/client
2
+
3
+ > **Official JavaScript/TypeScript client for Browser Native API**
4
+
5
+ [![npm version](https://badge.fury.io/js/%40browsernative%2Fclient.svg)](https://badge.fury.io/js/%40browsernative%2Fclient)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)
8
+
9
+ A lightweight, fast, and reliable client for the Browser Native web scraping and content extraction API. Works in browsers, Node.js, Deno, and edge environments.
10
+
11
+ ## 🚀 Quick Start
12
+
13
+ ### Installation
14
+
15
+ ```bash
16
+ npm install @browsernative/client
17
+ # or
18
+ yarn add @browsernative/client
19
+ # or
20
+ pnpm add @browsernative/client
21
+ ```
22
+
23
+ ### Get Your API Key
24
+
25
+ 1. Sign up at [browsernative.monostate.ai](https://browsernative.monostate.ai)
26
+ 2. Get your API key from the dashboard
27
+ 3. Start scraping!
28
+
29
+ ### Basic Usage
30
+
31
+ ```javascript
32
+ import { BrowserNativeClient } from '@browsernative/client';
33
+
34
+ const client = new BrowserNativeClient('your-api-key');
35
+
36
+ // Scrape any website
37
+ const result = await client.scrape('https://example.com');
38
+ console.log(result.data.title);
39
+ console.log(result.data.content);
40
+ ```
41
+
42
+ ### Quick Functions
43
+
44
+ ```javascript
45
+ import { quickScrape, quickScreenshot, quickAnalyze } from '@browsernative/client';
46
+
47
+ // One-line scraping
48
+ const content = await quickScrape('https://example.com', 'your-api-key');
49
+
50
+ // Take a screenshot
51
+ const screenshot = await quickScreenshot('https://example.com', 'your-api-key');
52
+
53
+ // AI-powered analysis
54
+ const analysis = await quickAnalyze(
55
+ 'https://news.ycombinator.com',
56
+ 'What are the top 3 trending topics?',
57
+ 'your-api-key'
58
+ );
59
+ ```
60
+
61
+ ## 📋 API Reference
62
+
63
+ ### Client Initialization
64
+
65
+ ```javascript
66
+ const client = new BrowserNativeClient(apiKey, options);
67
+ ```
68
+
69
+ **Options:**
70
+ - `baseUrl` (string): API base URL (default: `https://browsernative.monostate.ai`)
71
+ - `timeout` (number): Request timeout in ms (default: `30000`)
72
+ - `retries` (number): Number of retry attempts (default: `2`)
73
+ - `verbose` (boolean): Enable logging (default: `false`)
74
+
75
+ ### Methods
76
+
77
+ #### `client.scrape(url, options)`
78
+
79
+ Extract structured content from any webpage.
80
+
81
+ ```javascript
82
+ const result = await client.scrape('https://example.com', {
83
+ includeScreenshot: true,
84
+ waitForSelector: '.main-content',
85
+ extractMetadata: true,
86
+ userAgent: 'Custom Bot 1.0'
87
+ });
88
+
89
+ console.log(result.data.title); // Page title
90
+ console.log(result.data.content); // Main content
91
+ console.log(result.data.metadata); // Meta tags, etc.
92
+ console.log(result.screenshot); // Base64 image (if requested)
93
+ console.log(result.method); // Scraping method used
94
+ ```
95
+
96
+ **Options:**
97
+ - `includeScreenshot` (boolean): Include page screenshot
98
+ - `waitForSelector` (string): CSS selector to wait for
99
+ - `userAgent` (string): Custom user agent
100
+ - `viewport` (object): `{ width: number, height: number }`
101
+ - `extractMetadata` (boolean): Extract meta tags and structured data
102
+
103
+ #### `client.screenshot(url, options)`
104
+
105
+ Take high-quality screenshots of webpages.
106
+
107
+ ```javascript
108
+ const result = await client.screenshot('https://example.com', {
109
+ fullPage: true,
110
+ format: 'png',
111
+ viewport: { width: 1920, height: 1080 }
112
+ });
113
+
114
+ // Use the base64 image
115
+ const img = `data:image/png;base64,${result.screenshot}`;
116
+ ```
117
+
118
+ **Options:**
119
+ - `fullPage` (boolean): Capture full page scroll
120
+ - `format` (string): `'png'`, `'jpeg'`, or `'webp'`
121
+ - `quality` (number): JPEG quality (1-100)
122
+ - All scrape options are also available
123
+
124
+ #### `client.analyze(url, question, options)`
125
+
126
+ AI-powered content analysis and question answering.
127
+
128
+ ```javascript
129
+ const result = await client.analyze(
130
+ 'https://techcrunch.com',
131
+ 'What are the latest AI developments mentioned?',
132
+ {
133
+ language: 'en',
134
+ style: 'detailed'
135
+ }
136
+ );
137
+
138
+ console.log(result.analysis.answer); // AI response
139
+ console.log(result.analysis.confidence); // Confidence score
140
+ ```
141
+
142
+ **Options:**
143
+ - `language` (string): Response language (`'en'`, `'pt'`, `'es'`, `'fr'`, `'de'`, `'auto'`)
144
+ - `style` (string): Response style (`'concise'`, `'detailed'`, `'technical'`)
145
+ - All scrape options are also available
146
+
147
+ #### `client.getUsage(days)`
148
+
149
+ Get your account usage statistics.
150
+
151
+ ```javascript
152
+ const usage = await client.getUsage(30); // Last 30 days
153
+
154
+ console.log(usage.data.monthlyTotal.totalRequests);
155
+ console.log(usage.data.currentUsage);
156
+ console.log(usage.data.usageLimit);
157
+ ```
158
+
159
+ #### `client.healthCheck()`
160
+
161
+ Check API status and your account health.
162
+
163
+ ```javascript
164
+ const health = await client.healthCheck();
165
+
166
+ console.log(health.data.status); // 'healthy', 'degraded', or 'unhealthy'
167
+ console.log(health.data.services); // Service status breakdown
168
+ ```
169
+
170
+ ## 🌐 Framework Integration
171
+
172
+ ### React Hook
173
+
174
+ ```javascript
175
+ // hooks/useBrowserNative.js
176
+ import { useState } from 'react';
177
+ import { BrowserNativeClient } from '@browsernative/client';
178
+
179
+ export function useBrowserNative(apiKey) {
180
+ const [loading, setLoading] = useState(false);
181
+ const [data, setData] = useState(null);
182
+ const [error, setError] = useState(null);
183
+
184
+ const client = new BrowserNativeClient(apiKey);
185
+
186
+ const scrape = async (url, options = {}) => {
187
+ setLoading(true);
188
+ setError(null);
189
+
190
+ try {
191
+ const result = await client.scrape(url, options);
192
+ if (result.success) {
193
+ setData(result.data);
194
+ } else {
195
+ setError(result.error);
196
+ }
197
+ } catch (err) {
198
+ setError(err.message);
199
+ } finally {
200
+ setLoading(false);
201
+ }
202
+ };
203
+
204
+ return { scrape, loading, data, error };
205
+ }
206
+ ```
207
+
208
+ ### Vue Composable
209
+
210
+ ```javascript
211
+ // composables/useBrowserNative.js
212
+ import { ref } from 'vue';
213
+ import { BrowserNativeClient } from '@browsernative/client';
214
+
215
+ export function useBrowserNative(apiKey) {
216
+ const loading = ref(false);
217
+ const data = ref(null);
218
+ const error = ref(null);
219
+
220
+ const client = new BrowserNativeClient(apiKey);
221
+
222
+ const scrape = async (url, options = {}) => {
223
+ loading.value = true;
224
+ error.value = null;
225
+
226
+ try {
227
+ const result = await client.scrape(url, options);
228
+ if (result.success) {
229
+ data.value = result.data;
230
+ } else {
231
+ error.value = result.error;
232
+ }
233
+ } catch (err) {
234
+ error.value = err.message;
235
+ } finally {
236
+ loading.value = false;
237
+ }
238
+ };
239
+
240
+ return { scrape, loading, data, error };
241
+ }
242
+ ```
243
+
244
+ ### Next.js API Route
245
+
246
+ ```javascript
247
+ // pages/api/scrape.js
248
+ import { BrowserNativeClient } from '@browsernative/client';
249
+
250
+ const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
251
+
252
+ export default async function handler(req, res) {
253
+ if (req.method !== 'POST') {
254
+ return res.status(405).json({ error: 'Method not allowed' });
255
+ }
256
+
257
+ try {
258
+ const { url, question } = req.body;
259
+
260
+ let result;
261
+ if (question) {
262
+ result = await client.analyze(url, question);
263
+ } else {
264
+ result = await client.scrape(url);
265
+ }
266
+
267
+ res.status(200).json(result);
268
+ } catch (error) {
269
+ res.status(500).json({ error: error.message });
270
+ }
271
+ }
272
+ ```
273
+
274
+ ### Express.js
275
+
276
+ ```javascript
277
+ import express from 'express';
278
+ import { BrowserNativeClient } from '@browsernative/client';
279
+
280
+ const app = express();
281
+ const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
282
+
283
+ app.post('/scrape', async (req, res) => {
284
+ try {
285
+ const { url } = req.body;
286
+ const result = await client.scrape(url);
287
+ res.json(result);
288
+ } catch (error) {
289
+ res.status(500).json({ error: error.message });
290
+ }
291
+ });
292
+ ```
293
+
294
+ ## 🔒 Environment Variables
295
+
296
+ Create a `.env` file:
297
+
298
+ ```bash
299
+ BROWSER_NATIVE_API_KEY=your_api_key_here
300
+ ```
301
+
302
+ Then use in your code:
303
+
304
+ ```javascript
305
+ const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
306
+ ```
307
+
308
+ ## 📱 Browser Usage
309
+
310
+ You can use this client directly in browsers, but be careful with API keys:
311
+
312
+ ```html
313
+ <!DOCTYPE html>
314
+ <html>
315
+ <head>
316
+ <title>Browser Native Demo</title>
317
+ </head>
318
+ <body>
319
+ <script type="module">
320
+ import { BrowserNativeClient } from 'https://cdn.skypack.dev/@browsernative/client';
321
+
322
+ // ⚠️ Never expose your API key in client-side code!
323
+ // Use a proxy server or environment variables
324
+ const client = new BrowserNativeClient(await getApiKeyFromServer());
325
+
326
+ const result = await client.scrape('https://example.com');
327
+ console.log(result);
328
+ </script>
329
+ </body>
330
+ </html>
331
+ ```
332
+
333
+ **Security Note**: Never expose your API key in client-side code. Use a backend proxy or server-side rendering.
334
+
335
+ ## ⚡ Performance Tips
336
+
337
+ 1. **Reuse Client Instances**: Create one client instance and reuse it
338
+ 2. **Enable Retries**: The client automatically retries failed requests
339
+ 3. **Use Appropriate Timeouts**: Adjust timeout based on your use case
340
+ 4. **Batch Requests**: Process multiple URLs concurrently
341
+
342
+ ```javascript
343
+ const client = new BrowserNativeClient(apiKey, {
344
+ timeout: 45000, // Longer timeout for complex sites
345
+ retries: 3, // More retries for reliability
346
+ verbose: true // Enable logging for debugging
347
+ });
348
+
349
+ // Concurrent scraping
350
+ const urls = ['https://site1.com', 'https://site2.com', 'https://site3.com'];
351
+ const results = await Promise.all(
352
+ urls.map(url => client.scrape(url))
353
+ );
354
+ ```
355
+
356
+ ## 🔧 Error Handling
357
+
358
+ ```javascript
359
+ try {
360
+ const result = await client.scrape(url);
361
+
362
+ if (result.success) {
363
+ console.log('Success:', result.data);
364
+ } else {
365
+ console.error('Scraping failed:', result.error);
366
+ }
367
+ } catch (error) {
368
+ console.error('Request failed:', error.message);
369
+ }
370
+ ```
371
+
372
+ Common error scenarios:
373
+ - **Invalid API Key**: Check your API key and account status
374
+ - **Rate Limited**: Upgrade your plan or reduce request frequency
375
+ - **Timeout**: Increase timeout or try a simpler extraction method
376
+ - **Invalid URL**: Ensure the URL is accessible and properly formatted
377
+
378
+ ## 🚀 TypeScript Support
379
+
380
+ Full TypeScript support with comprehensive type definitions:
381
+
382
+ ```typescript
383
+ import { BrowserNativeClient, ScrapeResult, AnalyzeResult } from '@browsernative/client';
384
+
385
+ const client: BrowserNativeClient = new BrowserNativeClient('your-api-key');
386
+
387
+ const result: ScrapeResult = await client.scrape('https://example.com');
388
+ const analysis: AnalyzeResult = await client.analyze(url, question);
389
+ ```
390
+
391
+ ## 📊 Rate Limits
392
+
393
+ | Plan | Requests/Month | Rate Limit |
394
+ |------|----------------|------------|
395
+ | **Free** | 1,000 | 10/minute |
396
+ | **Starter** | 10,000 | 60/minute |
397
+ | **Pro** | 100,000 | 300/minute |
398
+ | **Enterprise** | Unlimited | Custom |
399
+
400
+ ## 🤝 Support
401
+
402
+ - 📧 **Email**: [support@browsernative.monostate.ai](mailto:support@browsernative.monostate.ai)
403
+ - 📖 **Documentation**: [browsernative.monostate.ai/docs](https://browsernative.monostate.ai/docs)
404
+ - 🐛 **Issues**: [GitHub Issues](https://github.com/browsernative/client-sdk/issues)
405
+ - 💬 **Discord**: [Join our community](https://discord.gg/browsernative)
406
+
407
+ ## 📄 License
408
+
409
+ MIT License - see [LICENSE](../../LICENSE) file for details.
410
+
411
+ ---
412
+
413
+ <div align="center">
414
+
415
+ **Built with ❤️ for developers who value speed and reliability**
416
+
417
+ [🌐 Website](https://browsernative.monostate.ai) | [📖 Docs](https://browsernative.monostate.ai/docs) | [🚀 Get API Key](https://browsernative.monostate.ai/signup)
418
+
419
+ </div>
package/index.d.ts ADDED
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Browser Native Client SDK TypeScript Definitions
3
+ */
4
+
5
+ export interface ClientOptions {
6
+ /** Base URL for the API (default: https://browsernative.monostate.ai) */
7
+ baseUrl?: string;
8
+ /** Request timeout in milliseconds (default: 30000) */
9
+ timeout?: number;
10
+ /** Number of retry attempts (default: 2) */
11
+ retries?: number;
12
+ /** Enable verbose logging (default: false) */
13
+ verbose?: boolean;
14
+ }
15
+
16
+ export interface ScrapeOptions {
17
+ /** Include screenshot in the response */
18
+ includeScreenshot?: boolean;
19
+ /** Wait for specific selector before extracting content */
20
+ waitForSelector?: string;
21
+ /** Custom user agent string */
22
+ userAgent?: string;
23
+ /** Viewport size for rendering */
24
+ viewport?: {
25
+ width: number;
26
+ height: number;
27
+ };
28
+ /** Additional metadata to extract */
29
+ extractMetadata?: boolean;
30
+ }
31
+
32
+ export interface ScreenshotOptions extends ScrapeOptions {
33
+ /** Force full page screenshot */
34
+ fullPage?: boolean;
35
+ /** Image format (default: png) */
36
+ format?: 'png' | 'jpeg' | 'webp';
37
+ /** Image quality for JPEG (1-100) */
38
+ quality?: number;
39
+ }
40
+
41
+ export interface AnalyzeOptions extends ScrapeOptions {
42
+ /** Language for the AI response */
43
+ language?: 'en' | 'pt' | 'es' | 'fr' | 'de' | 'auto';
44
+ /** Response style */
45
+ style?: 'concise' | 'detailed' | 'technical';
46
+ }
47
+
48
+ export interface ScrapeResult {
49
+ /** Whether the request was successful */
50
+ success: boolean;
51
+ /** Extracted content data */
52
+ data?: {
53
+ title?: string;
54
+ description?: string;
55
+ content?: string;
56
+ metadata?: Record<string, any>;
57
+ links?: string[];
58
+ images?: string[];
59
+ };
60
+ /** Scraping method used */
61
+ method?: 'direct' | 'lightpanda' | 'puppeteer';
62
+ /** Performance information */
63
+ performance?: {
64
+ totalTime: number;
65
+ method: string;
66
+ };
67
+ /** Base64 encoded screenshot (if requested) */
68
+ screenshot?: string;
69
+ /** Error message (if failed) */
70
+ error?: string;
71
+ /** Response time in milliseconds */
72
+ responseTime: number;
73
+ /** Attempt number that succeeded */
74
+ attempt?: number;
75
+ }
76
+
77
+ export interface AnalyzeResult extends ScrapeResult {
78
+ /** AI analysis response */
79
+ analysis?: {
80
+ answer: string;
81
+ confidence: number;
82
+ processingTime: number;
83
+ language: string;
84
+ };
85
+ }
86
+
87
+ export interface UsageResult {
88
+ success: boolean;
89
+ data?: {
90
+ /** Daily usage breakdown */
91
+ dailyUsage: Array<{
92
+ date: string;
93
+ requests: number;
94
+ scrapeRequests: number;
95
+ analyzeRequests: number;
96
+ }>;
97
+ /** Monthly totals */
98
+ monthlyTotal: {
99
+ totalRequests: number;
100
+ scrapeTotal: number;
101
+ analyzeTotal: number;
102
+ };
103
+ /** Current plan information */
104
+ currentUsage: number;
105
+ usageLimit: number;
106
+ planType: string;
107
+ subscriptionStatus: string;
108
+ currentPeriodEnd: string;
109
+ };
110
+ error?: string;
111
+ responseTime: number;
112
+ }
113
+
114
+ export interface HealthResult {
115
+ success: boolean;
116
+ data?: {
117
+ status: 'healthy' | 'degraded' | 'unhealthy';
118
+ version: string;
119
+ uptime: number;
120
+ services: {
121
+ scraping: boolean;
122
+ ai: boolean;
123
+ database: boolean;
124
+ };
125
+ };
126
+ error?: string;
127
+ responseTime: number;
128
+ }
129
+
130
+ /**
131
+ * Browser Native API Client
132
+ */
133
+ export declare class BrowserNativeClient {
134
+ constructor(apiKey: string, options?: ClientOptions);
135
+
136
+ /**
137
+ * Scrape a webpage and extract structured content
138
+ */
139
+ scrape(url: string, options?: ScrapeOptions): Promise<ScrapeResult>;
140
+
141
+ /**
142
+ * Scrape a webpage and take a screenshot
143
+ */
144
+ screenshot(url: string, options?: ScreenshotOptions): Promise<ScrapeResult>;
145
+
146
+ /**
147
+ * Extract content and answer questions using AI
148
+ */
149
+ analyze(url: string, question: string, options?: AnalyzeOptions): Promise<AnalyzeResult>;
150
+
151
+ /**
152
+ * Get account usage statistics
153
+ */
154
+ getUsage(days?: number): Promise<UsageResult>;
155
+
156
+ /**
157
+ * Check API health and your account status
158
+ */
159
+ healthCheck(): Promise<HealthResult>;
160
+ }
161
+
162
+ /**
163
+ * Convenience function for quick scraping without instantiating a client
164
+ */
165
+ export declare function quickScrape(
166
+ url: string,
167
+ apiKey: string,
168
+ options?: ScrapeOptions
169
+ ): Promise<ScrapeResult>;
170
+
171
+ /**
172
+ * Convenience function for taking screenshots
173
+ */
174
+ export declare function quickScreenshot(
175
+ url: string,
176
+ apiKey: string,
177
+ options?: ScreenshotOptions
178
+ ): Promise<ScrapeResult>;
179
+
180
+ /**
181
+ * Convenience function for AI analysis
182
+ */
183
+ export declare function quickAnalyze(
184
+ url: string,
185
+ question: string,
186
+ apiKey: string,
187
+ options?: AnalyzeOptions
188
+ ): Promise<AnalyzeResult>;
189
+
190
+ export default BrowserNativeClient;
package/index.js ADDED
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Browser Native Client SDK
3
+ *
4
+ * A lightweight JavaScript client for the Browser Native web scraping API.
5
+ * Works in browsers, Node.js, and edge environments.
6
+ */
7
+
8
+ export class BrowserNativeClient {
9
+ constructor(apiKey, options = {}) {
10
+ if (!apiKey) {
11
+ throw new Error('API key is required. Get one at https://browsernative.monostate.ai');
12
+ }
13
+
14
+ this.apiKey = apiKey;
15
+ this.baseUrl = options.baseUrl || 'https://bnca-api.fly.dev';
16
+ this.timeout = options.timeout || 30000;
17
+ this.retries = options.retries || 2;
18
+ this.verbose = options.verbose || false;
19
+ }
20
+
21
+ /**
22
+ * Scrape a webpage and extract structured content
23
+ * @param {string} url - The URL to scrape
24
+ * @param {object} options - Scraping options
25
+ * @returns {Promise<object>} Scraping result
26
+ */
27
+ async scrape(url, options = {}) {
28
+ const payload = {
29
+ url,
30
+ screenshot: options.includeScreenshot || false,
31
+ ...options
32
+ };
33
+
34
+ return this._makeRequest('/scrapeurl', payload);
35
+ }
36
+
37
+ /**
38
+ * Scrape a webpage and take a screenshot
39
+ * @param {string} url - The URL to scrape
40
+ * @param {object} options - Screenshot options
41
+ * @returns {Promise<object>} Screenshot result with base64 image
42
+ */
43
+ async screenshot(url, options = {}) {
44
+ const payload = {
45
+ url,
46
+ screenshot: true,
47
+ ...options
48
+ };
49
+
50
+ return this._makeRequest('/scrapeurl', payload);
51
+ }
52
+
53
+ /**
54
+ * Extract content and answer questions using AI
55
+ * @param {string} url - The URL to analyze
56
+ * @param {string} question - The question to answer
57
+ * @param {object} options - Analysis options
58
+ * @returns {Promise<object>} AI analysis result
59
+ */
60
+ async analyze(url, question, options = {}) {
61
+ const payload = {
62
+ url,
63
+ question,
64
+ screenshot: options.includeScreenshot || false,
65
+ ...options
66
+ };
67
+
68
+ return this._makeRequest('/aireply', payload);
69
+ }
70
+
71
+ /**
72
+ * Get account usage statistics
73
+ * @param {number} days - Number of days to fetch (max 30)
74
+ * @returns {Promise<object>} Usage statistics
75
+ */
76
+ async getUsage(days = 30) {
77
+ return this._makeRequest('/stats', {}, 'GET');
78
+ }
79
+
80
+ /**
81
+ * Check API health and your account status
82
+ * @returns {Promise<object>} Health check result
83
+ */
84
+ async healthCheck() {
85
+ return this._makeRequest('/health', {}, 'GET');
86
+ }
87
+
88
+ /**
89
+ * Make an authenticated request to the API
90
+ * @private
91
+ */
92
+ async _makeRequest(endpoint, payload = {}, method = 'POST', queryParams = '') {
93
+ const url = `${this.baseUrl}${endpoint}${queryParams}`;
94
+ const startTime = Date.now();
95
+
96
+ let lastError;
97
+
98
+ for (let attempt = 1; attempt <= this.retries + 1; attempt++) {
99
+ try {
100
+ if (this.verbose) {
101
+ console.log(`Browser Native: ${method} ${url} (attempt ${attempt})`);
102
+ }
103
+
104
+ const options = {
105
+ method,
106
+ headers: {
107
+ 'Authorization': `Bearer ${this.apiKey}`,
108
+ 'Content-Type': 'application/json',
109
+ 'User-Agent': 'Browser Native Client SDK/1.0.0'
110
+ }
111
+ };
112
+
113
+ if (method !== 'GET') {
114
+ options.body = JSON.stringify(payload);
115
+ }
116
+
117
+ // Set up timeout
118
+ const controller = new AbortController();
119
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
120
+ options.signal = controller.signal;
121
+
122
+ const response = await fetch(url, options);
123
+ clearTimeout(timeoutId);
124
+
125
+ const responseTime = Date.now() - startTime;
126
+
127
+ if (!response.ok) {
128
+ const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
129
+ throw new Error(`API Error (${response.status}): ${errorData.error || response.statusText}`);
130
+ }
131
+
132
+ const data = await response.json();
133
+
134
+ if (this.verbose) {
135
+ console.log(`Browser Native: Request completed in ${responseTime}ms`);
136
+ }
137
+
138
+ return {
139
+ success: true,
140
+ data,
141
+ responseTime,
142
+ attempt
143
+ };
144
+
145
+ } catch (error) {
146
+ lastError = error;
147
+
148
+ if (attempt <= this.retries && !error.name === 'AbortError') {
149
+ const delay = Math.pow(2, attempt - 1) * 1000; // Exponential backoff
150
+ if (this.verbose) {
151
+ console.log(`Browser Native: Attempt ${attempt} failed, retrying in ${delay}ms...`);
152
+ }
153
+ await new Promise(resolve => setTimeout(resolve, delay));
154
+ continue;
155
+ }
156
+
157
+ break;
158
+ }
159
+ }
160
+
161
+ // All retries failed
162
+ return {
163
+ success: false,
164
+ error: lastError.message || 'Request failed',
165
+ responseTime: Date.now() - startTime
166
+ };
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Convenience function for quick scraping without instantiating a client
172
+ * @param {string} url - The URL to scrape
173
+ * @param {string} apiKey - Your API key
174
+ * @param {object} options - Additional options
175
+ * @returns {Promise<object>} Scraping result
176
+ */
177
+ export async function quickScrape(url, apiKey, options = {}) {
178
+ const client = new BrowserNativeClient(apiKey, options);
179
+ return client.scrape(url, options);
180
+ }
181
+
182
+ /**
183
+ * Convenience function for taking screenshots
184
+ * @param {string} url - The URL to capture
185
+ * @param {string} apiKey - Your API key
186
+ * @param {object} options - Additional options
187
+ * @returns {Promise<object>} Screenshot result
188
+ */
189
+ export async function quickScreenshot(url, apiKey, options = {}) {
190
+ const client = new BrowserNativeClient(apiKey, options);
191
+ return client.screenshot(url, options);
192
+ }
193
+
194
+ /**
195
+ * Convenience function for AI analysis
196
+ * @param {string} url - The URL to analyze
197
+ * @param {string} question - The question to answer
198
+ * @param {string} apiKey - Your API key
199
+ * @param {object} options - Additional options
200
+ * @returns {Promise<object>} Analysis result
201
+ */
202
+ export async function quickAnalyze(url, question, apiKey, options = {}) {
203
+ const client = new BrowserNativeClient(apiKey, options);
204
+ return client.analyze(url, question, options);
205
+ }
206
+
207
+ // Default export for CommonJS compatibility
208
+ export default BrowserNativeClient;
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@monostate/browsernative-client",
3
+ "version": "1.0.1",
4
+ "description": "Browser Native client SDK for web scraping and content extraction API",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./index.js",
11
+ "types": "./index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "index.js",
16
+ "index.d.ts",
17
+ "README.md",
18
+ "package.json"
19
+ ],
20
+ "keywords": [
21
+ "web-scraping",
22
+ "api-client",
23
+ "browser-native",
24
+ "content-extraction",
25
+ "web-automation",
26
+ "data-extraction",
27
+ "javascript",
28
+ "typescript",
29
+ "browser",
30
+ "client-sdk"
31
+ ],
32
+ "author": "Browser Native Team",
33
+ "license": "MIT",
34
+ "dependencies": {},
35
+ "engines": {
36
+ "node": ">=16.0.0"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/browsernative/client-sdk.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/browsernative/client-sdk/issues"
44
+ },
45
+ "homepage": "https://browsernative.monostate.ai",
46
+ "publishConfig": {
47
+ "access": "public"
48
+ }
49
+ }