@blinkdotnew/sdk 0.18.8 → 0.19.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/dist/index.js CHANGED
@@ -7,6 +7,124 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
  throw Error('Dynamic require of "' + x + '" is not supported');
8
8
  });
9
9
 
10
+ // ../core/src/storage-adapter.ts
11
+ var WebStorageAdapter = class {
12
+ getItem(key) {
13
+ try {
14
+ if (typeof localStorage === "undefined") return null;
15
+ return localStorage.getItem(key);
16
+ } catch (error) {
17
+ console.warn("Failed to get item from localStorage:", error);
18
+ return null;
19
+ }
20
+ }
21
+ setItem(key, value) {
22
+ try {
23
+ if (typeof localStorage === "undefined") return;
24
+ localStorage.setItem(key, value);
25
+ } catch (error) {
26
+ console.warn("Failed to set item in localStorage:", error);
27
+ }
28
+ }
29
+ removeItem(key) {
30
+ try {
31
+ if (typeof localStorage === "undefined") return;
32
+ localStorage.removeItem(key);
33
+ } catch (error) {
34
+ console.warn("Failed to remove item from localStorage:", error);
35
+ }
36
+ }
37
+ clear() {
38
+ try {
39
+ if (typeof localStorage === "undefined") return;
40
+ localStorage.clear();
41
+ } catch (error) {
42
+ console.warn("Failed to clear localStorage:", error);
43
+ }
44
+ }
45
+ };
46
+ var AsyncStorageAdapter = class {
47
+ constructor(asyncStorage) {
48
+ this.asyncStorage = asyncStorage;
49
+ if (!asyncStorage) {
50
+ throw new Error("AsyncStorage instance is required");
51
+ }
52
+ }
53
+ async getItem(key) {
54
+ try {
55
+ return await this.asyncStorage.getItem(key);
56
+ } catch (error) {
57
+ console.warn("Failed to get item from AsyncStorage:", error);
58
+ return null;
59
+ }
60
+ }
61
+ async setItem(key, value) {
62
+ try {
63
+ await this.asyncStorage.setItem(key, value);
64
+ } catch (error) {
65
+ console.warn("Failed to set item in AsyncStorage:", error);
66
+ }
67
+ }
68
+ async removeItem(key) {
69
+ try {
70
+ await this.asyncStorage.removeItem(key);
71
+ } catch (error) {
72
+ console.warn("Failed to remove item from AsyncStorage:", error);
73
+ }
74
+ }
75
+ async clear() {
76
+ try {
77
+ await this.asyncStorage.clear();
78
+ } catch (error) {
79
+ console.warn("Failed to clear AsyncStorage:", error);
80
+ }
81
+ }
82
+ };
83
+ var NoOpStorageAdapter = class {
84
+ getItem(_key) {
85
+ return null;
86
+ }
87
+ setItem(_key, _value) {
88
+ }
89
+ removeItem(_key) {
90
+ }
91
+ clear() {
92
+ }
93
+ };
94
+ function getDefaultStorageAdapter() {
95
+ if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
96
+ try {
97
+ localStorage.setItem("__test__", "test");
98
+ localStorage.removeItem("__test__");
99
+ return new WebStorageAdapter();
100
+ } catch {
101
+ }
102
+ }
103
+ return new NoOpStorageAdapter();
104
+ }
105
+
106
+ // ../core/src/platform.ts
107
+ function detectPlatform() {
108
+ if (typeof process !== "undefined" && process.versions?.node) {
109
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
110
+ return "react-native";
111
+ }
112
+ return "node";
113
+ }
114
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
115
+ return "react-native";
116
+ }
117
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
118
+ return "web";
119
+ }
120
+ return "node";
121
+ }
122
+ var platform = detectPlatform();
123
+ var isWeb = platform === "web";
124
+ var isReactNative = platform === "react-native";
125
+ var isNode = platform === "node";
126
+ var isBrowser = isWeb || isReactNative;
127
+
10
128
  // ../core/src/types.ts
11
129
  var BlinkError = class extends Error {
12
130
  constructor(message, code, status, details) {
@@ -914,6 +1032,7 @@ var BlinkAuth = class {
914
1032
  isIframe = false;
915
1033
  initializationPromise = null;
916
1034
  isInitialized = false;
1035
+ storage;
917
1036
  constructor(config) {
918
1037
  this.config = config;
919
1038
  if (!config.projectId) {
@@ -940,7 +1059,8 @@ var BlinkAuth = class {
940
1059
  isAuthenticated: false,
941
1060
  isLoading: false
942
1061
  };
943
- if (typeof window !== "undefined") {
1062
+ this.storage = config.auth?.storage || config.storage || getDefaultStorageAdapter();
1063
+ if (isWeb) {
944
1064
  this.isIframe = window.self !== window.top;
945
1065
  this.setupParentWindowListener();
946
1066
  this.setupCrossTabSync();
@@ -977,7 +1097,7 @@ var BlinkAuth = class {
977
1097
  * Setup listener for tokens from parent window
978
1098
  */
979
1099
  setupParentWindowListener() {
980
- if (!this.isIframe) return;
1100
+ if (!isWeb || !this.isIframe) return;
981
1101
  window.addEventListener("message", (event) => {
982
1102
  if (event.origin !== "https://blink.new" && event.origin !== "http://localhost:3000" && event.origin !== "http://localhost:3001") {
983
1103
  return;
@@ -1032,7 +1152,7 @@ var BlinkAuth = class {
1032
1152
  console.log("\u2705 Auth initialization complete (from URL)");
1033
1153
  return;
1034
1154
  }
1035
- const storedTokens = this.getStoredTokens();
1155
+ const storedTokens = await this.getStoredTokens();
1036
1156
  if (storedTokens) {
1037
1157
  console.log("\u{1F4BE} Found stored tokens, validating...", {
1038
1158
  hasAccessToken: !!storedTokens.access_token,
@@ -2085,15 +2205,18 @@ var BlinkAuth = class {
2085
2205
  expiresIn: tokensWithTimestamp.expires_in,
2086
2206
  issuedAt: tokensWithTimestamp.issued_at
2087
2207
  });
2088
- if (persist && typeof window !== "undefined") {
2208
+ if (persist) {
2089
2209
  try {
2090
- localStorage.setItem(this.getStorageKey("tokens"), JSON.stringify(tokensWithTimestamp));
2091
- console.log("\u{1F4BE} Tokens persisted to localStorage");
2092
- } catch (error) {
2093
- console.log("\u{1F4A5} Error persisting tokens to localStorage:", error);
2094
- if (error instanceof DOMException && error.name === "SecurityError") {
2095
- console.log("\u{1F6AB} localStorage access blocked - running in cross-origin iframe");
2210
+ const result = this.storage.setItem(
2211
+ this.getStorageKey("tokens"),
2212
+ JSON.stringify(tokensWithTimestamp)
2213
+ );
2214
+ if (result instanceof Promise) {
2215
+ await result;
2096
2216
  }
2217
+ console.log("\u{1F4BE} Tokens persisted to storage");
2218
+ } catch (error) {
2219
+ console.log("\u{1F4A5} Error persisting tokens:", error);
2097
2220
  }
2098
2221
  }
2099
2222
  let user = null;
@@ -2136,12 +2259,15 @@ var BlinkAuth = class {
2136
2259
  });
2137
2260
  }
2138
2261
  clearTokens() {
2139
- if (typeof window !== "undefined") {
2140
- try {
2141
- localStorage.removeItem(this.getStorageKey("tokens"));
2142
- } catch (error) {
2143
- console.log("\u{1F4A5} Error clearing tokens from localStorage:", error);
2262
+ try {
2263
+ const result = this.storage.removeItem(this.getStorageKey("tokens"));
2264
+ if (result instanceof Promise) {
2265
+ result.catch((error) => {
2266
+ console.log("\u{1F4A5} Error clearing tokens from storage:", error);
2267
+ });
2144
2268
  }
2269
+ } catch (error) {
2270
+ console.log("\u{1F4A5} Error clearing tokens:", error);
2145
2271
  }
2146
2272
  this.updateAuthState({
2147
2273
  user: null,
@@ -2150,18 +2276,17 @@ var BlinkAuth = class {
2150
2276
  isLoading: false
2151
2277
  });
2152
2278
  }
2153
- getStoredTokens() {
2154
- if (typeof window === "undefined") return null;
2155
- if (this.isIframe && this.parentWindowTokens) {
2279
+ async getStoredTokens() {
2280
+ if (isWeb && this.isIframe && this.parentWindowTokens) {
2156
2281
  return this.parentWindowTokens;
2157
2282
  }
2158
2283
  try {
2159
- const stored = localStorage.getItem(this.getStorageKey("tokens"));
2160
- console.log("\u{1F50D} Checking localStorage for tokens:", {
2284
+ const result = this.storage.getItem(this.getStorageKey("tokens"));
2285
+ const stored = result instanceof Promise ? await result : result;
2286
+ console.log("\u{1F50D} Checking storage for tokens:", {
2161
2287
  hasStoredData: !!stored,
2162
2288
  storedLength: stored?.length || 0,
2163
- origin: window.location.origin,
2164
- isIframe: window.self !== window.top
2289
+ isIframe: isWeb && this.isIframe
2165
2290
  });
2166
2291
  if (stored) {
2167
2292
  const tokens = JSON.parse(stored);
@@ -2175,10 +2300,7 @@ var BlinkAuth = class {
2175
2300
  }
2176
2301
  return null;
2177
2302
  } catch (error) {
2178
- console.log("\u{1F4A5} Error accessing localStorage:", error);
2179
- if (error instanceof DOMException && error.name === "SecurityError") {
2180
- console.log("\u{1F6AB} localStorage access blocked - likely due to cross-origin iframe restrictions");
2181
- }
2303
+ console.log("\u{1F4A5} Error reading tokens from storage:", error);
2182
2304
  return null;
2183
2305
  }
2184
2306
  }
@@ -2324,7 +2446,7 @@ var BlinkAuth = class {
2324
2446
  * Setup cross-tab authentication synchronization
2325
2447
  */
2326
2448
  setupCrossTabSync() {
2327
- if (typeof window === "undefined") return;
2449
+ if (!isWeb) return;
2328
2450
  window.addEventListener("storage", (e) => {
2329
2451
  if (e.key === this.getStorageKey("tokens")) {
2330
2452
  const newTokens = e.newValue ? JSON.parse(e.newValue) : null;
@@ -3370,38 +3492,58 @@ var BlinkAIImpl = class {
3370
3492
  }
3371
3493
  }
3372
3494
  /**
3373
- * Generates images from text descriptions using Gemini 2.5 Flash Image.
3495
+ * Generates images from text descriptions using AI image models.
3374
3496
  *
3375
3497
  * @param options - Object containing:
3376
3498
  * - `prompt`: Text description of the desired image (required, up to 100k characters)
3499
+ * - `model`: AI model to use (optional). Available models:
3500
+ * **Fal.ai Models (Recommended):**
3501
+ * - `"fal-ai/nano-banana"` (default) - Gemini 2.5 Flash Image (Fast)
3502
+ * - `"fal-ai/nano-banana-pro"` - Gemini 3 Pro Image (High quality)
3503
+ * - `"fal-ai/gemini-25-flash-image"` - Alias for nano-banana
3504
+ * - `"fal-ai/gemini-3-pro-image-preview"` - Alias for nano-banana-pro
3505
+ * **Legacy Gemini Models:**
3506
+ * - `"gemini-2.5-flash-image-preview"` - Direct Gemini API
3507
+ * - `"gemini-3-pro-image-preview"` - Direct Gemini API
3377
3508
  * - `n`: Number of images to generate (default: 1)
3509
+ * - `size`: Image dimensions (e.g., "1024x1024", "512x512")
3378
3510
  * - Plus optional signal parameter
3379
3511
  *
3380
3512
  * @example
3381
3513
  * ```ts
3382
- * // Basic image generation
3514
+ * // Basic image generation (uses default fast model)
3383
3515
  * const { data } = await blink.ai.generateImage({
3384
3516
  * prompt: "A serene landscape with mountains and a lake at sunset"
3385
3517
  * });
3386
3518
  * console.log("Image URL:", data[0].url);
3387
3519
  *
3388
- * // Multiple images
3520
+ * // High quality generation with Pro model
3521
+ * const { data } = await blink.ai.generateImage({
3522
+ * prompt: "A detailed infographic about AI with charts and diagrams",
3523
+ * model: "fal-ai/nano-banana-pro",
3524
+ * n: 2
3525
+ * });
3526
+ *
3527
+ * // Fast generation with specific size
3389
3528
  * const { data } = await blink.ai.generateImage({
3390
3529
  * prompt: "A futuristic city skyline with flying cars",
3530
+ * model: "fal-ai/nano-banana",
3531
+ * size: "1024x1024",
3391
3532
  * n: 3
3392
3533
  * });
3393
3534
  * data.forEach((img, i) => console.log(`Image ${i+1}:`, img.url));
3394
3535
  *
3395
- * // Detailed prompt for better results
3536
+ * // Using legacy Gemini model
3396
3537
  * const { data } = await blink.ai.generateImage({
3397
- * prompt: "A cute robot mascot for a tech company, digital art style, vibrant colors, modern design, friendly expression"
3538
+ * prompt: "A cute robot mascot for a tech company",
3539
+ * model: "gemini-2.5-flash-image-preview"
3398
3540
  * });
3399
3541
  * ```
3400
3542
  *
3401
3543
  * @returns Promise<ImageGenerationResponse> - Object containing:
3402
3544
  * - `data`: Array of generated images with URLs
3403
3545
  * - `created`: Timestamp of generation
3404
- * - `model`: Always "gemini-2.5-flash-image-preview"
3546
+ * - `model`: The model used for generation
3405
3547
  */
3406
3548
  async generateImage(options) {
3407
3549
  try {
@@ -3411,7 +3553,9 @@ var BlinkAIImpl = class {
3411
3553
  const response = await this.httpClient.aiImage(
3412
3554
  options.prompt,
3413
3555
  {
3556
+ model: options.model,
3414
3557
  n: options.n,
3558
+ size: options.size,
3415
3559
  signal: options.signal
3416
3560
  }
3417
3561
  );
@@ -3448,16 +3592,38 @@ var BlinkAIImpl = class {
3448
3592
  }
3449
3593
  }
3450
3594
  /**
3451
- * Modifies existing images using Gemini 2.5 Flash Image with text prompts for image-to-image editing.
3595
+ * Modifies existing images using AI image editing models with text prompts for image-to-image editing.
3452
3596
  *
3453
3597
  * @param options - Object containing:
3454
3598
  * - `images`: Array of public image URLs to modify (required, up to 50 images)
3455
3599
  * - `prompt`: Text description of desired modifications (required, up to 100k characters)
3600
+ * - `model`: AI model to use (optional). Available editing models:
3601
+ * **Fal.ai Editing Models (Recommended):**
3602
+ * - `"fal-ai/nano-banana/edit"` (default) - Flash editing (Fast)
3603
+ * - `"fal-ai/nano-banana-pro/edit"` - Pro editing (High quality)
3604
+ * - `"fal-ai/gemini-25-flash-image/edit"` - Alias for nano-banana/edit
3605
+ * - `"fal-ai/gemini-3-pro-image-preview/edit"` - Alias for nano-banana-pro/edit
3606
+ * **Legacy Gemini Models:**
3607
+ * - `"gemini-2.5-flash-image-preview"` - Direct Gemini API
3608
+ * - `"gemini-3-pro-image-preview"` - Direct Gemini API
3456
3609
  * - `n`: Number of output images to generate (default: 1)
3457
3610
  * - Plus optional signal parameter
3458
3611
  *
3459
3612
  * @example
3460
3613
  * ```ts
3614
+ * // Fast editing with default model
3615
+ * const { data } = await blink.ai.modifyImage({
3616
+ * images: ["https://storage.example.com/photo.jpg"],
3617
+ * prompt: "make it green"
3618
+ * });
3619
+ *
3620
+ * // High quality editing with Pro model
3621
+ * const { data } = await blink.ai.modifyImage({
3622
+ * images: ["https://storage.example.com/landscape.jpg"],
3623
+ * prompt: "add a tree in the background",
3624
+ * model: "fal-ai/nano-banana-pro/edit"
3625
+ * });
3626
+ *
3461
3627
  * // Professional headshots from casual photos
3462
3628
  * const { data } = await blink.ai.modifyImage({
3463
3629
  * images: [
@@ -3465,6 +3631,7 @@ var BlinkAIImpl = class {
3465
3631
  * "https://storage.example.com/user-photo-2.jpg"
3466
3632
  * ],
3467
3633
  * prompt: "Transform into professional business headshots with studio lighting",
3634
+ * model: "fal-ai/nano-banana/edit",
3468
3635
  * n: 4
3469
3636
  * });
3470
3637
  * data.forEach((img, i) => console.log(`Headshot ${i+1}:`, img.url));
@@ -3472,7 +3639,8 @@ var BlinkAIImpl = class {
3472
3639
  * // Artistic style transformation
3473
3640
  * const { data } = await blink.ai.modifyImage({
3474
3641
  * images: ["https://storage.example.com/portrait.jpg"],
3475
- * prompt: "Transform into oil painting style with dramatic lighting"
3642
+ * prompt: "Transform into oil painting style with dramatic lighting",
3643
+ * model: "fal-ai/nano-banana-pro/edit"
3476
3644
  * });
3477
3645
  *
3478
3646
  * // Background replacement
@@ -3510,7 +3678,7 @@ var BlinkAIImpl = class {
3510
3678
  * @returns Promise<ImageGenerationResponse> - Object containing:
3511
3679
  * - `data`: Array of modified images with URLs
3512
3680
  * - `created`: Timestamp of generation
3513
- * - `model`: Always "gemini-2.5-flash-image-preview"
3681
+ * - `model`: The model used for editing
3514
3682
  */
3515
3683
  async modifyImage(options) {
3516
3684
  try {
@@ -3533,6 +3701,7 @@ var BlinkAIImpl = class {
3533
3701
  options.prompt,
3534
3702
  // Non-null assertion since we validated above
3535
3703
  {
3704
+ model: options.model,
3536
3705
  images: options.images,
3537
3706
  n: options.n,
3538
3707
  signal: options.signal
@@ -4489,7 +4658,8 @@ var BlinkAnalyticsImpl = class {
4489
4658
  constructor(httpClient, projectId) {
4490
4659
  this.httpClient = httpClient;
4491
4660
  this.projectId = projectId;
4492
- if (typeof window === "undefined") {
4661
+ if (!isWeb) {
4662
+ this.enabled = false;
4493
4663
  return;
4494
4664
  }
4495
4665
  if (navigator.doNotTrack === "1") {
@@ -4513,7 +4683,7 @@ var BlinkAnalyticsImpl = class {
4513
4683
  * Log a custom analytics event
4514
4684
  */
4515
4685
  log(eventName, data = {}) {
4516
- if (!this.enabled || typeof window === "undefined") {
4686
+ if (!this.enabled || !isWeb) {
4517
4687
  return;
4518
4688
  }
4519
4689
  const event = this.buildEvent(eventName, data);
@@ -4701,6 +4871,7 @@ var BlinkAnalyticsImpl = class {
4701
4871
  }
4702
4872
  }
4703
4873
  setupRouteChangeListener() {
4874
+ if (!isWeb) return;
4704
4875
  if (!window.__blinkAnalyticsSetup) {
4705
4876
  const originalPushState = history.pushState;
4706
4877
  const originalReplaceState = history.replaceState;
@@ -4734,6 +4905,7 @@ var BlinkAnalyticsImpl = class {
4734
4905
  window.__blinkAnalyticsInstances?.add(this);
4735
4906
  }
4736
4907
  setupUnloadListener() {
4908
+ if (!isWeb) return;
4737
4909
  window.addEventListener("pagehide", () => {
4738
4910
  this.flush();
4739
4911
  });
@@ -4742,6 +4914,7 @@ var BlinkAnalyticsImpl = class {
4742
4914
  });
4743
4915
  }
4744
4916
  captureUTMParams() {
4917
+ if (!isWeb) return;
4745
4918
  const urlParams = new URLSearchParams(window.location.search);
4746
4919
  this.utmParams = {
4747
4920
  utm_source: urlParams.get("utm_source"),
@@ -4853,6 +5026,7 @@ function createClient(config) {
4853
5026
  return new BlinkClientImpl(config);
4854
5027
  }
4855
5028
 
5029
+ exports.AsyncStorageAdapter = AsyncStorageAdapter;
4856
5030
  exports.BlinkAIImpl = BlinkAIImpl;
4857
5031
  exports.BlinkAnalyticsImpl = BlinkAnalyticsImpl;
4858
5032
  exports.BlinkDataImpl = BlinkDataImpl;
@@ -4861,6 +5035,14 @@ exports.BlinkRealtimeChannel = BlinkRealtimeChannel;
4861
5035
  exports.BlinkRealtimeImpl = BlinkRealtimeImpl;
4862
5036
  exports.BlinkStorageImpl = BlinkStorageImpl;
4863
5037
  exports.BlinkTable = BlinkTable;
5038
+ exports.NoOpStorageAdapter = NoOpStorageAdapter;
5039
+ exports.WebStorageAdapter = WebStorageAdapter;
4864
5040
  exports.createClient = createClient;
5041
+ exports.getDefaultStorageAdapter = getDefaultStorageAdapter;
5042
+ exports.isBrowser = isBrowser;
5043
+ exports.isNode = isNode;
5044
+ exports.isReactNative = isReactNative;
5045
+ exports.isWeb = isWeb;
5046
+ exports.platform = platform;
4865
5047
  //# sourceMappingURL=index.js.map
4866
5048
  //# sourceMappingURL=index.js.map