@blinkdotnew/sdk 0.14.12 → 0.16.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 +22 -7
- package/dist/index.d.mts +143 -16
- package/dist/index.d.ts +143 -16
- package/dist/index.js +223 -32
- package/dist/index.mjs +223 -32
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -201,13 +201,13 @@ const unsubscribe = blink.auth.onAuthStateChanged((state) => {
|
|
|
201
201
|
|
|
202
202
|
**🎉 NEW: Automatic Case Conversion!**
|
|
203
203
|
The SDK now automatically converts between JavaScript camelCase and SQL snake_case:
|
|
204
|
-
- **
|
|
205
|
-
- **
|
|
204
|
+
- **Table names**: `blink.db.emailDrafts` → `email_drafts` table
|
|
205
|
+
- **Field names**: `userId`, `createdAt`, `isCompleted` → `user_id`, `created_at`, `is_completed`
|
|
206
206
|
- **No manual conversion needed!**
|
|
207
207
|
|
|
208
208
|
**⚠️ Important: Always Use camelCase in Your Code**
|
|
209
|
-
- ✅ **Correct**: `{ userId: user.id, createdAt: new Date() }`
|
|
210
|
-
- ❌ **Wrong**: `{ user_id: user.id, created_at: new Date() }`
|
|
209
|
+
- ✅ **Correct**: `blink.db.emailDrafts.create({ userId: user.id, createdAt: new Date() })`
|
|
210
|
+
- ❌ **Wrong**: `blink.db.email_drafts.create({ user_id: user.id, created_at: new Date() })`
|
|
211
211
|
|
|
212
212
|
|
|
213
213
|
```typescript
|
|
@@ -353,12 +353,27 @@ const { object: todoList } = await blink.ai.generateObject({
|
|
|
353
353
|
// })
|
|
354
354
|
// Error: "schema must be a JSON Schema of 'type: \"object\"', got 'type: \"array\"'"
|
|
355
355
|
|
|
356
|
-
//
|
|
356
|
+
// Generate and modify images with AI
|
|
357
|
+
|
|
358
|
+
// Basic image generation - returns public URLs directly
|
|
357
359
|
const { data } = await blink.ai.generateImage({
|
|
358
|
-
prompt: 'A serene landscape',
|
|
360
|
+
prompt: 'A serene landscape with mountains and a lake at sunset',
|
|
359
361
|
size: '1024x1024',
|
|
360
|
-
quality: 'hd'
|
|
362
|
+
quality: 'hd',
|
|
363
|
+
n: 2
|
|
364
|
+
})
|
|
365
|
+
console.log('Image URL:', data[0].url)
|
|
366
|
+
|
|
367
|
+
// Image editing - transform existing images with prompts
|
|
368
|
+
const { data: headshots } = await blink.ai.modifyImage({
|
|
369
|
+
images: ['https://storage.example.com/user-photo.jpg'], // ... up to 16 images maximum!
|
|
370
|
+
prompt: 'Generate professional business headshot with studio lighting for this person.',
|
|
371
|
+
quality: 'hd',
|
|
372
|
+
n: 4
|
|
361
373
|
})
|
|
374
|
+
// Options: size ('1024x1024', '1536x1024'), quality ('standard'|'hd'),
|
|
375
|
+
// background ('auto'|'transparent'|'opaque'), n (1-10 images)
|
|
376
|
+
|
|
362
377
|
|
|
363
378
|
// Speech synthesis
|
|
364
379
|
const { url } = await blink.ai.generateSpeech({
|
package/dist/index.d.mts
CHANGED
|
@@ -119,8 +119,17 @@ interface FileObject {
|
|
|
119
119
|
}
|
|
120
120
|
interface BlinkStorage {
|
|
121
121
|
upload(file: File | Blob | Buffer, path: string, options?: StorageUploadOptions): Promise<StorageUploadResponse>;
|
|
122
|
+
download(path: string, options?: {
|
|
123
|
+
filename?: string;
|
|
124
|
+
}): Promise<StorageDownloadResponse>;
|
|
122
125
|
remove(...paths: string[]): Promise<void>;
|
|
123
126
|
}
|
|
127
|
+
interface StorageDownloadResponse {
|
|
128
|
+
downloadUrl: string;
|
|
129
|
+
filename: string;
|
|
130
|
+
contentType?: string;
|
|
131
|
+
size?: number;
|
|
132
|
+
}
|
|
124
133
|
interface TokenUsage {
|
|
125
134
|
promptTokens: number;
|
|
126
135
|
completionTokens: number;
|
|
@@ -211,10 +220,15 @@ interface ObjectGenerationResponse {
|
|
|
211
220
|
interface ImageGenerationRequest {
|
|
212
221
|
model?: string;
|
|
213
222
|
prompt: string;
|
|
223
|
+
images?: string[];
|
|
214
224
|
size?: string;
|
|
215
225
|
quality?: 'standard' | 'hd';
|
|
226
|
+
background?: 'auto' | 'transparent' | 'opaque';
|
|
216
227
|
n?: number;
|
|
217
228
|
response_format?: 'url' | 'b64_json';
|
|
229
|
+
output_format?: 'png' | 'jpeg' | 'webp';
|
|
230
|
+
output_compression?: number;
|
|
231
|
+
moderation?: 'auto' | 'low';
|
|
218
232
|
signal?: AbortSignal;
|
|
219
233
|
}
|
|
220
234
|
interface ImageGenerationResponse {
|
|
@@ -273,6 +287,15 @@ interface BlinkAI {
|
|
|
273
287
|
generateObject(options: ObjectGenerationRequest): Promise<ObjectGenerationResponse>;
|
|
274
288
|
streamObject(options: ObjectGenerationRequest, onPartial: (partial: any) => void): Promise<ObjectGenerationResponse>;
|
|
275
289
|
generateImage(options: ImageGenerationRequest): Promise<ImageGenerationResponse>;
|
|
290
|
+
modifyImage(options: {
|
|
291
|
+
images: string[];
|
|
292
|
+
prompt: string;
|
|
293
|
+
size?: string;
|
|
294
|
+
quality?: "standard" | "hd";
|
|
295
|
+
n?: number;
|
|
296
|
+
background?: "auto" | "transparent" | "opaque";
|
|
297
|
+
signal?: AbortSignal;
|
|
298
|
+
}): Promise<ImageGenerationResponse>;
|
|
276
299
|
generateSpeech(options: SpeechGenerationRequest): Promise<SpeechGenerationResponse>;
|
|
277
300
|
transcribeAudio(options: TranscriptionRequest): Promise<TranscriptionResponse>;
|
|
278
301
|
}
|
|
@@ -660,10 +683,15 @@ declare class HttpClient {
|
|
|
660
683
|
} | undefined, onPartial: (partial: any) => void): Promise<any>;
|
|
661
684
|
aiImage(prompt: string, options?: {
|
|
662
685
|
model?: string;
|
|
686
|
+
images?: string[];
|
|
663
687
|
size?: string;
|
|
664
688
|
quality?: 'standard' | 'hd';
|
|
689
|
+
background?: 'auto' | 'transparent' | 'opaque';
|
|
665
690
|
n?: number;
|
|
666
691
|
response_format?: 'url' | 'b64_json';
|
|
692
|
+
output_format?: 'png' | 'jpeg' | 'webp';
|
|
693
|
+
output_compression?: number;
|
|
694
|
+
moderation?: 'auto' | 'low';
|
|
667
695
|
signal?: AbortSignal;
|
|
668
696
|
}): Promise<BlinkResponse<any>>;
|
|
669
697
|
aiSpeech(text: string, options?: {
|
|
@@ -834,6 +862,7 @@ declare class BlinkAuth {
|
|
|
834
862
|
declare class BlinkTable<T = any> implements TableOperations<T> {
|
|
835
863
|
private tableName;
|
|
836
864
|
private httpClient;
|
|
865
|
+
private readonly actualTableName;
|
|
837
866
|
constructor(tableName: string, httpClient: HttpClient);
|
|
838
867
|
/**
|
|
839
868
|
* Create a single record
|
|
@@ -1129,6 +1158,32 @@ declare class BlinkStorageImpl implements BlinkStorage {
|
|
|
1129
1158
|
* ```
|
|
1130
1159
|
*/
|
|
1131
1160
|
upload(file: File | Blob | Buffer, path: string, options?: StorageUploadOptions): Promise<StorageUploadResponse>;
|
|
1161
|
+
/**
|
|
1162
|
+
* Get a download URL for a file that triggers browser download
|
|
1163
|
+
*
|
|
1164
|
+
* @param path - Path to the file in project storage
|
|
1165
|
+
* @param options - Download options including custom filename
|
|
1166
|
+
* @returns Promise resolving to download response with download URL
|
|
1167
|
+
*
|
|
1168
|
+
* @example
|
|
1169
|
+
* ```ts
|
|
1170
|
+
* // Download with original filename
|
|
1171
|
+
* const { downloadUrl, filename } = await blink.storage.download('images/photo.jpg');
|
|
1172
|
+
* window.open(downloadUrl, '_blank');
|
|
1173
|
+
*
|
|
1174
|
+
* // Download with custom filename
|
|
1175
|
+
* const { downloadUrl } = await blink.storage.download(
|
|
1176
|
+
* 'images/photo.jpg',
|
|
1177
|
+
* { filename: 'my-photo.jpg' }
|
|
1178
|
+
* );
|
|
1179
|
+
*
|
|
1180
|
+
* // Create download link in React
|
|
1181
|
+
* <a href={downloadUrl} download={filename}>Download Image</a>
|
|
1182
|
+
* ```
|
|
1183
|
+
*/
|
|
1184
|
+
download(path: string, options?: {
|
|
1185
|
+
filename?: string;
|
|
1186
|
+
}): Promise<StorageDownloadResponse>;
|
|
1132
1187
|
/**
|
|
1133
1188
|
* Remove one or more files from project storage
|
|
1134
1189
|
*
|
|
@@ -1361,15 +1416,15 @@ declare class BlinkAIImpl implements BlinkAI {
|
|
|
1361
1416
|
*/
|
|
1362
1417
|
streamObject(options: ObjectGenerationRequest, onPartial: (partial: any) => void): Promise<ObjectGenerationResponse>;
|
|
1363
1418
|
/**
|
|
1364
|
-
* Generates images from text descriptions using AI
|
|
1419
|
+
* Generates images from text descriptions using AI.
|
|
1365
1420
|
*
|
|
1366
1421
|
* @param options - Object containing:
|
|
1367
|
-
* - `prompt`: Text description of the image
|
|
1368
|
-
* - `size`: Image dimensions (
|
|
1369
|
-
* - `quality`: Image quality ("standard" or "hd")
|
|
1422
|
+
* - `prompt`: Text description of the desired image (required)
|
|
1423
|
+
* - `size`: Image dimensions (default: "1024x1024")
|
|
1424
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
1370
1425
|
* - `n`: Number of images to generate (default: 1)
|
|
1371
|
-
* - `
|
|
1372
|
-
* - Plus optional
|
|
1426
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
1427
|
+
* - Plus optional signal parameter
|
|
1373
1428
|
*
|
|
1374
1429
|
* @example
|
|
1375
1430
|
* ```ts
|
|
@@ -1382,31 +1437,103 @@ declare class BlinkAIImpl implements BlinkAI {
|
|
|
1382
1437
|
* // High-quality image with specific size
|
|
1383
1438
|
* const { data } = await blink.ai.generateImage({
|
|
1384
1439
|
* prompt: "A futuristic city skyline with flying cars",
|
|
1385
|
-
* size: "
|
|
1440
|
+
* size: "1536x1024",
|
|
1386
1441
|
* quality: "hd",
|
|
1387
|
-
*
|
|
1442
|
+
* background: "transparent"
|
|
1388
1443
|
* });
|
|
1389
1444
|
*
|
|
1390
1445
|
* // Multiple images
|
|
1391
1446
|
* const { data } = await blink.ai.generateImage({
|
|
1392
1447
|
* prompt: "A cute robot mascot for a tech company",
|
|
1393
1448
|
* n: 3,
|
|
1394
|
-
* size: "1024x1024"
|
|
1449
|
+
* size: "1024x1024",
|
|
1450
|
+
* quality: "hd"
|
|
1395
1451
|
* });
|
|
1396
1452
|
* data.forEach((img, i) => console.log(`Image ${i+1}:`, img.url));
|
|
1453
|
+
* ```
|
|
1397
1454
|
*
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1455
|
+
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
1456
|
+
* - `data`: Array of generated images with URLs
|
|
1457
|
+
* - `created`: Timestamp of generation
|
|
1458
|
+
* - `usage`: Token usage information
|
|
1459
|
+
*/
|
|
1460
|
+
generateImage(options: {
|
|
1461
|
+
prompt: string;
|
|
1462
|
+
size?: string;
|
|
1463
|
+
quality?: "standard" | "hd";
|
|
1464
|
+
n?: number;
|
|
1465
|
+
background?: "auto" | "transparent" | "opaque";
|
|
1466
|
+
signal?: AbortSignal;
|
|
1467
|
+
}): Promise<ImageGenerationResponse>;
|
|
1468
|
+
/**
|
|
1469
|
+
* Modifies existing images using AI with text prompts for image-to-image editing.
|
|
1470
|
+
*
|
|
1471
|
+
* @param options - Object containing:
|
|
1472
|
+
* - `images`: Array of public image URLs to modify (required, up to 16 images)
|
|
1473
|
+
* - `prompt`: Text description of desired modifications (required)
|
|
1474
|
+
* - `size`: Output image dimensions (default: "auto")
|
|
1475
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
1476
|
+
* - `n`: Number of output images to generate (default: 1)
|
|
1477
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
1478
|
+
* - Plus optional signal parameter
|
|
1479
|
+
*
|
|
1480
|
+
* @example
|
|
1481
|
+
* ```ts
|
|
1482
|
+
* // Professional headshots from casual photos
|
|
1483
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1484
|
+
* images: [
|
|
1485
|
+
* "https://storage.example.com/user-photo-1.jpg",
|
|
1486
|
+
* "https://storage.example.com/user-photo-2.jpg"
|
|
1487
|
+
* ],
|
|
1488
|
+
* prompt: "Transform into professional business headshots with studio lighting",
|
|
1489
|
+
* quality: "hd",
|
|
1490
|
+
* n: 4
|
|
1491
|
+
* });
|
|
1492
|
+
* data.forEach((img, i) => console.log(`Headshot ${i+1}:`, img.url));
|
|
1493
|
+
*
|
|
1494
|
+
* // Artistic style transformation
|
|
1495
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1496
|
+
* images: ["https://storage.example.com/portrait.jpg"],
|
|
1497
|
+
* prompt: "Transform into oil painting style with dramatic lighting",
|
|
1498
|
+
* quality: "hd",
|
|
1499
|
+
* size: "1024x1024"
|
|
1500
|
+
* });
|
|
1501
|
+
*
|
|
1502
|
+
* // Background replacement
|
|
1503
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1504
|
+
* images: ["https://storage.example.com/product.jpg"],
|
|
1505
|
+
* prompt: "Remove background and place on clean white studio background",
|
|
1506
|
+
* background: "transparent",
|
|
1507
|
+
* n: 2
|
|
1508
|
+
* });
|
|
1509
|
+
*
|
|
1510
|
+
* // Batch processing multiple photos
|
|
1511
|
+
* const userPhotos = [
|
|
1512
|
+
* "https://storage.example.com/photo1.jpg",
|
|
1513
|
+
* "https://storage.example.com/photo2.jpg",
|
|
1514
|
+
* "https://storage.example.com/photo3.jpg"
|
|
1515
|
+
* ];
|
|
1516
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1517
|
+
* images: userPhotos,
|
|
1518
|
+
* prompt: "Convert to black and white vintage style photographs",
|
|
1519
|
+
* quality: "hd"
|
|
1402
1520
|
* });
|
|
1403
|
-
* console.log("Base64 data:", data[0].b64_json);
|
|
1404
1521
|
* ```
|
|
1405
1522
|
*
|
|
1406
1523
|
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
1407
|
-
* - `data`: Array of
|
|
1524
|
+
* - `data`: Array of modified images with URLs
|
|
1525
|
+
* - `created`: Timestamp of generation
|
|
1526
|
+
* - `usage`: Token usage information
|
|
1408
1527
|
*/
|
|
1409
|
-
|
|
1528
|
+
modifyImage(options: {
|
|
1529
|
+
images: string[];
|
|
1530
|
+
prompt: string;
|
|
1531
|
+
size?: string;
|
|
1532
|
+
quality?: "standard" | "hd";
|
|
1533
|
+
n?: number;
|
|
1534
|
+
background?: "auto" | "transparent" | "opaque";
|
|
1535
|
+
signal?: AbortSignal;
|
|
1536
|
+
}): Promise<ImageGenerationResponse>;
|
|
1410
1537
|
/**
|
|
1411
1538
|
* Converts text to speech using AI voice synthesis models.
|
|
1412
1539
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -119,8 +119,17 @@ interface FileObject {
|
|
|
119
119
|
}
|
|
120
120
|
interface BlinkStorage {
|
|
121
121
|
upload(file: File | Blob | Buffer, path: string, options?: StorageUploadOptions): Promise<StorageUploadResponse>;
|
|
122
|
+
download(path: string, options?: {
|
|
123
|
+
filename?: string;
|
|
124
|
+
}): Promise<StorageDownloadResponse>;
|
|
122
125
|
remove(...paths: string[]): Promise<void>;
|
|
123
126
|
}
|
|
127
|
+
interface StorageDownloadResponse {
|
|
128
|
+
downloadUrl: string;
|
|
129
|
+
filename: string;
|
|
130
|
+
contentType?: string;
|
|
131
|
+
size?: number;
|
|
132
|
+
}
|
|
124
133
|
interface TokenUsage {
|
|
125
134
|
promptTokens: number;
|
|
126
135
|
completionTokens: number;
|
|
@@ -211,10 +220,15 @@ interface ObjectGenerationResponse {
|
|
|
211
220
|
interface ImageGenerationRequest {
|
|
212
221
|
model?: string;
|
|
213
222
|
prompt: string;
|
|
223
|
+
images?: string[];
|
|
214
224
|
size?: string;
|
|
215
225
|
quality?: 'standard' | 'hd';
|
|
226
|
+
background?: 'auto' | 'transparent' | 'opaque';
|
|
216
227
|
n?: number;
|
|
217
228
|
response_format?: 'url' | 'b64_json';
|
|
229
|
+
output_format?: 'png' | 'jpeg' | 'webp';
|
|
230
|
+
output_compression?: number;
|
|
231
|
+
moderation?: 'auto' | 'low';
|
|
218
232
|
signal?: AbortSignal;
|
|
219
233
|
}
|
|
220
234
|
interface ImageGenerationResponse {
|
|
@@ -273,6 +287,15 @@ interface BlinkAI {
|
|
|
273
287
|
generateObject(options: ObjectGenerationRequest): Promise<ObjectGenerationResponse>;
|
|
274
288
|
streamObject(options: ObjectGenerationRequest, onPartial: (partial: any) => void): Promise<ObjectGenerationResponse>;
|
|
275
289
|
generateImage(options: ImageGenerationRequest): Promise<ImageGenerationResponse>;
|
|
290
|
+
modifyImage(options: {
|
|
291
|
+
images: string[];
|
|
292
|
+
prompt: string;
|
|
293
|
+
size?: string;
|
|
294
|
+
quality?: "standard" | "hd";
|
|
295
|
+
n?: number;
|
|
296
|
+
background?: "auto" | "transparent" | "opaque";
|
|
297
|
+
signal?: AbortSignal;
|
|
298
|
+
}): Promise<ImageGenerationResponse>;
|
|
276
299
|
generateSpeech(options: SpeechGenerationRequest): Promise<SpeechGenerationResponse>;
|
|
277
300
|
transcribeAudio(options: TranscriptionRequest): Promise<TranscriptionResponse>;
|
|
278
301
|
}
|
|
@@ -660,10 +683,15 @@ declare class HttpClient {
|
|
|
660
683
|
} | undefined, onPartial: (partial: any) => void): Promise<any>;
|
|
661
684
|
aiImage(prompt: string, options?: {
|
|
662
685
|
model?: string;
|
|
686
|
+
images?: string[];
|
|
663
687
|
size?: string;
|
|
664
688
|
quality?: 'standard' | 'hd';
|
|
689
|
+
background?: 'auto' | 'transparent' | 'opaque';
|
|
665
690
|
n?: number;
|
|
666
691
|
response_format?: 'url' | 'b64_json';
|
|
692
|
+
output_format?: 'png' | 'jpeg' | 'webp';
|
|
693
|
+
output_compression?: number;
|
|
694
|
+
moderation?: 'auto' | 'low';
|
|
667
695
|
signal?: AbortSignal;
|
|
668
696
|
}): Promise<BlinkResponse<any>>;
|
|
669
697
|
aiSpeech(text: string, options?: {
|
|
@@ -834,6 +862,7 @@ declare class BlinkAuth {
|
|
|
834
862
|
declare class BlinkTable<T = any> implements TableOperations<T> {
|
|
835
863
|
private tableName;
|
|
836
864
|
private httpClient;
|
|
865
|
+
private readonly actualTableName;
|
|
837
866
|
constructor(tableName: string, httpClient: HttpClient);
|
|
838
867
|
/**
|
|
839
868
|
* Create a single record
|
|
@@ -1129,6 +1158,32 @@ declare class BlinkStorageImpl implements BlinkStorage {
|
|
|
1129
1158
|
* ```
|
|
1130
1159
|
*/
|
|
1131
1160
|
upload(file: File | Blob | Buffer, path: string, options?: StorageUploadOptions): Promise<StorageUploadResponse>;
|
|
1161
|
+
/**
|
|
1162
|
+
* Get a download URL for a file that triggers browser download
|
|
1163
|
+
*
|
|
1164
|
+
* @param path - Path to the file in project storage
|
|
1165
|
+
* @param options - Download options including custom filename
|
|
1166
|
+
* @returns Promise resolving to download response with download URL
|
|
1167
|
+
*
|
|
1168
|
+
* @example
|
|
1169
|
+
* ```ts
|
|
1170
|
+
* // Download with original filename
|
|
1171
|
+
* const { downloadUrl, filename } = await blink.storage.download('images/photo.jpg');
|
|
1172
|
+
* window.open(downloadUrl, '_blank');
|
|
1173
|
+
*
|
|
1174
|
+
* // Download with custom filename
|
|
1175
|
+
* const { downloadUrl } = await blink.storage.download(
|
|
1176
|
+
* 'images/photo.jpg',
|
|
1177
|
+
* { filename: 'my-photo.jpg' }
|
|
1178
|
+
* );
|
|
1179
|
+
*
|
|
1180
|
+
* // Create download link in React
|
|
1181
|
+
* <a href={downloadUrl} download={filename}>Download Image</a>
|
|
1182
|
+
* ```
|
|
1183
|
+
*/
|
|
1184
|
+
download(path: string, options?: {
|
|
1185
|
+
filename?: string;
|
|
1186
|
+
}): Promise<StorageDownloadResponse>;
|
|
1132
1187
|
/**
|
|
1133
1188
|
* Remove one or more files from project storage
|
|
1134
1189
|
*
|
|
@@ -1361,15 +1416,15 @@ declare class BlinkAIImpl implements BlinkAI {
|
|
|
1361
1416
|
*/
|
|
1362
1417
|
streamObject(options: ObjectGenerationRequest, onPartial: (partial: any) => void): Promise<ObjectGenerationResponse>;
|
|
1363
1418
|
/**
|
|
1364
|
-
* Generates images from text descriptions using AI
|
|
1419
|
+
* Generates images from text descriptions using AI.
|
|
1365
1420
|
*
|
|
1366
1421
|
* @param options - Object containing:
|
|
1367
|
-
* - `prompt`: Text description of the image
|
|
1368
|
-
* - `size`: Image dimensions (
|
|
1369
|
-
* - `quality`: Image quality ("standard" or "hd")
|
|
1422
|
+
* - `prompt`: Text description of the desired image (required)
|
|
1423
|
+
* - `size`: Image dimensions (default: "1024x1024")
|
|
1424
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
1370
1425
|
* - `n`: Number of images to generate (default: 1)
|
|
1371
|
-
* - `
|
|
1372
|
-
* - Plus optional
|
|
1426
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
1427
|
+
* - Plus optional signal parameter
|
|
1373
1428
|
*
|
|
1374
1429
|
* @example
|
|
1375
1430
|
* ```ts
|
|
@@ -1382,31 +1437,103 @@ declare class BlinkAIImpl implements BlinkAI {
|
|
|
1382
1437
|
* // High-quality image with specific size
|
|
1383
1438
|
* const { data } = await blink.ai.generateImage({
|
|
1384
1439
|
* prompt: "A futuristic city skyline with flying cars",
|
|
1385
|
-
* size: "
|
|
1440
|
+
* size: "1536x1024",
|
|
1386
1441
|
* quality: "hd",
|
|
1387
|
-
*
|
|
1442
|
+
* background: "transparent"
|
|
1388
1443
|
* });
|
|
1389
1444
|
*
|
|
1390
1445
|
* // Multiple images
|
|
1391
1446
|
* const { data } = await blink.ai.generateImage({
|
|
1392
1447
|
* prompt: "A cute robot mascot for a tech company",
|
|
1393
1448
|
* n: 3,
|
|
1394
|
-
* size: "1024x1024"
|
|
1449
|
+
* size: "1024x1024",
|
|
1450
|
+
* quality: "hd"
|
|
1395
1451
|
* });
|
|
1396
1452
|
* data.forEach((img, i) => console.log(`Image ${i+1}:`, img.url));
|
|
1453
|
+
* ```
|
|
1397
1454
|
*
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1455
|
+
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
1456
|
+
* - `data`: Array of generated images with URLs
|
|
1457
|
+
* - `created`: Timestamp of generation
|
|
1458
|
+
* - `usage`: Token usage information
|
|
1459
|
+
*/
|
|
1460
|
+
generateImage(options: {
|
|
1461
|
+
prompt: string;
|
|
1462
|
+
size?: string;
|
|
1463
|
+
quality?: "standard" | "hd";
|
|
1464
|
+
n?: number;
|
|
1465
|
+
background?: "auto" | "transparent" | "opaque";
|
|
1466
|
+
signal?: AbortSignal;
|
|
1467
|
+
}): Promise<ImageGenerationResponse>;
|
|
1468
|
+
/**
|
|
1469
|
+
* Modifies existing images using AI with text prompts for image-to-image editing.
|
|
1470
|
+
*
|
|
1471
|
+
* @param options - Object containing:
|
|
1472
|
+
* - `images`: Array of public image URLs to modify (required, up to 16 images)
|
|
1473
|
+
* - `prompt`: Text description of desired modifications (required)
|
|
1474
|
+
* - `size`: Output image dimensions (default: "auto")
|
|
1475
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
1476
|
+
* - `n`: Number of output images to generate (default: 1)
|
|
1477
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
1478
|
+
* - Plus optional signal parameter
|
|
1479
|
+
*
|
|
1480
|
+
* @example
|
|
1481
|
+
* ```ts
|
|
1482
|
+
* // Professional headshots from casual photos
|
|
1483
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1484
|
+
* images: [
|
|
1485
|
+
* "https://storage.example.com/user-photo-1.jpg",
|
|
1486
|
+
* "https://storage.example.com/user-photo-2.jpg"
|
|
1487
|
+
* ],
|
|
1488
|
+
* prompt: "Transform into professional business headshots with studio lighting",
|
|
1489
|
+
* quality: "hd",
|
|
1490
|
+
* n: 4
|
|
1491
|
+
* });
|
|
1492
|
+
* data.forEach((img, i) => console.log(`Headshot ${i+1}:`, img.url));
|
|
1493
|
+
*
|
|
1494
|
+
* // Artistic style transformation
|
|
1495
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1496
|
+
* images: ["https://storage.example.com/portrait.jpg"],
|
|
1497
|
+
* prompt: "Transform into oil painting style with dramatic lighting",
|
|
1498
|
+
* quality: "hd",
|
|
1499
|
+
* size: "1024x1024"
|
|
1500
|
+
* });
|
|
1501
|
+
*
|
|
1502
|
+
* // Background replacement
|
|
1503
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1504
|
+
* images: ["https://storage.example.com/product.jpg"],
|
|
1505
|
+
* prompt: "Remove background and place on clean white studio background",
|
|
1506
|
+
* background: "transparent",
|
|
1507
|
+
* n: 2
|
|
1508
|
+
* });
|
|
1509
|
+
*
|
|
1510
|
+
* // Batch processing multiple photos
|
|
1511
|
+
* const userPhotos = [
|
|
1512
|
+
* "https://storage.example.com/photo1.jpg",
|
|
1513
|
+
* "https://storage.example.com/photo2.jpg",
|
|
1514
|
+
* "https://storage.example.com/photo3.jpg"
|
|
1515
|
+
* ];
|
|
1516
|
+
* const { data } = await blink.ai.modifyImage({
|
|
1517
|
+
* images: userPhotos,
|
|
1518
|
+
* prompt: "Convert to black and white vintage style photographs",
|
|
1519
|
+
* quality: "hd"
|
|
1402
1520
|
* });
|
|
1403
|
-
* console.log("Base64 data:", data[0].b64_json);
|
|
1404
1521
|
* ```
|
|
1405
1522
|
*
|
|
1406
1523
|
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
1407
|
-
* - `data`: Array of
|
|
1524
|
+
* - `data`: Array of modified images with URLs
|
|
1525
|
+
* - `created`: Timestamp of generation
|
|
1526
|
+
* - `usage`: Token usage information
|
|
1408
1527
|
*/
|
|
1409
|
-
|
|
1528
|
+
modifyImage(options: {
|
|
1529
|
+
images: string[];
|
|
1530
|
+
prompt: string;
|
|
1531
|
+
size?: string;
|
|
1532
|
+
quality?: "standard" | "hd";
|
|
1533
|
+
n?: number;
|
|
1534
|
+
background?: "auto" | "transparent" | "opaque";
|
|
1535
|
+
signal?: AbortSignal;
|
|
1536
|
+
}): Promise<ImageGenerationResponse>;
|
|
1410
1537
|
/**
|
|
1411
1538
|
* Converts text to speech using AI voice synthesis models.
|
|
1412
1539
|
*
|
package/dist/index.js
CHANGED
|
@@ -1530,6 +1530,9 @@ var BlinkAuth = class {
|
|
|
1530
1530
|
};
|
|
1531
1531
|
|
|
1532
1532
|
// src/database.ts
|
|
1533
|
+
function camelToSnake3(str) {
|
|
1534
|
+
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
1535
|
+
}
|
|
1533
1536
|
function generateSecureId() {
|
|
1534
1537
|
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
1535
1538
|
const array = new Uint8Array(16);
|
|
@@ -1552,14 +1555,16 @@ var BlinkTable = class {
|
|
|
1552
1555
|
constructor(tableName, httpClient) {
|
|
1553
1556
|
this.tableName = tableName;
|
|
1554
1557
|
this.httpClient = httpClient;
|
|
1558
|
+
this.actualTableName = camelToSnake3(tableName);
|
|
1555
1559
|
}
|
|
1560
|
+
actualTableName;
|
|
1556
1561
|
/**
|
|
1557
1562
|
* Create a single record
|
|
1558
1563
|
*/
|
|
1559
1564
|
async create(data, options = {}) {
|
|
1560
1565
|
const record = ensureRecordId(data);
|
|
1561
1566
|
const response = await this.httpClient.dbPost(
|
|
1562
|
-
this.
|
|
1567
|
+
this.actualTableName,
|
|
1563
1568
|
record,
|
|
1564
1569
|
{ returning: options.returning !== false }
|
|
1565
1570
|
);
|
|
@@ -1575,7 +1580,7 @@ var BlinkTable = class {
|
|
|
1575
1580
|
async createMany(data, options = {}) {
|
|
1576
1581
|
const records = data.map(ensureRecordId);
|
|
1577
1582
|
const response = await this.httpClient.dbPost(
|
|
1578
|
-
this.
|
|
1583
|
+
this.actualTableName,
|
|
1579
1584
|
records,
|
|
1580
1585
|
{ returning: options.returning !== false }
|
|
1581
1586
|
);
|
|
@@ -1595,7 +1600,7 @@ var BlinkTable = class {
|
|
|
1595
1600
|
}
|
|
1596
1601
|
const record = ensureRecordId(data);
|
|
1597
1602
|
const response = await this.httpClient.request(
|
|
1598
|
-
`/api/db/${this.httpClient.projectId}/rest/v1/${this.
|
|
1603
|
+
`/api/db/${this.httpClient.projectId}/rest/v1/${this.actualTableName}?on_conflict=${options.onConflict || "id"}`,
|
|
1599
1604
|
{
|
|
1600
1605
|
method: "POST",
|
|
1601
1606
|
body: record,
|
|
@@ -1621,7 +1626,7 @@ var BlinkTable = class {
|
|
|
1621
1626
|
headers["Prefer"] = `${headers["Prefer"] || ""} resolution=merge-duplicates`.trim();
|
|
1622
1627
|
}
|
|
1623
1628
|
const response = await this.httpClient.request(
|
|
1624
|
-
`/api/db/${this.httpClient.projectId}/rest/v1/${this.
|
|
1629
|
+
`/api/db/${this.httpClient.projectId}/rest/v1/${this.actualTableName}?on_conflict=${options.onConflict || "id"}`,
|
|
1625
1630
|
{
|
|
1626
1631
|
method: "POST",
|
|
1627
1632
|
body: records,
|
|
@@ -1639,7 +1644,7 @@ var BlinkTable = class {
|
|
|
1639
1644
|
id: `eq.${id}`,
|
|
1640
1645
|
limit: "1"
|
|
1641
1646
|
};
|
|
1642
|
-
const response = await this.httpClient.dbGet(this.
|
|
1647
|
+
const response = await this.httpClient.dbGet(this.actualTableName, searchParams);
|
|
1643
1648
|
const records = response.data;
|
|
1644
1649
|
if (records.length === 0) {
|
|
1645
1650
|
return null;
|
|
@@ -1652,7 +1657,7 @@ var BlinkTable = class {
|
|
|
1652
1657
|
async list(options = {}) {
|
|
1653
1658
|
const queryParams = buildQuery(options);
|
|
1654
1659
|
const searchParams = queryParams;
|
|
1655
|
-
const response = await this.httpClient.dbGet(this.
|
|
1660
|
+
const response = await this.httpClient.dbGet(this.actualTableName, searchParams);
|
|
1656
1661
|
const records = response.data;
|
|
1657
1662
|
return records;
|
|
1658
1663
|
}
|
|
@@ -1664,7 +1669,7 @@ var BlinkTable = class {
|
|
|
1664
1669
|
id: `eq.${id}`
|
|
1665
1670
|
};
|
|
1666
1671
|
const response = await this.httpClient.dbPatch(
|
|
1667
|
-
this.
|
|
1672
|
+
this.actualTableName,
|
|
1668
1673
|
data,
|
|
1669
1674
|
searchParams,
|
|
1670
1675
|
{ returning: options.returning !== false }
|
|
@@ -1694,7 +1699,7 @@ var BlinkTable = class {
|
|
|
1694
1699
|
const searchParams = {
|
|
1695
1700
|
id: `eq.${id}`
|
|
1696
1701
|
};
|
|
1697
|
-
await this.httpClient.dbDelete(this.
|
|
1702
|
+
await this.httpClient.dbDelete(this.actualTableName, searchParams);
|
|
1698
1703
|
}
|
|
1699
1704
|
/**
|
|
1700
1705
|
* Delete multiple records based on filter
|
|
@@ -1702,7 +1707,7 @@ var BlinkTable = class {
|
|
|
1702
1707
|
async deleteMany(options) {
|
|
1703
1708
|
const queryParams = buildQuery({ where: options.where });
|
|
1704
1709
|
const searchParams = queryParams;
|
|
1705
|
-
await this.httpClient.dbDelete(this.
|
|
1710
|
+
await this.httpClient.dbDelete(this.actualTableName, searchParams);
|
|
1706
1711
|
}
|
|
1707
1712
|
/**
|
|
1708
1713
|
* Count records matching filter
|
|
@@ -1713,7 +1718,7 @@ var BlinkTable = class {
|
|
|
1713
1718
|
select: ["id"]
|
|
1714
1719
|
});
|
|
1715
1720
|
const response = await this.httpClient.request(
|
|
1716
|
-
`/api/db/${this.httpClient.projectId}/rest/v1/${this.
|
|
1721
|
+
`/api/db/${this.httpClient.projectId}/rest/v1/${this.actualTableName}`,
|
|
1717
1722
|
{
|
|
1718
1723
|
method: "GET",
|
|
1719
1724
|
searchParams: queryParams,
|
|
@@ -1882,6 +1887,74 @@ var BlinkStorageImpl = class {
|
|
|
1882
1887
|
);
|
|
1883
1888
|
}
|
|
1884
1889
|
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Get a download URL for a file that triggers browser download
|
|
1892
|
+
*
|
|
1893
|
+
* @param path - Path to the file in project storage
|
|
1894
|
+
* @param options - Download options including custom filename
|
|
1895
|
+
* @returns Promise resolving to download response with download URL
|
|
1896
|
+
*
|
|
1897
|
+
* @example
|
|
1898
|
+
* ```ts
|
|
1899
|
+
* // Download with original filename
|
|
1900
|
+
* const { downloadUrl, filename } = await blink.storage.download('images/photo.jpg');
|
|
1901
|
+
* window.open(downloadUrl, '_blank');
|
|
1902
|
+
*
|
|
1903
|
+
* // Download with custom filename
|
|
1904
|
+
* const { downloadUrl } = await blink.storage.download(
|
|
1905
|
+
* 'images/photo.jpg',
|
|
1906
|
+
* { filename: 'my-photo.jpg' }
|
|
1907
|
+
* );
|
|
1908
|
+
*
|
|
1909
|
+
* // Create download link in React
|
|
1910
|
+
* <a href={downloadUrl} download={filename}>Download Image</a>
|
|
1911
|
+
* ```
|
|
1912
|
+
*/
|
|
1913
|
+
async download(path, options = {}) {
|
|
1914
|
+
try {
|
|
1915
|
+
if (!path || typeof path !== "string" || !path.trim()) {
|
|
1916
|
+
throw new BlinkStorageError("Path must be a non-empty string");
|
|
1917
|
+
}
|
|
1918
|
+
const response = await this.httpClient.request(
|
|
1919
|
+
`/api/storage/${this.httpClient.projectId}/download`,
|
|
1920
|
+
{
|
|
1921
|
+
method: "GET",
|
|
1922
|
+
searchParams: {
|
|
1923
|
+
path: path.trim(),
|
|
1924
|
+
...options.filename && { filename: options.filename }
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
);
|
|
1928
|
+
if (response.data?.downloadUrl) {
|
|
1929
|
+
return {
|
|
1930
|
+
downloadUrl: response.data.downloadUrl,
|
|
1931
|
+
filename: response.data.filename || options.filename || path.split("/").pop() || "download",
|
|
1932
|
+
contentType: response.data.contentType,
|
|
1933
|
+
size: response.data.size
|
|
1934
|
+
};
|
|
1935
|
+
} else {
|
|
1936
|
+
throw new BlinkStorageError("Invalid response format: missing downloadUrl");
|
|
1937
|
+
}
|
|
1938
|
+
} catch (error) {
|
|
1939
|
+
if (error instanceof BlinkStorageError) {
|
|
1940
|
+
throw error;
|
|
1941
|
+
}
|
|
1942
|
+
if (error instanceof Error && "status" in error) {
|
|
1943
|
+
const status = error.status;
|
|
1944
|
+
if (status === 404) {
|
|
1945
|
+
throw new BlinkStorageError("File not found", 404);
|
|
1946
|
+
}
|
|
1947
|
+
if (status === 400) {
|
|
1948
|
+
throw new BlinkStorageError("Invalid request parameters", 400);
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
throw new BlinkStorageError(
|
|
1952
|
+
`Download failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1953
|
+
void 0,
|
|
1954
|
+
{ originalError: error }
|
|
1955
|
+
);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1885
1958
|
/**
|
|
1886
1959
|
* Remove one or more files from project storage
|
|
1887
1960
|
*
|
|
@@ -2349,15 +2422,15 @@ var BlinkAIImpl = class {
|
|
|
2349
2422
|
}
|
|
2350
2423
|
}
|
|
2351
2424
|
/**
|
|
2352
|
-
* Generates images from text descriptions using AI
|
|
2425
|
+
* Generates images from text descriptions using AI.
|
|
2353
2426
|
*
|
|
2354
2427
|
* @param options - Object containing:
|
|
2355
|
-
* - `prompt`: Text description of the image
|
|
2356
|
-
* - `size`: Image dimensions (
|
|
2357
|
-
* - `quality`: Image quality ("standard" or "hd")
|
|
2428
|
+
* - `prompt`: Text description of the desired image (required)
|
|
2429
|
+
* - `size`: Image dimensions (default: "1024x1024")
|
|
2430
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
2358
2431
|
* - `n`: Number of images to generate (default: 1)
|
|
2359
|
-
* - `
|
|
2360
|
-
* - Plus optional
|
|
2432
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
2433
|
+
* - Plus optional signal parameter
|
|
2361
2434
|
*
|
|
2362
2435
|
* @example
|
|
2363
2436
|
* ```ts
|
|
@@ -2370,29 +2443,25 @@ var BlinkAIImpl = class {
|
|
|
2370
2443
|
* // High-quality image with specific size
|
|
2371
2444
|
* const { data } = await blink.ai.generateImage({
|
|
2372
2445
|
* prompt: "A futuristic city skyline with flying cars",
|
|
2373
|
-
* size: "
|
|
2446
|
+
* size: "1536x1024",
|
|
2374
2447
|
* quality: "hd",
|
|
2375
|
-
*
|
|
2448
|
+
* background: "transparent"
|
|
2376
2449
|
* });
|
|
2377
2450
|
*
|
|
2378
2451
|
* // Multiple images
|
|
2379
2452
|
* const { data } = await blink.ai.generateImage({
|
|
2380
2453
|
* prompt: "A cute robot mascot for a tech company",
|
|
2381
2454
|
* n: 3,
|
|
2382
|
-
* size: "1024x1024"
|
|
2455
|
+
* size: "1024x1024",
|
|
2456
|
+
* quality: "hd"
|
|
2383
2457
|
* });
|
|
2384
2458
|
* data.forEach((img, i) => console.log(`Image ${i+1}:`, img.url));
|
|
2385
|
-
*
|
|
2386
|
-
* // Base64 format for direct embedding
|
|
2387
|
-
* const { data } = await blink.ai.generateImage({
|
|
2388
|
-
* prompt: "A minimalist logo design",
|
|
2389
|
-
* response_format: "b64_json"
|
|
2390
|
-
* });
|
|
2391
|
-
* console.log("Base64 data:", data[0].b64_json);
|
|
2392
2459
|
* ```
|
|
2393
2460
|
*
|
|
2394
2461
|
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
2395
|
-
* - `data`: Array of generated images with
|
|
2462
|
+
* - `data`: Array of generated images with URLs
|
|
2463
|
+
* - `created`: Timestamp of generation
|
|
2464
|
+
* - `usage`: Token usage information
|
|
2396
2465
|
*/
|
|
2397
2466
|
async generateImage(options) {
|
|
2398
2467
|
try {
|
|
@@ -2402,11 +2471,12 @@ var BlinkAIImpl = class {
|
|
|
2402
2471
|
const response = await this.httpClient.aiImage(
|
|
2403
2472
|
options.prompt,
|
|
2404
2473
|
{
|
|
2405
|
-
model:
|
|
2474
|
+
model: "gpt-image-1",
|
|
2406
2475
|
size: options.size,
|
|
2407
2476
|
quality: options.quality,
|
|
2408
2477
|
n: options.n,
|
|
2409
|
-
|
|
2478
|
+
background: options.background,
|
|
2479
|
+
response_format: "url",
|
|
2410
2480
|
signal: options.signal
|
|
2411
2481
|
}
|
|
2412
2482
|
);
|
|
@@ -2426,10 +2496,8 @@ var BlinkAIImpl = class {
|
|
|
2426
2496
|
return { url: item };
|
|
2427
2497
|
} else if (item.url) {
|
|
2428
2498
|
return item;
|
|
2429
|
-
} else if (item.b64_json) {
|
|
2430
|
-
return { b64_json: item.b64_json };
|
|
2431
2499
|
} else {
|
|
2432
|
-
|
|
2500
|
+
throw new BlinkAIError("Invalid image response format");
|
|
2433
2501
|
}
|
|
2434
2502
|
});
|
|
2435
2503
|
return imageResponse;
|
|
@@ -2444,6 +2512,129 @@ var BlinkAIImpl = class {
|
|
|
2444
2512
|
);
|
|
2445
2513
|
}
|
|
2446
2514
|
}
|
|
2515
|
+
/**
|
|
2516
|
+
* Modifies existing images using AI with text prompts for image-to-image editing.
|
|
2517
|
+
*
|
|
2518
|
+
* @param options - Object containing:
|
|
2519
|
+
* - `images`: Array of public image URLs to modify (required, up to 16 images)
|
|
2520
|
+
* - `prompt`: Text description of desired modifications (required)
|
|
2521
|
+
* - `size`: Output image dimensions (default: "auto")
|
|
2522
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
2523
|
+
* - `n`: Number of output images to generate (default: 1)
|
|
2524
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
2525
|
+
* - Plus optional signal parameter
|
|
2526
|
+
*
|
|
2527
|
+
* @example
|
|
2528
|
+
* ```ts
|
|
2529
|
+
* // Professional headshots from casual photos
|
|
2530
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2531
|
+
* images: [
|
|
2532
|
+
* "https://storage.example.com/user-photo-1.jpg",
|
|
2533
|
+
* "https://storage.example.com/user-photo-2.jpg"
|
|
2534
|
+
* ],
|
|
2535
|
+
* prompt: "Transform into professional business headshots with studio lighting",
|
|
2536
|
+
* quality: "hd",
|
|
2537
|
+
* n: 4
|
|
2538
|
+
* });
|
|
2539
|
+
* data.forEach((img, i) => console.log(`Headshot ${i+1}:`, img.url));
|
|
2540
|
+
*
|
|
2541
|
+
* // Artistic style transformation
|
|
2542
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2543
|
+
* images: ["https://storage.example.com/portrait.jpg"],
|
|
2544
|
+
* prompt: "Transform into oil painting style with dramatic lighting",
|
|
2545
|
+
* quality: "hd",
|
|
2546
|
+
* size: "1024x1024"
|
|
2547
|
+
* });
|
|
2548
|
+
*
|
|
2549
|
+
* // Background replacement
|
|
2550
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2551
|
+
* images: ["https://storage.example.com/product.jpg"],
|
|
2552
|
+
* prompt: "Remove background and place on clean white studio background",
|
|
2553
|
+
* background: "transparent",
|
|
2554
|
+
* n: 2
|
|
2555
|
+
* });
|
|
2556
|
+
*
|
|
2557
|
+
* // Batch processing multiple photos
|
|
2558
|
+
* const userPhotos = [
|
|
2559
|
+
* "https://storage.example.com/photo1.jpg",
|
|
2560
|
+
* "https://storage.example.com/photo2.jpg",
|
|
2561
|
+
* "https://storage.example.com/photo3.jpg"
|
|
2562
|
+
* ];
|
|
2563
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2564
|
+
* images: userPhotos,
|
|
2565
|
+
* prompt: "Convert to black and white vintage style photographs",
|
|
2566
|
+
* quality: "hd"
|
|
2567
|
+
* });
|
|
2568
|
+
* ```
|
|
2569
|
+
*
|
|
2570
|
+
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
2571
|
+
* - `data`: Array of modified images with URLs
|
|
2572
|
+
* - `created`: Timestamp of generation
|
|
2573
|
+
* - `usage`: Token usage information
|
|
2574
|
+
*/
|
|
2575
|
+
async modifyImage(options) {
|
|
2576
|
+
try {
|
|
2577
|
+
if (!options.prompt) {
|
|
2578
|
+
throw new BlinkAIError("Prompt is required");
|
|
2579
|
+
}
|
|
2580
|
+
if (!options.images || !Array.isArray(options.images) || options.images.length === 0) {
|
|
2581
|
+
throw new BlinkAIError("Images array is required and must contain at least one image URL");
|
|
2582
|
+
}
|
|
2583
|
+
if (options.images.length > 16) {
|
|
2584
|
+
throw new BlinkAIError("Maximum 16 images allowed");
|
|
2585
|
+
}
|
|
2586
|
+
for (let i = 0; i < options.images.length; i++) {
|
|
2587
|
+
const validation = this.validateImageUrl(options.images[i]);
|
|
2588
|
+
if (!validation.isValid) {
|
|
2589
|
+
throw new BlinkAIError(`Image ${i + 1}: ${validation.error}`);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
const response = await this.httpClient.aiImage(
|
|
2593
|
+
options.prompt,
|
|
2594
|
+
// Non-null assertion since we validated above
|
|
2595
|
+
{
|
|
2596
|
+
model: "gpt-image-1",
|
|
2597
|
+
images: options.images,
|
|
2598
|
+
size: options.size,
|
|
2599
|
+
quality: options.quality,
|
|
2600
|
+
n: options.n,
|
|
2601
|
+
background: options.background,
|
|
2602
|
+
response_format: "url",
|
|
2603
|
+
signal: options.signal
|
|
2604
|
+
}
|
|
2605
|
+
);
|
|
2606
|
+
let imageResponse;
|
|
2607
|
+
if (response.data?.result?.data) {
|
|
2608
|
+
imageResponse = response.data.result;
|
|
2609
|
+
} else if (response.data?.data) {
|
|
2610
|
+
imageResponse = response.data;
|
|
2611
|
+
} else {
|
|
2612
|
+
throw new BlinkAIError("Invalid response format: missing image data");
|
|
2613
|
+
}
|
|
2614
|
+
if (!Array.isArray(imageResponse.data)) {
|
|
2615
|
+
throw new BlinkAIError("Invalid response format: data should be an array");
|
|
2616
|
+
}
|
|
2617
|
+
imageResponse.data = imageResponse.data.map((item) => {
|
|
2618
|
+
if (typeof item === "string") {
|
|
2619
|
+
return { url: item };
|
|
2620
|
+
} else if (item.url) {
|
|
2621
|
+
return item;
|
|
2622
|
+
} else {
|
|
2623
|
+
throw new BlinkAIError("Invalid image response format");
|
|
2624
|
+
}
|
|
2625
|
+
});
|
|
2626
|
+
return imageResponse;
|
|
2627
|
+
} catch (error) {
|
|
2628
|
+
if (error instanceof BlinkAIError) {
|
|
2629
|
+
throw error;
|
|
2630
|
+
}
|
|
2631
|
+
throw new BlinkAIError(
|
|
2632
|
+
`Image modification failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
2633
|
+
void 0,
|
|
2634
|
+
{ originalError: error }
|
|
2635
|
+
);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2447
2638
|
/**
|
|
2448
2639
|
* Converts text to speech using AI voice synthesis models.
|
|
2449
2640
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1528,6 +1528,9 @@ var BlinkAuth = class {
|
|
|
1528
1528
|
};
|
|
1529
1529
|
|
|
1530
1530
|
// src/database.ts
|
|
1531
|
+
function camelToSnake3(str) {
|
|
1532
|
+
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
1533
|
+
}
|
|
1531
1534
|
function generateSecureId() {
|
|
1532
1535
|
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
1533
1536
|
const array = new Uint8Array(16);
|
|
@@ -1550,14 +1553,16 @@ var BlinkTable = class {
|
|
|
1550
1553
|
constructor(tableName, httpClient) {
|
|
1551
1554
|
this.tableName = tableName;
|
|
1552
1555
|
this.httpClient = httpClient;
|
|
1556
|
+
this.actualTableName = camelToSnake3(tableName);
|
|
1553
1557
|
}
|
|
1558
|
+
actualTableName;
|
|
1554
1559
|
/**
|
|
1555
1560
|
* Create a single record
|
|
1556
1561
|
*/
|
|
1557
1562
|
async create(data, options = {}) {
|
|
1558
1563
|
const record = ensureRecordId(data);
|
|
1559
1564
|
const response = await this.httpClient.dbPost(
|
|
1560
|
-
this.
|
|
1565
|
+
this.actualTableName,
|
|
1561
1566
|
record,
|
|
1562
1567
|
{ returning: options.returning !== false }
|
|
1563
1568
|
);
|
|
@@ -1573,7 +1578,7 @@ var BlinkTable = class {
|
|
|
1573
1578
|
async createMany(data, options = {}) {
|
|
1574
1579
|
const records = data.map(ensureRecordId);
|
|
1575
1580
|
const response = await this.httpClient.dbPost(
|
|
1576
|
-
this.
|
|
1581
|
+
this.actualTableName,
|
|
1577
1582
|
records,
|
|
1578
1583
|
{ returning: options.returning !== false }
|
|
1579
1584
|
);
|
|
@@ -1593,7 +1598,7 @@ var BlinkTable = class {
|
|
|
1593
1598
|
}
|
|
1594
1599
|
const record = ensureRecordId(data);
|
|
1595
1600
|
const response = await this.httpClient.request(
|
|
1596
|
-
`/api/db/${this.httpClient.projectId}/rest/v1/${this.
|
|
1601
|
+
`/api/db/${this.httpClient.projectId}/rest/v1/${this.actualTableName}?on_conflict=${options.onConflict || "id"}`,
|
|
1597
1602
|
{
|
|
1598
1603
|
method: "POST",
|
|
1599
1604
|
body: record,
|
|
@@ -1619,7 +1624,7 @@ var BlinkTable = class {
|
|
|
1619
1624
|
headers["Prefer"] = `${headers["Prefer"] || ""} resolution=merge-duplicates`.trim();
|
|
1620
1625
|
}
|
|
1621
1626
|
const response = await this.httpClient.request(
|
|
1622
|
-
`/api/db/${this.httpClient.projectId}/rest/v1/${this.
|
|
1627
|
+
`/api/db/${this.httpClient.projectId}/rest/v1/${this.actualTableName}?on_conflict=${options.onConflict || "id"}`,
|
|
1623
1628
|
{
|
|
1624
1629
|
method: "POST",
|
|
1625
1630
|
body: records,
|
|
@@ -1637,7 +1642,7 @@ var BlinkTable = class {
|
|
|
1637
1642
|
id: `eq.${id}`,
|
|
1638
1643
|
limit: "1"
|
|
1639
1644
|
};
|
|
1640
|
-
const response = await this.httpClient.dbGet(this.
|
|
1645
|
+
const response = await this.httpClient.dbGet(this.actualTableName, searchParams);
|
|
1641
1646
|
const records = response.data;
|
|
1642
1647
|
if (records.length === 0) {
|
|
1643
1648
|
return null;
|
|
@@ -1650,7 +1655,7 @@ var BlinkTable = class {
|
|
|
1650
1655
|
async list(options = {}) {
|
|
1651
1656
|
const queryParams = buildQuery(options);
|
|
1652
1657
|
const searchParams = queryParams;
|
|
1653
|
-
const response = await this.httpClient.dbGet(this.
|
|
1658
|
+
const response = await this.httpClient.dbGet(this.actualTableName, searchParams);
|
|
1654
1659
|
const records = response.data;
|
|
1655
1660
|
return records;
|
|
1656
1661
|
}
|
|
@@ -1662,7 +1667,7 @@ var BlinkTable = class {
|
|
|
1662
1667
|
id: `eq.${id}`
|
|
1663
1668
|
};
|
|
1664
1669
|
const response = await this.httpClient.dbPatch(
|
|
1665
|
-
this.
|
|
1670
|
+
this.actualTableName,
|
|
1666
1671
|
data,
|
|
1667
1672
|
searchParams,
|
|
1668
1673
|
{ returning: options.returning !== false }
|
|
@@ -1692,7 +1697,7 @@ var BlinkTable = class {
|
|
|
1692
1697
|
const searchParams = {
|
|
1693
1698
|
id: `eq.${id}`
|
|
1694
1699
|
};
|
|
1695
|
-
await this.httpClient.dbDelete(this.
|
|
1700
|
+
await this.httpClient.dbDelete(this.actualTableName, searchParams);
|
|
1696
1701
|
}
|
|
1697
1702
|
/**
|
|
1698
1703
|
* Delete multiple records based on filter
|
|
@@ -1700,7 +1705,7 @@ var BlinkTable = class {
|
|
|
1700
1705
|
async deleteMany(options) {
|
|
1701
1706
|
const queryParams = buildQuery({ where: options.where });
|
|
1702
1707
|
const searchParams = queryParams;
|
|
1703
|
-
await this.httpClient.dbDelete(this.
|
|
1708
|
+
await this.httpClient.dbDelete(this.actualTableName, searchParams);
|
|
1704
1709
|
}
|
|
1705
1710
|
/**
|
|
1706
1711
|
* Count records matching filter
|
|
@@ -1711,7 +1716,7 @@ var BlinkTable = class {
|
|
|
1711
1716
|
select: ["id"]
|
|
1712
1717
|
});
|
|
1713
1718
|
const response = await this.httpClient.request(
|
|
1714
|
-
`/api/db/${this.httpClient.projectId}/rest/v1/${this.
|
|
1719
|
+
`/api/db/${this.httpClient.projectId}/rest/v1/${this.actualTableName}`,
|
|
1715
1720
|
{
|
|
1716
1721
|
method: "GET",
|
|
1717
1722
|
searchParams: queryParams,
|
|
@@ -1880,6 +1885,74 @@ var BlinkStorageImpl = class {
|
|
|
1880
1885
|
);
|
|
1881
1886
|
}
|
|
1882
1887
|
}
|
|
1888
|
+
/**
|
|
1889
|
+
* Get a download URL for a file that triggers browser download
|
|
1890
|
+
*
|
|
1891
|
+
* @param path - Path to the file in project storage
|
|
1892
|
+
* @param options - Download options including custom filename
|
|
1893
|
+
* @returns Promise resolving to download response with download URL
|
|
1894
|
+
*
|
|
1895
|
+
* @example
|
|
1896
|
+
* ```ts
|
|
1897
|
+
* // Download with original filename
|
|
1898
|
+
* const { downloadUrl, filename } = await blink.storage.download('images/photo.jpg');
|
|
1899
|
+
* window.open(downloadUrl, '_blank');
|
|
1900
|
+
*
|
|
1901
|
+
* // Download with custom filename
|
|
1902
|
+
* const { downloadUrl } = await blink.storage.download(
|
|
1903
|
+
* 'images/photo.jpg',
|
|
1904
|
+
* { filename: 'my-photo.jpg' }
|
|
1905
|
+
* );
|
|
1906
|
+
*
|
|
1907
|
+
* // Create download link in React
|
|
1908
|
+
* <a href={downloadUrl} download={filename}>Download Image</a>
|
|
1909
|
+
* ```
|
|
1910
|
+
*/
|
|
1911
|
+
async download(path, options = {}) {
|
|
1912
|
+
try {
|
|
1913
|
+
if (!path || typeof path !== "string" || !path.trim()) {
|
|
1914
|
+
throw new BlinkStorageError("Path must be a non-empty string");
|
|
1915
|
+
}
|
|
1916
|
+
const response = await this.httpClient.request(
|
|
1917
|
+
`/api/storage/${this.httpClient.projectId}/download`,
|
|
1918
|
+
{
|
|
1919
|
+
method: "GET",
|
|
1920
|
+
searchParams: {
|
|
1921
|
+
path: path.trim(),
|
|
1922
|
+
...options.filename && { filename: options.filename }
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
);
|
|
1926
|
+
if (response.data?.downloadUrl) {
|
|
1927
|
+
return {
|
|
1928
|
+
downloadUrl: response.data.downloadUrl,
|
|
1929
|
+
filename: response.data.filename || options.filename || path.split("/").pop() || "download",
|
|
1930
|
+
contentType: response.data.contentType,
|
|
1931
|
+
size: response.data.size
|
|
1932
|
+
};
|
|
1933
|
+
} else {
|
|
1934
|
+
throw new BlinkStorageError("Invalid response format: missing downloadUrl");
|
|
1935
|
+
}
|
|
1936
|
+
} catch (error) {
|
|
1937
|
+
if (error instanceof BlinkStorageError) {
|
|
1938
|
+
throw error;
|
|
1939
|
+
}
|
|
1940
|
+
if (error instanceof Error && "status" in error) {
|
|
1941
|
+
const status = error.status;
|
|
1942
|
+
if (status === 404) {
|
|
1943
|
+
throw new BlinkStorageError("File not found", 404);
|
|
1944
|
+
}
|
|
1945
|
+
if (status === 400) {
|
|
1946
|
+
throw new BlinkStorageError("Invalid request parameters", 400);
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
throw new BlinkStorageError(
|
|
1950
|
+
`Download failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1951
|
+
void 0,
|
|
1952
|
+
{ originalError: error }
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1883
1956
|
/**
|
|
1884
1957
|
* Remove one or more files from project storage
|
|
1885
1958
|
*
|
|
@@ -2347,15 +2420,15 @@ var BlinkAIImpl = class {
|
|
|
2347
2420
|
}
|
|
2348
2421
|
}
|
|
2349
2422
|
/**
|
|
2350
|
-
* Generates images from text descriptions using AI
|
|
2423
|
+
* Generates images from text descriptions using AI.
|
|
2351
2424
|
*
|
|
2352
2425
|
* @param options - Object containing:
|
|
2353
|
-
* - `prompt`: Text description of the image
|
|
2354
|
-
* - `size`: Image dimensions (
|
|
2355
|
-
* - `quality`: Image quality ("standard" or "hd")
|
|
2426
|
+
* - `prompt`: Text description of the desired image (required)
|
|
2427
|
+
* - `size`: Image dimensions (default: "1024x1024")
|
|
2428
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
2356
2429
|
* - `n`: Number of images to generate (default: 1)
|
|
2357
|
-
* - `
|
|
2358
|
-
* - Plus optional
|
|
2430
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
2431
|
+
* - Plus optional signal parameter
|
|
2359
2432
|
*
|
|
2360
2433
|
* @example
|
|
2361
2434
|
* ```ts
|
|
@@ -2368,29 +2441,25 @@ var BlinkAIImpl = class {
|
|
|
2368
2441
|
* // High-quality image with specific size
|
|
2369
2442
|
* const { data } = await blink.ai.generateImage({
|
|
2370
2443
|
* prompt: "A futuristic city skyline with flying cars",
|
|
2371
|
-
* size: "
|
|
2444
|
+
* size: "1536x1024",
|
|
2372
2445
|
* quality: "hd",
|
|
2373
|
-
*
|
|
2446
|
+
* background: "transparent"
|
|
2374
2447
|
* });
|
|
2375
2448
|
*
|
|
2376
2449
|
* // Multiple images
|
|
2377
2450
|
* const { data } = await blink.ai.generateImage({
|
|
2378
2451
|
* prompt: "A cute robot mascot for a tech company",
|
|
2379
2452
|
* n: 3,
|
|
2380
|
-
* size: "1024x1024"
|
|
2453
|
+
* size: "1024x1024",
|
|
2454
|
+
* quality: "hd"
|
|
2381
2455
|
* });
|
|
2382
2456
|
* data.forEach((img, i) => console.log(`Image ${i+1}:`, img.url));
|
|
2383
|
-
*
|
|
2384
|
-
* // Base64 format for direct embedding
|
|
2385
|
-
* const { data } = await blink.ai.generateImage({
|
|
2386
|
-
* prompt: "A minimalist logo design",
|
|
2387
|
-
* response_format: "b64_json"
|
|
2388
|
-
* });
|
|
2389
|
-
* console.log("Base64 data:", data[0].b64_json);
|
|
2390
2457
|
* ```
|
|
2391
2458
|
*
|
|
2392
2459
|
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
2393
|
-
* - `data`: Array of generated images with
|
|
2460
|
+
* - `data`: Array of generated images with URLs
|
|
2461
|
+
* - `created`: Timestamp of generation
|
|
2462
|
+
* - `usage`: Token usage information
|
|
2394
2463
|
*/
|
|
2395
2464
|
async generateImage(options) {
|
|
2396
2465
|
try {
|
|
@@ -2400,11 +2469,12 @@ var BlinkAIImpl = class {
|
|
|
2400
2469
|
const response = await this.httpClient.aiImage(
|
|
2401
2470
|
options.prompt,
|
|
2402
2471
|
{
|
|
2403
|
-
model:
|
|
2472
|
+
model: "gpt-image-1",
|
|
2404
2473
|
size: options.size,
|
|
2405
2474
|
quality: options.quality,
|
|
2406
2475
|
n: options.n,
|
|
2407
|
-
|
|
2476
|
+
background: options.background,
|
|
2477
|
+
response_format: "url",
|
|
2408
2478
|
signal: options.signal
|
|
2409
2479
|
}
|
|
2410
2480
|
);
|
|
@@ -2424,10 +2494,8 @@ var BlinkAIImpl = class {
|
|
|
2424
2494
|
return { url: item };
|
|
2425
2495
|
} else if (item.url) {
|
|
2426
2496
|
return item;
|
|
2427
|
-
} else if (item.b64_json) {
|
|
2428
|
-
return { b64_json: item.b64_json };
|
|
2429
2497
|
} else {
|
|
2430
|
-
|
|
2498
|
+
throw new BlinkAIError("Invalid image response format");
|
|
2431
2499
|
}
|
|
2432
2500
|
});
|
|
2433
2501
|
return imageResponse;
|
|
@@ -2442,6 +2510,129 @@ var BlinkAIImpl = class {
|
|
|
2442
2510
|
);
|
|
2443
2511
|
}
|
|
2444
2512
|
}
|
|
2513
|
+
/**
|
|
2514
|
+
* Modifies existing images using AI with text prompts for image-to-image editing.
|
|
2515
|
+
*
|
|
2516
|
+
* @param options - Object containing:
|
|
2517
|
+
* - `images`: Array of public image URLs to modify (required, up to 16 images)
|
|
2518
|
+
* - `prompt`: Text description of desired modifications (required)
|
|
2519
|
+
* - `size`: Output image dimensions (default: "auto")
|
|
2520
|
+
* - `quality`: Image quality ("standard" or "hd", default: "standard")
|
|
2521
|
+
* - `n`: Number of output images to generate (default: 1)
|
|
2522
|
+
* - `background`: Background handling ("auto", "transparent", "opaque", default: "auto")
|
|
2523
|
+
* - Plus optional signal parameter
|
|
2524
|
+
*
|
|
2525
|
+
* @example
|
|
2526
|
+
* ```ts
|
|
2527
|
+
* // Professional headshots from casual photos
|
|
2528
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2529
|
+
* images: [
|
|
2530
|
+
* "https://storage.example.com/user-photo-1.jpg",
|
|
2531
|
+
* "https://storage.example.com/user-photo-2.jpg"
|
|
2532
|
+
* ],
|
|
2533
|
+
* prompt: "Transform into professional business headshots with studio lighting",
|
|
2534
|
+
* quality: "hd",
|
|
2535
|
+
* n: 4
|
|
2536
|
+
* });
|
|
2537
|
+
* data.forEach((img, i) => console.log(`Headshot ${i+1}:`, img.url));
|
|
2538
|
+
*
|
|
2539
|
+
* // Artistic style transformation
|
|
2540
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2541
|
+
* images: ["https://storage.example.com/portrait.jpg"],
|
|
2542
|
+
* prompt: "Transform into oil painting style with dramatic lighting",
|
|
2543
|
+
* quality: "hd",
|
|
2544
|
+
* size: "1024x1024"
|
|
2545
|
+
* });
|
|
2546
|
+
*
|
|
2547
|
+
* // Background replacement
|
|
2548
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2549
|
+
* images: ["https://storage.example.com/product.jpg"],
|
|
2550
|
+
* prompt: "Remove background and place on clean white studio background",
|
|
2551
|
+
* background: "transparent",
|
|
2552
|
+
* n: 2
|
|
2553
|
+
* });
|
|
2554
|
+
*
|
|
2555
|
+
* // Batch processing multiple photos
|
|
2556
|
+
* const userPhotos = [
|
|
2557
|
+
* "https://storage.example.com/photo1.jpg",
|
|
2558
|
+
* "https://storage.example.com/photo2.jpg",
|
|
2559
|
+
* "https://storage.example.com/photo3.jpg"
|
|
2560
|
+
* ];
|
|
2561
|
+
* const { data } = await blink.ai.modifyImage({
|
|
2562
|
+
* images: userPhotos,
|
|
2563
|
+
* prompt: "Convert to black and white vintage style photographs",
|
|
2564
|
+
* quality: "hd"
|
|
2565
|
+
* });
|
|
2566
|
+
* ```
|
|
2567
|
+
*
|
|
2568
|
+
* @returns Promise<ImageGenerationResponse> - Object containing:
|
|
2569
|
+
* - `data`: Array of modified images with URLs
|
|
2570
|
+
* - `created`: Timestamp of generation
|
|
2571
|
+
* - `usage`: Token usage information
|
|
2572
|
+
*/
|
|
2573
|
+
async modifyImage(options) {
|
|
2574
|
+
try {
|
|
2575
|
+
if (!options.prompt) {
|
|
2576
|
+
throw new BlinkAIError("Prompt is required");
|
|
2577
|
+
}
|
|
2578
|
+
if (!options.images || !Array.isArray(options.images) || options.images.length === 0) {
|
|
2579
|
+
throw new BlinkAIError("Images array is required and must contain at least one image URL");
|
|
2580
|
+
}
|
|
2581
|
+
if (options.images.length > 16) {
|
|
2582
|
+
throw new BlinkAIError("Maximum 16 images allowed");
|
|
2583
|
+
}
|
|
2584
|
+
for (let i = 0; i < options.images.length; i++) {
|
|
2585
|
+
const validation = this.validateImageUrl(options.images[i]);
|
|
2586
|
+
if (!validation.isValid) {
|
|
2587
|
+
throw new BlinkAIError(`Image ${i + 1}: ${validation.error}`);
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
const response = await this.httpClient.aiImage(
|
|
2591
|
+
options.prompt,
|
|
2592
|
+
// Non-null assertion since we validated above
|
|
2593
|
+
{
|
|
2594
|
+
model: "gpt-image-1",
|
|
2595
|
+
images: options.images,
|
|
2596
|
+
size: options.size,
|
|
2597
|
+
quality: options.quality,
|
|
2598
|
+
n: options.n,
|
|
2599
|
+
background: options.background,
|
|
2600
|
+
response_format: "url",
|
|
2601
|
+
signal: options.signal
|
|
2602
|
+
}
|
|
2603
|
+
);
|
|
2604
|
+
let imageResponse;
|
|
2605
|
+
if (response.data?.result?.data) {
|
|
2606
|
+
imageResponse = response.data.result;
|
|
2607
|
+
} else if (response.data?.data) {
|
|
2608
|
+
imageResponse = response.data;
|
|
2609
|
+
} else {
|
|
2610
|
+
throw new BlinkAIError("Invalid response format: missing image data");
|
|
2611
|
+
}
|
|
2612
|
+
if (!Array.isArray(imageResponse.data)) {
|
|
2613
|
+
throw new BlinkAIError("Invalid response format: data should be an array");
|
|
2614
|
+
}
|
|
2615
|
+
imageResponse.data = imageResponse.data.map((item) => {
|
|
2616
|
+
if (typeof item === "string") {
|
|
2617
|
+
return { url: item };
|
|
2618
|
+
} else if (item.url) {
|
|
2619
|
+
return item;
|
|
2620
|
+
} else {
|
|
2621
|
+
throw new BlinkAIError("Invalid image response format");
|
|
2622
|
+
}
|
|
2623
|
+
});
|
|
2624
|
+
return imageResponse;
|
|
2625
|
+
} catch (error) {
|
|
2626
|
+
if (error instanceof BlinkAIError) {
|
|
2627
|
+
throw error;
|
|
2628
|
+
}
|
|
2629
|
+
throw new BlinkAIError(
|
|
2630
|
+
`Image modification failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
2631
|
+
void 0,
|
|
2632
|
+
{ originalError: error }
|
|
2633
|
+
);
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2445
2636
|
/**
|
|
2446
2637
|
* Converts text to speech using AI voice synthesis models.
|
|
2447
2638
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blinkdotnew/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Blink TypeScript SDK for client-side applications - Zero-boilerplate CRUD + auth + AI + analytics + notifications for modern SaaS/AI apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"blink",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@blink/core": "
|
|
53
|
+
"@blink/core": "0.4.0",
|
|
54
54
|
"tsup": "^8.0.0",
|
|
55
55
|
"typescript": "^5.0.0"
|
|
56
56
|
},
|