@blinkdotnew/sdk 0.4.1 β 0.5.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 +269 -1
- package/dist/index.d.mts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +38 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,6 +52,18 @@ const text = await blink.data.extractFromUrl("https://example.com/document.pdf")
|
|
|
52
52
|
const { markdown, metadata, links } = await blink.data.scrape("https://competitor.com")
|
|
53
53
|
const screenshotUrl = await blink.data.screenshot("https://competitor.com")
|
|
54
54
|
|
|
55
|
+
// Web search (get real-time information)
|
|
56
|
+
const searchResults = await blink.data.search("chatgpt latest news", { type: 'news' })
|
|
57
|
+
const localResults = await blink.data.search("best restaurants", { location: "San Francisco,CA,United States" })
|
|
58
|
+
|
|
59
|
+
// Secure API proxy (call external APIs with secret substitution)
|
|
60
|
+
const response = await blink.data.fetch({
|
|
61
|
+
url: "https://api.sendgrid.com/v3/mail/send",
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: { "Authorization": "Bearer {{sendgrid_api_key}}" },
|
|
64
|
+
body: { /* email data */ }
|
|
65
|
+
})
|
|
66
|
+
|
|
55
67
|
// Storage operations (instant - returns public URL directly)
|
|
56
68
|
const { publicUrl } = await blink.storage.upload(
|
|
57
69
|
file,
|
|
@@ -76,7 +88,7 @@ This SDK powers every Blink-generated app with:
|
|
|
76
88
|
- **π Authentication**: JWT-based auth with automatic token management
|
|
77
89
|
- **ποΈ Database**: PostgREST-compatible CRUD operations with advanced filtering
|
|
78
90
|
- **π€ AI**: Text generation with web search, object generation, image creation, speech synthesis, and transcription
|
|
79
|
-
- **π Data**: Extract text content from documents,
|
|
91
|
+
- **π Data**: Extract text content from documents, secure API proxy with secret substitution, web scraping, screenshots, and web search
|
|
80
92
|
- **π Storage**: File upload, download, and management
|
|
81
93
|
- **π Universal**: Works on client-side and server-side
|
|
82
94
|
- **π± Framework Agnostic**: React, Vue, Svelte, vanilla JS, Node.js, Deno
|
|
@@ -321,6 +333,127 @@ const fullPageUrl = await blink.data.screenshot('https://example.com', {
|
|
|
321
333
|
height: 1080
|
|
322
334
|
});
|
|
323
335
|
|
|
336
|
+
// π₯ Web Search (NEW!) - Google search results with clean structure
|
|
337
|
+
// Perfect for getting real-time information and current data
|
|
338
|
+
|
|
339
|
+
// Basic web search - just provide a query
|
|
340
|
+
const searchResults = await blink.data.search('chatgpt');
|
|
341
|
+
console.log(searchResults.organic_results); // Main search results
|
|
342
|
+
console.log(searchResults.related_searches); // Related search suggestions
|
|
343
|
+
console.log(searchResults.people_also_ask); // People also ask questions
|
|
344
|
+
|
|
345
|
+
// Search with location for local results
|
|
346
|
+
const localResults = await blink.data.search('best restaurants', {
|
|
347
|
+
location: 'San Francisco,CA,United States'
|
|
348
|
+
});
|
|
349
|
+
console.log(localResults.local_results); // Local business results
|
|
350
|
+
console.log(localResults.organic_results); // Regular web results
|
|
351
|
+
|
|
352
|
+
// News search - get latest news articles
|
|
353
|
+
const newsResults = await blink.data.search('artificial intelligence', {
|
|
354
|
+
type: 'news'
|
|
355
|
+
});
|
|
356
|
+
console.log(newsResults.news_results); // News articles with dates and sources
|
|
357
|
+
|
|
358
|
+
// Image search - find images
|
|
359
|
+
const imageResults = await blink.data.search('elon musk', {
|
|
360
|
+
type: 'images',
|
|
361
|
+
limit: 20
|
|
362
|
+
});
|
|
363
|
+
console.log(imageResults.image_results); // Image results with thumbnails
|
|
364
|
+
|
|
365
|
+
// Search in different languages
|
|
366
|
+
const spanishResults = await blink.data.search('noticias tecnologΓa', {
|
|
367
|
+
language: 'es',
|
|
368
|
+
type: 'news'
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Shopping search - find products
|
|
372
|
+
const shoppingResults = await blink.data.search('macbook pro', {
|
|
373
|
+
type: 'shopping'
|
|
374
|
+
});
|
|
375
|
+
console.log(shoppingResults.shopping_results); // Product results with prices
|
|
376
|
+
|
|
377
|
+
// All search types return consistent, structured data:
|
|
378
|
+
// - organic_results: Main search results (always included)
|
|
379
|
+
// - related_searches: Related search suggestions
|
|
380
|
+
// - people_also_ask: FAQ-style questions and answers
|
|
381
|
+
// - local_results: Local businesses (when location provided)
|
|
382
|
+
// - news_results: News articles (when type='news')
|
|
383
|
+
// - image_results: Images (when type='images')
|
|
384
|
+
// - shopping_results: Products (when type='shopping')
|
|
385
|
+
// - ads: Sponsored results (when present)
|
|
386
|
+
|
|
387
|
+
// π₯ Secure API Proxy (NEW!) - Make API calls with secret substitution
|
|
388
|
+
|
|
389
|
+
// Basic API call with secret substitution
|
|
390
|
+
const response = await blink.data.fetch({
|
|
391
|
+
url: 'https://api.sendgrid.com/v3/mail/send',
|
|
392
|
+
method: 'POST',
|
|
393
|
+
headers: {
|
|
394
|
+
'Authorization': 'Bearer {{sendgrid_api_key}}', // Secret replaced server-side
|
|
395
|
+
'Content-Type': 'application/json'
|
|
396
|
+
},
|
|
397
|
+
body: {
|
|
398
|
+
from: { email: 'me@example.com' },
|
|
399
|
+
personalizations: [{ to: [{ email: 'user@example.com' }] }],
|
|
400
|
+
subject: 'Hello from Blink',
|
|
401
|
+
content: [{ type: 'text/plain', value: 'Sent securely through Blink!' }]
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
console.log('Email sent:', response.status === 200);
|
|
406
|
+
console.log('Response:', response.body);
|
|
407
|
+
console.log('Took:', response.durationMs, 'ms');
|
|
408
|
+
|
|
409
|
+
// GET request with secret in URL and query params
|
|
410
|
+
const weatherData = await blink.data.fetch({
|
|
411
|
+
url: 'https://api.openweathermap.org/data/2.5/weather',
|
|
412
|
+
method: 'GET',
|
|
413
|
+
query: {
|
|
414
|
+
q: 'London',
|
|
415
|
+
appid: '{{openweather_api_key}}', // Secret replaced in query params
|
|
416
|
+
units: 'metric'
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
console.log('Weather:', weatherData.body.main.temp, 'Β°C');
|
|
421
|
+
|
|
422
|
+
// Async/background requests (fire-and-forget)
|
|
423
|
+
const asyncResponse = await blink.data.fetchAsync({
|
|
424
|
+
url: 'https://api.stripe.com/v1/customers',
|
|
425
|
+
method: 'POST',
|
|
426
|
+
headers: {
|
|
427
|
+
'Authorization': 'Bearer {{stripe_secret_key}}',
|
|
428
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
429
|
+
},
|
|
430
|
+
body: 'email=customer@example.com&name=John Doe'
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
console.log(asyncResponse.status); // 'triggered'
|
|
434
|
+
console.log(asyncResponse.message); // 'Request triggered in background'
|
|
435
|
+
|
|
436
|
+
// Multiple secrets in different places
|
|
437
|
+
const complexRequest = await blink.data.fetch({
|
|
438
|
+
url: 'https://api.github.com/repos/{{github_username}}/{{repo_name}}/issues',
|
|
439
|
+
method: 'POST',
|
|
440
|
+
headers: {
|
|
441
|
+
'Authorization': 'token {{github_token}}',
|
|
442
|
+
'Accept': 'application/vnd.github.v3+json',
|
|
443
|
+
'User-Agent': '{{app_name}}'
|
|
444
|
+
},
|
|
445
|
+
body: {
|
|
446
|
+
title: 'Bug Report',
|
|
447
|
+
body: 'Found via {{app_name}} monitoring'
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Secret substitution works everywhere:
|
|
452
|
+
// - URL path: /api/{{version}}/users
|
|
453
|
+
// - Query params: ?key={{api_key}}&user={{user_id}}
|
|
454
|
+
// - Headers: Authorization: Bearer {{token}}
|
|
455
|
+
// - Body: { "apiKey": "{{secret}}", "data": "{{value}}" }
|
|
456
|
+
|
|
324
457
|
// Error handling for data extraction
|
|
325
458
|
try {
|
|
326
459
|
const result = await blink.data.extractFromUrl('https://example.com/huge-file.pdf');
|
|
@@ -418,6 +551,47 @@ const todos = await blink.db.todos.list<Todo>({
|
|
|
418
551
|
// todos is fully typed as ListResponse<Todo>
|
|
419
552
|
```
|
|
420
553
|
|
|
554
|
+
### Secret Management for API Proxy
|
|
555
|
+
|
|
556
|
+
The `blink.data.fetch()` method allows you to make secure API calls with automatic secret substitution. Here's how to set it up:
|
|
557
|
+
|
|
558
|
+
**Step 1: Store your secrets in your Blink project**
|
|
559
|
+
Visit your project dashboard at [blink.new](https://blink.new) and add your API keys in the "Secrets" section:
|
|
560
|
+
- `sendgrid_api_key` β `SG.abc123...`
|
|
561
|
+
- `openweather_api_key` β `d4f5g6h7...`
|
|
562
|
+
- `stripe_secret_key` β `sk_live_abc123...`
|
|
563
|
+
|
|
564
|
+
**Step 2: Use secrets in your API calls**
|
|
565
|
+
```typescript
|
|
566
|
+
// Secrets are automatically substituted server-side - never exposed to frontend
|
|
567
|
+
const result = await blink.data.fetch({
|
|
568
|
+
url: 'https://api.example.com/endpoint',
|
|
569
|
+
headers: {
|
|
570
|
+
'Authorization': 'Bearer {{your_secret_key}}' // Replaced with actual value
|
|
571
|
+
}
|
|
572
|
+
})
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Step 3: Secret substitution works everywhere**
|
|
576
|
+
```typescript
|
|
577
|
+
await blink.data.fetch({
|
|
578
|
+
url: 'https://api.{{service_domain}}/v{{api_version}}/users/{{user_id}}',
|
|
579
|
+
query: {
|
|
580
|
+
key: '{{api_key}}',
|
|
581
|
+
format: 'json'
|
|
582
|
+
},
|
|
583
|
+
headers: {
|
|
584
|
+
'X-API-Key': '{{secondary_key}}'
|
|
585
|
+
},
|
|
586
|
+
body: {
|
|
587
|
+
token: '{{auth_token}}',
|
|
588
|
+
data: 'regular string data'
|
|
589
|
+
}
|
|
590
|
+
})
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
All `{{secret_name}}` placeholders are replaced with encrypted values from your project's secret store. Secrets never leave the server and are never visible to your frontend code.
|
|
594
|
+
|
|
421
595
|
## π Framework Examples
|
|
422
596
|
|
|
423
597
|
### React
|
|
@@ -442,6 +616,100 @@ function App() {
|
|
|
442
616
|
|
|
443
617
|
return <div>Welcome, {user.email}!</div>
|
|
444
618
|
}
|
|
619
|
+
|
|
620
|
+
// React example with search functionality
|
|
621
|
+
function SearchResults() {
|
|
622
|
+
const [query, setQuery] = useState('')
|
|
623
|
+
const [results, setResults] = useState(null)
|
|
624
|
+
const [loading, setLoading] = useState(false)
|
|
625
|
+
|
|
626
|
+
const handleSearch = async () => {
|
|
627
|
+
if (!query.trim()) return
|
|
628
|
+
|
|
629
|
+
setLoading(true)
|
|
630
|
+
try {
|
|
631
|
+
const searchResults = await blink.data.search(query, {
|
|
632
|
+
type: 'news', // Get latest news
|
|
633
|
+
limit: 10
|
|
634
|
+
})
|
|
635
|
+
setResults(searchResults)
|
|
636
|
+
} catch (error) {
|
|
637
|
+
console.error('Search failed:', error)
|
|
638
|
+
} finally {
|
|
639
|
+
setLoading(false)
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
return (
|
|
644
|
+
<div>
|
|
645
|
+
<input
|
|
646
|
+
value={query}
|
|
647
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
648
|
+
placeholder="Search for news..."
|
|
649
|
+
onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
|
|
650
|
+
/>
|
|
651
|
+
<button onClick={handleSearch} disabled={loading}>
|
|
652
|
+
{loading ? 'Searching...' : 'Search'}
|
|
653
|
+
</button>
|
|
654
|
+
|
|
655
|
+
{results && (
|
|
656
|
+
<div>
|
|
657
|
+
<h3>News Results:</h3>
|
|
658
|
+
{results.news_results?.map((article, i) => (
|
|
659
|
+
<div key={i}>
|
|
660
|
+
<h4><a href={article.link}>{article.title}</a></h4>
|
|
661
|
+
<p>{article.snippet}</p>
|
|
662
|
+
<small>{article.source} - {article.date}</small>
|
|
663
|
+
</div>
|
|
664
|
+
))}
|
|
665
|
+
|
|
666
|
+
<h3>Related Searches:</h3>
|
|
667
|
+
{results.related_searches?.map((suggestion, i) => (
|
|
668
|
+
<button key={i} onClick={() => setQuery(suggestion)}>
|
|
669
|
+
{suggestion}
|
|
670
|
+
</button>
|
|
671
|
+
))}
|
|
672
|
+
</div>
|
|
673
|
+
)}
|
|
674
|
+
</div>
|
|
675
|
+
)
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// React example with secure API calls
|
|
679
|
+
function EmailSender() {
|
|
680
|
+
const [status, setStatus] = useState('')
|
|
681
|
+
|
|
682
|
+
const sendEmail = async () => {
|
|
683
|
+
setStatus('Sending...')
|
|
684
|
+
try {
|
|
685
|
+
const response = await blink.data.fetch({
|
|
686
|
+
url: 'https://api.sendgrid.com/v3/mail/send',
|
|
687
|
+
method: 'POST',
|
|
688
|
+
headers: {
|
|
689
|
+
'Authorization': 'Bearer {{sendgrid_api_key}}', // Secret safe on server
|
|
690
|
+
'Content-Type': 'application/json'
|
|
691
|
+
},
|
|
692
|
+
body: {
|
|
693
|
+
from: { email: 'app@example.com' },
|
|
694
|
+
personalizations: [{ to: [{ email: user.email }] }],
|
|
695
|
+
subject: 'Welcome to our app!',
|
|
696
|
+
content: [{ type: 'text/plain', value: 'Thanks for signing up!' }]
|
|
697
|
+
}
|
|
698
|
+
})
|
|
699
|
+
|
|
700
|
+
setStatus(response.status === 202 ? 'Email sent!' : 'Failed to send')
|
|
701
|
+
} catch (error) {
|
|
702
|
+
setStatus('Error: ' + error.message)
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
return (
|
|
707
|
+
<div>
|
|
708
|
+
<button onClick={sendEmail}>Send Welcome Email</button>
|
|
709
|
+
<p>{status}</p>
|
|
710
|
+
</div>
|
|
711
|
+
)
|
|
712
|
+
}
|
|
445
713
|
```
|
|
446
714
|
|
|
447
715
|
### Next.js API Routes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BlinkClientConfig, BlinkUser, AuthState, HttpClient, TableOperations, CreateOptions, UpsertOptions, QueryOptions, ListResponse, UpdateOptions, FilterCondition, ScrapeResult, BlinkStorage, BlinkAI, StorageUploadOptions, StorageUploadResponse, TextGenerationRequest, TextGenerationResponse, ObjectGenerationRequest, ObjectGenerationResponse, ImageGenerationRequest, ImageGenerationResponse, SpeechGenerationRequest, SpeechGenerationResponse, TranscriptionRequest, TranscriptionResponse } from '@blink/core';
|
|
1
|
+
import { BlinkClientConfig, BlinkUser, AuthState, HttpClient, TableOperations, CreateOptions, UpsertOptions, QueryOptions, ListResponse, UpdateOptions, FilterCondition, ScrapeResult, FetchRequest, FetchResponse, AsyncFetchResponse, SearchResponse, BlinkStorage, BlinkAI, StorageUploadOptions, StorageUploadResponse, TextGenerationRequest, TextGenerationResponse, ObjectGenerationRequest, ObjectGenerationResponse, ImageGenerationRequest, ImageGenerationResponse, SpeechGenerationRequest, SpeechGenerationResponse, TranscriptionRequest, TranscriptionResponse } from '@blink/core';
|
|
2
2
|
export { AuthState, AuthTokens, BlinkAI, BlinkClientConfig, BlinkData, BlinkStorage, BlinkUser, CreateOptions, DataExtraction, FileObject, FilterCondition, ImageGenerationRequest, ImageGenerationResponse, ListResponse, Message, ObjectGenerationRequest, ObjectGenerationResponse, QueryOptions, SpeechGenerationRequest, SpeechGenerationResponse, StorageUploadOptions, StorageUploadResponse, TableOperations, TextGenerationRequest, TextGenerationResponse, TokenUsage, TranscriptionRequest, TranscriptionResponse, UpdateOptions, UpsertOptions } from '@blink/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -211,6 +211,14 @@ interface BlinkData {
|
|
|
211
211
|
width?: number;
|
|
212
212
|
height?: number;
|
|
213
213
|
}): Promise<string>;
|
|
214
|
+
fetch(request: FetchRequest): Promise<FetchResponse>;
|
|
215
|
+
fetchAsync(request: Omit<FetchRequest, 'async'>): Promise<AsyncFetchResponse>;
|
|
216
|
+
search(query: string, options?: {
|
|
217
|
+
location?: string;
|
|
218
|
+
type?: 'news' | 'images' | 'videos' | 'shopping';
|
|
219
|
+
language?: string;
|
|
220
|
+
limit?: number;
|
|
221
|
+
}): Promise<SearchResponse>;
|
|
214
222
|
}
|
|
215
223
|
declare class BlinkDataImpl implements BlinkData {
|
|
216
224
|
private httpClient;
|
|
@@ -230,6 +238,14 @@ declare class BlinkDataImpl implements BlinkData {
|
|
|
230
238
|
width?: number;
|
|
231
239
|
height?: number;
|
|
232
240
|
}): Promise<string>;
|
|
241
|
+
fetch(request: FetchRequest): Promise<FetchResponse>;
|
|
242
|
+
fetchAsync(request: Omit<FetchRequest, 'async'>): Promise<AsyncFetchResponse>;
|
|
243
|
+
search(query: string, options?: {
|
|
244
|
+
location?: string;
|
|
245
|
+
type?: 'news' | 'images' | 'videos' | 'shopping';
|
|
246
|
+
language?: string;
|
|
247
|
+
limit?: number;
|
|
248
|
+
}): Promise<SearchResponse>;
|
|
233
249
|
}
|
|
234
250
|
|
|
235
251
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BlinkClientConfig, BlinkUser, AuthState, HttpClient, TableOperations, CreateOptions, UpsertOptions, QueryOptions, ListResponse, UpdateOptions, FilterCondition, ScrapeResult, BlinkStorage, BlinkAI, StorageUploadOptions, StorageUploadResponse, TextGenerationRequest, TextGenerationResponse, ObjectGenerationRequest, ObjectGenerationResponse, ImageGenerationRequest, ImageGenerationResponse, SpeechGenerationRequest, SpeechGenerationResponse, TranscriptionRequest, TranscriptionResponse } from '@blink/core';
|
|
1
|
+
import { BlinkClientConfig, BlinkUser, AuthState, HttpClient, TableOperations, CreateOptions, UpsertOptions, QueryOptions, ListResponse, UpdateOptions, FilterCondition, ScrapeResult, FetchRequest, FetchResponse, AsyncFetchResponse, SearchResponse, BlinkStorage, BlinkAI, StorageUploadOptions, StorageUploadResponse, TextGenerationRequest, TextGenerationResponse, ObjectGenerationRequest, ObjectGenerationResponse, ImageGenerationRequest, ImageGenerationResponse, SpeechGenerationRequest, SpeechGenerationResponse, TranscriptionRequest, TranscriptionResponse } from '@blink/core';
|
|
2
2
|
export { AuthState, AuthTokens, BlinkAI, BlinkClientConfig, BlinkData, BlinkStorage, BlinkUser, CreateOptions, DataExtraction, FileObject, FilterCondition, ImageGenerationRequest, ImageGenerationResponse, ListResponse, Message, ObjectGenerationRequest, ObjectGenerationResponse, QueryOptions, SpeechGenerationRequest, SpeechGenerationResponse, StorageUploadOptions, StorageUploadResponse, TableOperations, TextGenerationRequest, TextGenerationResponse, TokenUsage, TranscriptionRequest, TranscriptionResponse, UpdateOptions, UpsertOptions } from '@blink/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -211,6 +211,14 @@ interface BlinkData {
|
|
|
211
211
|
width?: number;
|
|
212
212
|
height?: number;
|
|
213
213
|
}): Promise<string>;
|
|
214
|
+
fetch(request: FetchRequest): Promise<FetchResponse>;
|
|
215
|
+
fetchAsync(request: Omit<FetchRequest, 'async'>): Promise<AsyncFetchResponse>;
|
|
216
|
+
search(query: string, options?: {
|
|
217
|
+
location?: string;
|
|
218
|
+
type?: 'news' | 'images' | 'videos' | 'shopping';
|
|
219
|
+
language?: string;
|
|
220
|
+
limit?: number;
|
|
221
|
+
}): Promise<SearchResponse>;
|
|
214
222
|
}
|
|
215
223
|
declare class BlinkDataImpl implements BlinkData {
|
|
216
224
|
private httpClient;
|
|
@@ -230,6 +238,14 @@ declare class BlinkDataImpl implements BlinkData {
|
|
|
230
238
|
width?: number;
|
|
231
239
|
height?: number;
|
|
232
240
|
}): Promise<string>;
|
|
241
|
+
fetch(request: FetchRequest): Promise<FetchResponse>;
|
|
242
|
+
fetchAsync(request: Omit<FetchRequest, 'async'>): Promise<AsyncFetchResponse>;
|
|
243
|
+
search(query: string, options?: {
|
|
244
|
+
location?: string;
|
|
245
|
+
type?: 'news' | 'images' | 'videos' | 'shopping';
|
|
246
|
+
language?: string;
|
|
247
|
+
limit?: number;
|
|
248
|
+
}): Promise<SearchResponse>;
|
|
233
249
|
}
|
|
234
250
|
|
|
235
251
|
/**
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,12 @@ var BlinkAIError = class extends BlinkError {
|
|
|
40
40
|
this.name = "BlinkAIError";
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
|
+
var BlinkDataError = class extends BlinkError {
|
|
44
|
+
constructor(message, status, details) {
|
|
45
|
+
super(message, "DATA_ERROR", status, details);
|
|
46
|
+
this.name = "BlinkDataError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
43
49
|
|
|
44
50
|
// ../core/src/query-builder.ts
|
|
45
51
|
function buildFilterQuery(condition) {
|
|
@@ -564,6 +570,12 @@ var HttpClient = class {
|
|
|
564
570
|
body: JSON.stringify(request)
|
|
565
571
|
});
|
|
566
572
|
}
|
|
573
|
+
async dataFetch(projectId, request) {
|
|
574
|
+
return this.post(`/api/data/${projectId}/fetch`, request);
|
|
575
|
+
}
|
|
576
|
+
async dataSearch(projectId, request) {
|
|
577
|
+
return this.post(`/api/data/${projectId}/search`, request);
|
|
578
|
+
}
|
|
567
579
|
/**
|
|
568
580
|
* Private helper methods
|
|
569
581
|
*/
|
|
@@ -2392,6 +2404,32 @@ var BlinkDataImpl = class {
|
|
|
2392
2404
|
const response = await this.httpClient.dataScreenshot(this.projectId, request);
|
|
2393
2405
|
return response.data.url;
|
|
2394
2406
|
}
|
|
2407
|
+
async fetch(request) {
|
|
2408
|
+
const response = await this.httpClient.dataFetch(this.projectId, request);
|
|
2409
|
+
if ("status" in response.data && "headers" in response.data) {
|
|
2410
|
+
return response.data;
|
|
2411
|
+
}
|
|
2412
|
+
throw new BlinkDataError("Unexpected response format from fetch endpoint");
|
|
2413
|
+
}
|
|
2414
|
+
async fetchAsync(request) {
|
|
2415
|
+
const asyncRequest = { ...request, async: true };
|
|
2416
|
+
const response = await this.httpClient.dataFetch(this.projectId, asyncRequest);
|
|
2417
|
+
if ("status" in response.data && response.data.status === "triggered") {
|
|
2418
|
+
return response.data;
|
|
2419
|
+
}
|
|
2420
|
+
throw new BlinkDataError("Unexpected response format from async fetch endpoint");
|
|
2421
|
+
}
|
|
2422
|
+
async search(query, options) {
|
|
2423
|
+
const request = {
|
|
2424
|
+
q: query,
|
|
2425
|
+
location: options?.location,
|
|
2426
|
+
hl: options?.language || "en",
|
|
2427
|
+
tbm: options?.type === "news" ? "nws" : options?.type === "images" ? "isch" : options?.type === "videos" ? "vid" : options?.type === "shopping" ? "shop" : void 0,
|
|
2428
|
+
num: options?.limit
|
|
2429
|
+
};
|
|
2430
|
+
const response = await this.httpClient.dataSearch(this.projectId, request);
|
|
2431
|
+
return response.data;
|
|
2432
|
+
}
|
|
2395
2433
|
};
|
|
2396
2434
|
|
|
2397
2435
|
// src/client.ts
|