@blinkdotnew/sdk 2.0.3 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -61,6 +61,39 @@ interface BlinkClientConfig {
61
61
  projectId: string;
62
62
  authRequired?: boolean;
63
63
  auth?: BlinkAuthConfig;
64
+ /**
65
+ * Publishable key (client-safe).
66
+ *
67
+ * Used for **public endpoints** when no user JWT is present (e.g. analytics ingest, storage upload,
68
+ * optional public DB reads). Never use for privileged operations.
69
+ */
70
+ publishableKey?: string;
71
+ /**
72
+ * Secret key (server-only, privileged). Permanent, never expires.
73
+ *
74
+ * Used in **server runtimes** (Edge Functions, Workers) for privileged operations that require
75
+ * service-role access (e.g. raw SQL, bypassing row-level security).
76
+ *
77
+ * Format: `blnk_sk_{projectId-last-8}_{random}` (similar to Stripe's `sk_live_...`)
78
+ *
79
+ * **Security**: Never expose this key in client-side code. It is injected by the platform
80
+ * into edge function environments as `BLINK_SECRET_KEY`.
81
+ *
82
+ * When present, this key takes precedence over user JWTs for all requests.
83
+ *
84
+ * @example
85
+ * // Edge function (Deno)
86
+ * const blink = createClient({
87
+ * projectId: Deno.env.get('BLINK_PROJECT_ID')!,
88
+ * secretKey: Deno.env.get('BLINK_SECRET_KEY'),
89
+ * })
90
+ */
91
+ secretKey?: string;
92
+ /**
93
+ * @deprecated Use `secretKey` instead. Service tokens are JWT-based and expire after 365 days.
94
+ * Secret keys are permanent and never expire.
95
+ */
96
+ serviceToken?: string;
64
97
  /**
65
98
  * Storage adapter for cross-platform token persistence
66
99
  *
@@ -281,6 +314,9 @@ declare class BlinkError extends Error {
281
314
  constructor(message: string, code?: string | undefined, status?: number | undefined, details?: any);
282
315
  }
283
316
  interface StorageUploadOptions {
317
+ /**
318
+ * @deprecated Blink storage uploads are add-only by default. This option is ignored.
319
+ */
284
320
  upsert?: boolean;
285
321
  onProgress?: (percent: number) => void;
286
322
  }
@@ -737,7 +773,7 @@ interface BlinkNotifications {
737
773
  */
738
774
 
739
775
  interface RequestOptions {
740
- method?: 'GET' | 'POST' | 'PATCH' | 'DELETE';
776
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
741
777
  headers?: Record<string, string>;
742
778
  body?: any;
743
779
  searchParams?: Record<string, string>;
@@ -752,9 +788,14 @@ declare class HttpClient {
752
788
  private readonly authUrl;
753
789
  private readonly coreUrl;
754
790
  readonly projectId: string;
791
+ private readonly publishableKey?;
792
+ private readonly secretKey?;
755
793
  private getToken;
756
794
  private getValidToken?;
757
795
  constructor(config: BlinkClientConfig, getToken: () => string | null, getValidToken?: () => Promise<string | null>);
796
+ private shouldAttachPublishableKey;
797
+ private shouldSkipSecretKey;
798
+ private getAuthorizationHeader;
758
799
  /**
759
800
  * Make an authenticated request to the Blink API
760
801
  */
@@ -949,9 +990,9 @@ declare class HttpClient {
949
990
 
950
991
  /**
951
992
  * Platform detection for cross-platform compatibility
952
- * Detects whether code is running on web, React Native, or Node.js
993
+ * Detects whether code is running on web, React Native, Node.js, or Deno
953
994
  */
954
- type Platform = 'web' | 'react-native' | 'node';
995
+ type Platform = 'web' | 'react-native' | 'node' | 'deno';
955
996
  /**
956
997
  * Current platform
957
998
  */
@@ -962,7 +1003,9 @@ declare const platform: Platform;
962
1003
  declare const isWeb: boolean;
963
1004
  declare const isReactNative: boolean;
964
1005
  declare const isNode: boolean;
1006
+ declare const isDeno: boolean;
965
1007
  declare const isBrowser: boolean;
1008
+ declare const isServer: boolean;
966
1009
 
967
1010
  /**
968
1011
  * Blink Auth Module - Client-side authentication management
@@ -1633,6 +1676,50 @@ declare class BlinkAnalyticsImpl implements BlinkAnalytics {
1633
1676
  private detectChannel;
1634
1677
  }
1635
1678
 
1679
+ /**
1680
+ * Blink Functions - Edge function invocation helper
1681
+ * Provides a simple interface for calling Blink Edge Functions with automatic JWT attachment
1682
+ */
1683
+
1684
+ interface FunctionsInvokeOptions {
1685
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
1686
+ body?: any;
1687
+ headers?: Record<string, string>;
1688
+ searchParams?: Record<string, string>;
1689
+ }
1690
+ interface FunctionsInvokeResponse<T = any> {
1691
+ data: T;
1692
+ status: number;
1693
+ headers: Headers;
1694
+ }
1695
+ interface BlinkFunctions {
1696
+ /**
1697
+ * Invoke a Blink Edge Function.
1698
+ *
1699
+ * Automatically attaches the user's JWT for authenticated requests.
1700
+ * The function URL is constructed as: https://{projectSuffix}--{functionSlug}.functions.blink.new
1701
+ *
1702
+ * @param functionSlug - The slug of the edge function to invoke
1703
+ * @param options - Request options (method, body, headers, etc.)
1704
+ * @returns The function response
1705
+ *
1706
+ * @example
1707
+ * // Simple POST request
1708
+ * const { data } = await blink.functions.invoke('my-function', {
1709
+ * method: 'POST',
1710
+ * body: { message: 'Hello' }
1711
+ * })
1712
+ *
1713
+ * @example
1714
+ * // GET request with query params
1715
+ * const { data } = await blink.functions.invoke('my-function', {
1716
+ * method: 'GET',
1717
+ * searchParams: { limit: '10' }
1718
+ * })
1719
+ */
1720
+ invoke<T = any>(functionSlug: string, options?: FunctionsInvokeOptions): Promise<FunctionsInvokeResponse<T>>;
1721
+ }
1722
+
1636
1723
  /**
1637
1724
  * Blink Client - Main SDK entry point
1638
1725
  * Factory function and client class for the Blink SDK
@@ -1647,6 +1734,7 @@ interface BlinkClient {
1647
1734
  realtime: BlinkRealtime;
1648
1735
  notifications: BlinkNotifications;
1649
1736
  analytics: BlinkAnalytics;
1737
+ functions: BlinkFunctions;
1650
1738
  }
1651
1739
  /**
1652
1740
  * Create a new Blink client instance
@@ -2296,4 +2384,4 @@ declare class BlinkRealtimeImpl implements BlinkRealtime {
2296
2384
  onPresence(channelName: string, callback: (users: PresenceUser[]) => void): () => void;
2297
2385
  }
2298
2386
 
2299
- export { type AnalyticsEvent, AsyncStorageAdapter, type AuthState, type AuthStateChangeCallback, type AuthTokens, type BlinkAI, BlinkAIImpl, type BlinkAnalytics, BlinkAnalyticsImpl, type BlinkClient, type BlinkClientConfig, type BlinkData, BlinkDataImpl, BlinkDatabase, type BlinkRealtime, BlinkRealtimeChannel, BlinkRealtimeError, BlinkRealtimeImpl, type BlinkStorage, BlinkStorageImpl, BlinkTable, type BlinkUser, type CreateOptions, type DataExtraction, type FileObject, type FilterCondition, type ImageGenerationRequest, type ImageGenerationResponse, type Message, NoOpStorageAdapter, type ObjectGenerationRequest, type ObjectGenerationResponse, type PresenceUser, type QueryOptions, type RealtimeChannel, type RealtimeGetMessagesOptions, type RealtimeMessage, type RealtimePublishOptions, type RealtimeSubscribeOptions, type SearchRequest, type SearchResponse, type SpeechGenerationRequest, type SpeechGenerationResponse, type StorageAdapter, type StorageUploadOptions, type StorageUploadResponse, type TableOperations, type TextGenerationRequest, type TextGenerationResponse, type TokenUsage, type TranscriptionRequest, type TranscriptionResponse, type UpdateOptions, type UpsertOptions, type WebBrowserModule, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isNode, isReactNative, isWeb, platform };
2387
+ export { type AnalyticsEvent, AsyncStorageAdapter, type AuthState, type AuthStateChangeCallback, type AuthTokens, type BlinkAI, BlinkAIImpl, type BlinkAnalytics, BlinkAnalyticsImpl, type BlinkClient, type BlinkClientConfig, type BlinkData, BlinkDataImpl, BlinkDatabase, type BlinkRealtime, BlinkRealtimeChannel, BlinkRealtimeError, BlinkRealtimeImpl, type BlinkStorage, BlinkStorageImpl, BlinkTable, type BlinkUser, type CreateOptions, type DataExtraction, type FileObject, type FilterCondition, type ImageGenerationRequest, type ImageGenerationResponse, type Message, NoOpStorageAdapter, type ObjectGenerationRequest, type ObjectGenerationResponse, type PresenceUser, type QueryOptions, type RealtimeChannel, type RealtimeGetMessagesOptions, type RealtimeMessage, type RealtimePublishOptions, type RealtimeSubscribeOptions, type SearchRequest, type SearchResponse, type SpeechGenerationRequest, type SpeechGenerationResponse, type StorageAdapter, type StorageUploadOptions, type StorageUploadResponse, type TableOperations, type TextGenerationRequest, type TextGenerationResponse, type TokenUsage, type TranscriptionRequest, type TranscriptionResponse, type UpdateOptions, type UpsertOptions, type WebBrowserModule, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isDeno, isNode, isReactNative, isServer, isWeb, platform };
package/dist/index.d.ts CHANGED
@@ -61,6 +61,39 @@ interface BlinkClientConfig {
61
61
  projectId: string;
62
62
  authRequired?: boolean;
63
63
  auth?: BlinkAuthConfig;
64
+ /**
65
+ * Publishable key (client-safe).
66
+ *
67
+ * Used for **public endpoints** when no user JWT is present (e.g. analytics ingest, storage upload,
68
+ * optional public DB reads). Never use for privileged operations.
69
+ */
70
+ publishableKey?: string;
71
+ /**
72
+ * Secret key (server-only, privileged). Permanent, never expires.
73
+ *
74
+ * Used in **server runtimes** (Edge Functions, Workers) for privileged operations that require
75
+ * service-role access (e.g. raw SQL, bypassing row-level security).
76
+ *
77
+ * Format: `blnk_sk_{projectId-last-8}_{random}` (similar to Stripe's `sk_live_...`)
78
+ *
79
+ * **Security**: Never expose this key in client-side code. It is injected by the platform
80
+ * into edge function environments as `BLINK_SECRET_KEY`.
81
+ *
82
+ * When present, this key takes precedence over user JWTs for all requests.
83
+ *
84
+ * @example
85
+ * // Edge function (Deno)
86
+ * const blink = createClient({
87
+ * projectId: Deno.env.get('BLINK_PROJECT_ID')!,
88
+ * secretKey: Deno.env.get('BLINK_SECRET_KEY'),
89
+ * })
90
+ */
91
+ secretKey?: string;
92
+ /**
93
+ * @deprecated Use `secretKey` instead. Service tokens are JWT-based and expire after 365 days.
94
+ * Secret keys are permanent and never expire.
95
+ */
96
+ serviceToken?: string;
64
97
  /**
65
98
  * Storage adapter for cross-platform token persistence
66
99
  *
@@ -281,6 +314,9 @@ declare class BlinkError extends Error {
281
314
  constructor(message: string, code?: string | undefined, status?: number | undefined, details?: any);
282
315
  }
283
316
  interface StorageUploadOptions {
317
+ /**
318
+ * @deprecated Blink storage uploads are add-only by default. This option is ignored.
319
+ */
284
320
  upsert?: boolean;
285
321
  onProgress?: (percent: number) => void;
286
322
  }
@@ -737,7 +773,7 @@ interface BlinkNotifications {
737
773
  */
738
774
 
739
775
  interface RequestOptions {
740
- method?: 'GET' | 'POST' | 'PATCH' | 'DELETE';
776
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
741
777
  headers?: Record<string, string>;
742
778
  body?: any;
743
779
  searchParams?: Record<string, string>;
@@ -752,9 +788,14 @@ declare class HttpClient {
752
788
  private readonly authUrl;
753
789
  private readonly coreUrl;
754
790
  readonly projectId: string;
791
+ private readonly publishableKey?;
792
+ private readonly secretKey?;
755
793
  private getToken;
756
794
  private getValidToken?;
757
795
  constructor(config: BlinkClientConfig, getToken: () => string | null, getValidToken?: () => Promise<string | null>);
796
+ private shouldAttachPublishableKey;
797
+ private shouldSkipSecretKey;
798
+ private getAuthorizationHeader;
758
799
  /**
759
800
  * Make an authenticated request to the Blink API
760
801
  */
@@ -949,9 +990,9 @@ declare class HttpClient {
949
990
 
950
991
  /**
951
992
  * Platform detection for cross-platform compatibility
952
- * Detects whether code is running on web, React Native, or Node.js
993
+ * Detects whether code is running on web, React Native, Node.js, or Deno
953
994
  */
954
- type Platform = 'web' | 'react-native' | 'node';
995
+ type Platform = 'web' | 'react-native' | 'node' | 'deno';
955
996
  /**
956
997
  * Current platform
957
998
  */
@@ -962,7 +1003,9 @@ declare const platform: Platform;
962
1003
  declare const isWeb: boolean;
963
1004
  declare const isReactNative: boolean;
964
1005
  declare const isNode: boolean;
1006
+ declare const isDeno: boolean;
965
1007
  declare const isBrowser: boolean;
1008
+ declare const isServer: boolean;
966
1009
 
967
1010
  /**
968
1011
  * Blink Auth Module - Client-side authentication management
@@ -1633,6 +1676,50 @@ declare class BlinkAnalyticsImpl implements BlinkAnalytics {
1633
1676
  private detectChannel;
1634
1677
  }
1635
1678
 
1679
+ /**
1680
+ * Blink Functions - Edge function invocation helper
1681
+ * Provides a simple interface for calling Blink Edge Functions with automatic JWT attachment
1682
+ */
1683
+
1684
+ interface FunctionsInvokeOptions {
1685
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
1686
+ body?: any;
1687
+ headers?: Record<string, string>;
1688
+ searchParams?: Record<string, string>;
1689
+ }
1690
+ interface FunctionsInvokeResponse<T = any> {
1691
+ data: T;
1692
+ status: number;
1693
+ headers: Headers;
1694
+ }
1695
+ interface BlinkFunctions {
1696
+ /**
1697
+ * Invoke a Blink Edge Function.
1698
+ *
1699
+ * Automatically attaches the user's JWT for authenticated requests.
1700
+ * The function URL is constructed as: https://{projectSuffix}--{functionSlug}.functions.blink.new
1701
+ *
1702
+ * @param functionSlug - The slug of the edge function to invoke
1703
+ * @param options - Request options (method, body, headers, etc.)
1704
+ * @returns The function response
1705
+ *
1706
+ * @example
1707
+ * // Simple POST request
1708
+ * const { data } = await blink.functions.invoke('my-function', {
1709
+ * method: 'POST',
1710
+ * body: { message: 'Hello' }
1711
+ * })
1712
+ *
1713
+ * @example
1714
+ * // GET request with query params
1715
+ * const { data } = await blink.functions.invoke('my-function', {
1716
+ * method: 'GET',
1717
+ * searchParams: { limit: '10' }
1718
+ * })
1719
+ */
1720
+ invoke<T = any>(functionSlug: string, options?: FunctionsInvokeOptions): Promise<FunctionsInvokeResponse<T>>;
1721
+ }
1722
+
1636
1723
  /**
1637
1724
  * Blink Client - Main SDK entry point
1638
1725
  * Factory function and client class for the Blink SDK
@@ -1647,6 +1734,7 @@ interface BlinkClient {
1647
1734
  realtime: BlinkRealtime;
1648
1735
  notifications: BlinkNotifications;
1649
1736
  analytics: BlinkAnalytics;
1737
+ functions: BlinkFunctions;
1650
1738
  }
1651
1739
  /**
1652
1740
  * Create a new Blink client instance
@@ -2296,4 +2384,4 @@ declare class BlinkRealtimeImpl implements BlinkRealtime {
2296
2384
  onPresence(channelName: string, callback: (users: PresenceUser[]) => void): () => void;
2297
2385
  }
2298
2386
 
2299
- export { type AnalyticsEvent, AsyncStorageAdapter, type AuthState, type AuthStateChangeCallback, type AuthTokens, type BlinkAI, BlinkAIImpl, type BlinkAnalytics, BlinkAnalyticsImpl, type BlinkClient, type BlinkClientConfig, type BlinkData, BlinkDataImpl, BlinkDatabase, type BlinkRealtime, BlinkRealtimeChannel, BlinkRealtimeError, BlinkRealtimeImpl, type BlinkStorage, BlinkStorageImpl, BlinkTable, type BlinkUser, type CreateOptions, type DataExtraction, type FileObject, type FilterCondition, type ImageGenerationRequest, type ImageGenerationResponse, type Message, NoOpStorageAdapter, type ObjectGenerationRequest, type ObjectGenerationResponse, type PresenceUser, type QueryOptions, type RealtimeChannel, type RealtimeGetMessagesOptions, type RealtimeMessage, type RealtimePublishOptions, type RealtimeSubscribeOptions, type SearchRequest, type SearchResponse, type SpeechGenerationRequest, type SpeechGenerationResponse, type StorageAdapter, type StorageUploadOptions, type StorageUploadResponse, type TableOperations, type TextGenerationRequest, type TextGenerationResponse, type TokenUsage, type TranscriptionRequest, type TranscriptionResponse, type UpdateOptions, type UpsertOptions, type WebBrowserModule, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isNode, isReactNative, isWeb, platform };
2387
+ export { type AnalyticsEvent, AsyncStorageAdapter, type AuthState, type AuthStateChangeCallback, type AuthTokens, type BlinkAI, BlinkAIImpl, type BlinkAnalytics, BlinkAnalyticsImpl, type BlinkClient, type BlinkClientConfig, type BlinkData, BlinkDataImpl, BlinkDatabase, type BlinkRealtime, BlinkRealtimeChannel, BlinkRealtimeError, BlinkRealtimeImpl, type BlinkStorage, BlinkStorageImpl, BlinkTable, type BlinkUser, type CreateOptions, type DataExtraction, type FileObject, type FilterCondition, type ImageGenerationRequest, type ImageGenerationResponse, type Message, NoOpStorageAdapter, type ObjectGenerationRequest, type ObjectGenerationResponse, type PresenceUser, type QueryOptions, type RealtimeChannel, type RealtimeGetMessagesOptions, type RealtimeMessage, type RealtimePublishOptions, type RealtimeSubscribeOptions, type SearchRequest, type SearchResponse, type SpeechGenerationRequest, type SpeechGenerationResponse, type StorageAdapter, type StorageUploadOptions, type StorageUploadResponse, type TableOperations, type TextGenerationRequest, type TextGenerationResponse, type TokenUsage, type TranscriptionRequest, type TranscriptionResponse, type UpdateOptions, type UpsertOptions, type WebBrowserModule, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isDeno, isNode, isReactNative, isServer, isWeb, platform };
package/dist/index.js CHANGED
@@ -7,6 +7,33 @@ 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/platform.ts
11
+ function detectPlatform() {
12
+ if (typeof Deno !== "undefined") {
13
+ return "deno";
14
+ }
15
+ if (typeof process !== "undefined" && process.versions?.node) {
16
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
17
+ return "react-native";
18
+ }
19
+ return "node";
20
+ }
21
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
22
+ return "react-native";
23
+ }
24
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
25
+ return "web";
26
+ }
27
+ return "node";
28
+ }
29
+ var platform = detectPlatform();
30
+ var isWeb = platform === "web";
31
+ var isReactNative = platform === "react-native";
32
+ var isNode = platform === "node";
33
+ var isDeno = platform === "deno";
34
+ var isBrowser = isWeb || isReactNative;
35
+ var isServer = isNode || isDeno;
36
+
10
37
  // ../core/src/storage-adapter.ts
11
38
  var WebStorageAdapter = class {
12
39
  getItem(key) {
@@ -92,6 +119,9 @@ var NoOpStorageAdapter = class {
92
119
  }
93
120
  };
94
121
  function getDefaultStorageAdapter() {
122
+ if (isDeno) {
123
+ return new NoOpStorageAdapter();
124
+ }
95
125
  if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
96
126
  try {
97
127
  localStorage.setItem("__test__", "test");
@@ -103,28 +133,6 @@ function getDefaultStorageAdapter() {
103
133
  return new NoOpStorageAdapter();
104
134
  }
105
135
 
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
-
128
136
  // ../core/src/types.ts
129
137
  var BlinkError = class extends Error {
130
138
  constructor(message, code, status, details) {
@@ -391,32 +399,65 @@ var HttpClient = class {
391
399
  authUrl = "https://blink.new";
392
400
  coreUrl = "https://core.blink.new";
393
401
  projectId;
402
+ publishableKey;
403
+ secretKey;
404
+ // Permanent, non-expiring key (like Stripe's sk_live_...)
394
405
  getToken;
395
406
  getValidToken;
396
407
  constructor(config, getToken, getValidToken) {
397
408
  this.projectId = config.projectId;
409
+ this.publishableKey = config.publishableKey;
410
+ this.secretKey = config.secretKey || config.serviceToken;
398
411
  this.getToken = getToken;
399
412
  this.getValidToken = getValidToken;
400
413
  }
414
+ shouldAttachPublishableKey(path, method) {
415
+ if (method !== "GET" && method !== "POST") return false;
416
+ if (path.includes("/api/analytics/")) return true;
417
+ if (path.includes("/api/storage/")) return true;
418
+ if (path.includes("/api/db/") && path.includes("/rest/v1/")) return method === "GET";
419
+ return false;
420
+ }
421
+ shouldSkipSecretKey(url) {
422
+ try {
423
+ const parsed = new URL(url);
424
+ return parsed.hostname.endsWith(".functions.blink.new");
425
+ } catch {
426
+ return false;
427
+ }
428
+ }
429
+ getAuthorizationHeader(url, token) {
430
+ if (this.secretKey && !this.shouldSkipSecretKey(url)) {
431
+ return `Bearer ${this.secretKey}`;
432
+ }
433
+ if (token) {
434
+ return `Bearer ${token}`;
435
+ }
436
+ return null;
437
+ }
401
438
  /**
402
439
  * Make an authenticated request to the Blink API
403
440
  */
404
441
  async request(path, options = {}) {
405
442
  const url = this.buildUrl(path, options.searchParams);
406
443
  const token = this.getValidToken ? await this.getValidToken() : this.getToken();
444
+ const method = options.method || "GET";
407
445
  const headers = {
408
446
  "Content-Type": "application/json",
409
447
  ...options.headers
410
448
  };
411
- if (token) {
412
- headers.Authorization = `Bearer ${token}`;
449
+ const auth = this.getAuthorizationHeader(url, token);
450
+ if (auth) {
451
+ headers.Authorization = auth;
452
+ } else if (this.publishableKey && !headers["x-blink-publishable-key"] && this.shouldAttachPublishableKey(path, method)) {
453
+ headers["x-blink-publishable-key"] = this.publishableKey;
413
454
  }
414
455
  const requestInit = {
415
- method: options.method || "GET",
456
+ method,
416
457
  headers,
417
458
  signal: options.signal
418
459
  };
419
- if (options.body && options.method !== "GET") {
460
+ if (options.body && method !== "GET") {
420
461
  requestInit.body = typeof options.body === "string" ? options.body : JSON.stringify(options.body);
421
462
  }
422
463
  try {
@@ -570,12 +611,12 @@ var HttpClient = class {
570
611
  throw new BlinkValidationError("Unsupported file type");
571
612
  }
572
613
  formData.append("path", filePath);
573
- if (options.upsert !== void 0) {
574
- formData.append("options", JSON.stringify({ upsert: options.upsert }));
575
- }
576
614
  const headers = {};
577
- if (token) {
578
- headers.Authorization = `Bearer ${token}`;
615
+ const auth = this.getAuthorizationHeader(url, token);
616
+ if (auth) {
617
+ headers.Authorization = auth;
618
+ } else if (this.publishableKey && path.includes("/api/storage/") && !headers["x-blink-publishable-key"]) {
619
+ headers["x-blink-publishable-key"] = this.publishableKey;
579
620
  }
580
621
  try {
581
622
  if (typeof XMLHttpRequest !== "undefined" && options.onProgress) {
@@ -684,9 +725,8 @@ var HttpClient = class {
684
725
  const headers = {
685
726
  "Content-Type": "application/json"
686
727
  };
687
- if (token) {
688
- headers.Authorization = `Bearer ${token}`;
689
- }
728
+ const auth = this.getAuthorizationHeader(url, token);
729
+ if (auth) headers.Authorization = auth;
690
730
  const body = {
691
731
  prompt,
692
732
  stream: true,
@@ -739,9 +779,8 @@ var HttpClient = class {
739
779
  const headers = {
740
780
  "Content-Type": "application/json"
741
781
  };
742
- if (token) {
743
- headers.Authorization = `Bearer ${token}`;
744
- }
782
+ const auth = this.getAuthorizationHeader(url, token);
783
+ if (auth) headers.Authorization = auth;
745
784
  const body = {
746
785
  prompt,
747
786
  stream: true,
@@ -2966,6 +3005,11 @@ var BlinkAuth = class {
2966
3005
  };
2967
3006
 
2968
3007
  // src/database.ts
3008
+ function assertServerOnly(methodName) {
3009
+ if (typeof window !== "undefined") {
3010
+ throw new Error(`${methodName} is server-only. Use Blink CRUD methods (blink.db.<table>.*) instead.`);
3011
+ }
3012
+ }
2969
3013
  function camelToSnake3(str) {
2970
3014
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
2971
3015
  }
@@ -3184,6 +3228,7 @@ var BlinkTable = class {
3184
3228
  * Raw SQL query on this table (for advanced use cases)
3185
3229
  */
3186
3230
  async sql(query, params) {
3231
+ assertServerOnly("blink.db.<table>.sql");
3187
3232
  const response = await this.httpClient.dbSql(query, params);
3188
3233
  return response.data;
3189
3234
  }
@@ -3232,6 +3277,7 @@ var BlinkDatabase = class {
3232
3277
  * Execute raw SQL query
3233
3278
  */
3234
3279
  async sql(query, params) {
3280
+ assertServerOnly("blink.db.sql");
3235
3281
  const response = await this.httpClient.dbSql(query, params);
3236
3282
  return response.data;
3237
3283
  }
@@ -3239,6 +3285,7 @@ var BlinkDatabase = class {
3239
3285
  * Execute batch SQL operations
3240
3286
  */
3241
3287
  async batch(statements, mode = "write") {
3288
+ assertServerOnly("blink.db.batch");
3242
3289
  const response = await this.httpClient.dbBatch(statements, mode);
3243
3290
  return response.data;
3244
3291
  }
@@ -3301,7 +3348,6 @@ var BlinkStorageImpl = class {
3301
3348
  correctedPath,
3302
3349
  // Use corrected path with proper extension
3303
3350
  {
3304
- upsert: options.upsert,
3305
3351
  onProgress: options.onProgress,
3306
3352
  contentType: detectedContentType
3307
3353
  // Pass detected content type
@@ -3321,7 +3367,7 @@ var BlinkStorageImpl = class {
3321
3367
  if (error instanceof Error && "status" in error) {
3322
3368
  const status = error.status;
3323
3369
  if (status === 409) {
3324
- throw new BlinkStorageError("File already exists. Set upsert: true to overwrite.", 409);
3370
+ throw new BlinkStorageError("File already exists.", 409);
3325
3371
  }
3326
3372
  if (status === 400) {
3327
3373
  throw new BlinkStorageError("Invalid request parameters", 400);
@@ -3366,7 +3412,6 @@ var BlinkStorageImpl = class {
3366
3412
  detectedContentType
3367
3413
  };
3368
3414
  } catch (error) {
3369
- console.warn("File type detection failed, using original path:", error);
3370
3415
  return {
3371
3416
  correctedPath: originalPath,
3372
3417
  detectedContentType: "application/octet-stream"
@@ -5292,7 +5337,6 @@ var BlinkAnalyticsImpl = class {
5292
5337
  } catch (error) {
5293
5338
  this.queue = [...events, ...this.queue];
5294
5339
  this.persistQueue();
5295
- console.error("Failed to send analytics events:", error);
5296
5340
  }
5297
5341
  if (this.queue.length > 0) {
5298
5342
  this.timer = setTimeout(() => this.flush(), BATCH_TIMEOUT);
@@ -5483,6 +5527,45 @@ var BlinkAnalyticsImpl = class {
5483
5527
  }
5484
5528
  };
5485
5529
 
5530
+ // src/functions.ts
5531
+ var BlinkFunctionsImpl = class {
5532
+ httpClient;
5533
+ projectId;
5534
+ constructor(httpClient, projectId, _getToken) {
5535
+ this.httpClient = httpClient;
5536
+ this.projectId = projectId;
5537
+ }
5538
+ /**
5539
+ * Get the project suffix from the full project ID.
5540
+ * Project IDs are formatted as: prj_xxxxx
5541
+ * The suffix is the last 8 characters used in function URLs.
5542
+ */
5543
+ getProjectSuffix() {
5544
+ return this.projectId.slice(-8);
5545
+ }
5546
+ /**
5547
+ * Build the full function URL
5548
+ */
5549
+ buildFunctionUrl(functionSlug, searchParams) {
5550
+ const suffix = this.getProjectSuffix();
5551
+ const baseUrl = `https://${suffix}--${functionSlug}.functions.blink.new`;
5552
+ if (!searchParams || Object.keys(searchParams).length === 0) {
5553
+ return baseUrl;
5554
+ }
5555
+ const url = new URL(baseUrl);
5556
+ Object.entries(searchParams).forEach(([key, value]) => {
5557
+ url.searchParams.set(key, value);
5558
+ });
5559
+ return url.toString();
5560
+ }
5561
+ async invoke(functionSlug, options = {}) {
5562
+ const { method = "POST", body, headers = {}, searchParams } = options;
5563
+ const url = this.buildFunctionUrl(functionSlug, searchParams);
5564
+ const res = await this.httpClient.request(url, { method, body, headers });
5565
+ return { data: res.data, status: res.status, headers: res.headers };
5566
+ }
5567
+ };
5568
+
5486
5569
  // src/client.ts
5487
5570
  var BlinkClientImpl = class {
5488
5571
  auth;
@@ -5493,8 +5576,12 @@ var BlinkClientImpl = class {
5493
5576
  realtime;
5494
5577
  notifications;
5495
5578
  analytics;
5579
+ functions;
5496
5580
  httpClient;
5497
5581
  constructor(config) {
5582
+ if ((config.secretKey || config.serviceToken) && isBrowser) {
5583
+ throw new Error("secretKey/serviceToken is server-only. Do not provide it in browser/React Native clients.");
5584
+ }
5498
5585
  this.auth = new BlinkAuth(config);
5499
5586
  this.httpClient = new HttpClient(
5500
5587
  config,
@@ -5508,6 +5595,11 @@ var BlinkClientImpl = class {
5508
5595
  this.realtime = new BlinkRealtimeImpl(this.httpClient, config.projectId);
5509
5596
  this.notifications = new BlinkNotificationsImpl(this.httpClient);
5510
5597
  this.analytics = new BlinkAnalyticsImpl(this.httpClient, config.projectId);
5598
+ this.functions = new BlinkFunctionsImpl(
5599
+ this.httpClient,
5600
+ config.projectId,
5601
+ () => this.auth.getValidToken()
5602
+ );
5511
5603
  this.auth.onAuthStateChanged((state) => {
5512
5604
  if (state.isAuthenticated && state.user) {
5513
5605
  this.analytics.setUserId(state.user.id);
@@ -5540,8 +5632,10 @@ exports.WebStorageAdapter = WebStorageAdapter;
5540
5632
  exports.createClient = createClient;
5541
5633
  exports.getDefaultStorageAdapter = getDefaultStorageAdapter;
5542
5634
  exports.isBrowser = isBrowser;
5635
+ exports.isDeno = isDeno;
5543
5636
  exports.isNode = isNode;
5544
5637
  exports.isReactNative = isReactNative;
5638
+ exports.isServer = isServer;
5545
5639
  exports.isWeb = isWeb;
5546
5640
  exports.platform = platform;
5547
5641
  //# sourceMappingURL=index.js.map
package/dist/index.mjs CHANGED
@@ -5,6 +5,33 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
+ // ../core/src/platform.ts
9
+ function detectPlatform() {
10
+ if (typeof Deno !== "undefined") {
11
+ return "deno";
12
+ }
13
+ if (typeof process !== "undefined" && process.versions?.node) {
14
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
15
+ return "react-native";
16
+ }
17
+ return "node";
18
+ }
19
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
20
+ return "react-native";
21
+ }
22
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
23
+ return "web";
24
+ }
25
+ return "node";
26
+ }
27
+ var platform = detectPlatform();
28
+ var isWeb = platform === "web";
29
+ var isReactNative = platform === "react-native";
30
+ var isNode = platform === "node";
31
+ var isDeno = platform === "deno";
32
+ var isBrowser = isWeb || isReactNative;
33
+ var isServer = isNode || isDeno;
34
+
8
35
  // ../core/src/storage-adapter.ts
9
36
  var WebStorageAdapter = class {
10
37
  getItem(key) {
@@ -90,6 +117,9 @@ var NoOpStorageAdapter = class {
90
117
  }
91
118
  };
92
119
  function getDefaultStorageAdapter() {
120
+ if (isDeno) {
121
+ return new NoOpStorageAdapter();
122
+ }
93
123
  if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
94
124
  try {
95
125
  localStorage.setItem("__test__", "test");
@@ -101,28 +131,6 @@ function getDefaultStorageAdapter() {
101
131
  return new NoOpStorageAdapter();
102
132
  }
103
133
 
104
- // ../core/src/platform.ts
105
- function detectPlatform() {
106
- if (typeof process !== "undefined" && process.versions?.node) {
107
- if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
108
- return "react-native";
109
- }
110
- return "node";
111
- }
112
- if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
113
- return "react-native";
114
- }
115
- if (typeof window !== "undefined" && typeof document !== "undefined") {
116
- return "web";
117
- }
118
- return "node";
119
- }
120
- var platform = detectPlatform();
121
- var isWeb = platform === "web";
122
- var isReactNative = platform === "react-native";
123
- var isNode = platform === "node";
124
- var isBrowser = isWeb || isReactNative;
125
-
126
134
  // ../core/src/types.ts
127
135
  var BlinkError = class extends Error {
128
136
  constructor(message, code, status, details) {
@@ -389,32 +397,65 @@ var HttpClient = class {
389
397
  authUrl = "https://blink.new";
390
398
  coreUrl = "https://core.blink.new";
391
399
  projectId;
400
+ publishableKey;
401
+ secretKey;
402
+ // Permanent, non-expiring key (like Stripe's sk_live_...)
392
403
  getToken;
393
404
  getValidToken;
394
405
  constructor(config, getToken, getValidToken) {
395
406
  this.projectId = config.projectId;
407
+ this.publishableKey = config.publishableKey;
408
+ this.secretKey = config.secretKey || config.serviceToken;
396
409
  this.getToken = getToken;
397
410
  this.getValidToken = getValidToken;
398
411
  }
412
+ shouldAttachPublishableKey(path, method) {
413
+ if (method !== "GET" && method !== "POST") return false;
414
+ if (path.includes("/api/analytics/")) return true;
415
+ if (path.includes("/api/storage/")) return true;
416
+ if (path.includes("/api/db/") && path.includes("/rest/v1/")) return method === "GET";
417
+ return false;
418
+ }
419
+ shouldSkipSecretKey(url) {
420
+ try {
421
+ const parsed = new URL(url);
422
+ return parsed.hostname.endsWith(".functions.blink.new");
423
+ } catch {
424
+ return false;
425
+ }
426
+ }
427
+ getAuthorizationHeader(url, token) {
428
+ if (this.secretKey && !this.shouldSkipSecretKey(url)) {
429
+ return `Bearer ${this.secretKey}`;
430
+ }
431
+ if (token) {
432
+ return `Bearer ${token}`;
433
+ }
434
+ return null;
435
+ }
399
436
  /**
400
437
  * Make an authenticated request to the Blink API
401
438
  */
402
439
  async request(path, options = {}) {
403
440
  const url = this.buildUrl(path, options.searchParams);
404
441
  const token = this.getValidToken ? await this.getValidToken() : this.getToken();
442
+ const method = options.method || "GET";
405
443
  const headers = {
406
444
  "Content-Type": "application/json",
407
445
  ...options.headers
408
446
  };
409
- if (token) {
410
- headers.Authorization = `Bearer ${token}`;
447
+ const auth = this.getAuthorizationHeader(url, token);
448
+ if (auth) {
449
+ headers.Authorization = auth;
450
+ } else if (this.publishableKey && !headers["x-blink-publishable-key"] && this.shouldAttachPublishableKey(path, method)) {
451
+ headers["x-blink-publishable-key"] = this.publishableKey;
411
452
  }
412
453
  const requestInit = {
413
- method: options.method || "GET",
454
+ method,
414
455
  headers,
415
456
  signal: options.signal
416
457
  };
417
- if (options.body && options.method !== "GET") {
458
+ if (options.body && method !== "GET") {
418
459
  requestInit.body = typeof options.body === "string" ? options.body : JSON.stringify(options.body);
419
460
  }
420
461
  try {
@@ -568,12 +609,12 @@ var HttpClient = class {
568
609
  throw new BlinkValidationError("Unsupported file type");
569
610
  }
570
611
  formData.append("path", filePath);
571
- if (options.upsert !== void 0) {
572
- formData.append("options", JSON.stringify({ upsert: options.upsert }));
573
- }
574
612
  const headers = {};
575
- if (token) {
576
- headers.Authorization = `Bearer ${token}`;
613
+ const auth = this.getAuthorizationHeader(url, token);
614
+ if (auth) {
615
+ headers.Authorization = auth;
616
+ } else if (this.publishableKey && path.includes("/api/storage/") && !headers["x-blink-publishable-key"]) {
617
+ headers["x-blink-publishable-key"] = this.publishableKey;
577
618
  }
578
619
  try {
579
620
  if (typeof XMLHttpRequest !== "undefined" && options.onProgress) {
@@ -682,9 +723,8 @@ var HttpClient = class {
682
723
  const headers = {
683
724
  "Content-Type": "application/json"
684
725
  };
685
- if (token) {
686
- headers.Authorization = `Bearer ${token}`;
687
- }
726
+ const auth = this.getAuthorizationHeader(url, token);
727
+ if (auth) headers.Authorization = auth;
688
728
  const body = {
689
729
  prompt,
690
730
  stream: true,
@@ -737,9 +777,8 @@ var HttpClient = class {
737
777
  const headers = {
738
778
  "Content-Type": "application/json"
739
779
  };
740
- if (token) {
741
- headers.Authorization = `Bearer ${token}`;
742
- }
780
+ const auth = this.getAuthorizationHeader(url, token);
781
+ if (auth) headers.Authorization = auth;
743
782
  const body = {
744
783
  prompt,
745
784
  stream: true,
@@ -2964,6 +3003,11 @@ var BlinkAuth = class {
2964
3003
  };
2965
3004
 
2966
3005
  // src/database.ts
3006
+ function assertServerOnly(methodName) {
3007
+ if (typeof window !== "undefined") {
3008
+ throw new Error(`${methodName} is server-only. Use Blink CRUD methods (blink.db.<table>.*) instead.`);
3009
+ }
3010
+ }
2967
3011
  function camelToSnake3(str) {
2968
3012
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
2969
3013
  }
@@ -3182,6 +3226,7 @@ var BlinkTable = class {
3182
3226
  * Raw SQL query on this table (for advanced use cases)
3183
3227
  */
3184
3228
  async sql(query, params) {
3229
+ assertServerOnly("blink.db.<table>.sql");
3185
3230
  const response = await this.httpClient.dbSql(query, params);
3186
3231
  return response.data;
3187
3232
  }
@@ -3230,6 +3275,7 @@ var BlinkDatabase = class {
3230
3275
  * Execute raw SQL query
3231
3276
  */
3232
3277
  async sql(query, params) {
3278
+ assertServerOnly("blink.db.sql");
3233
3279
  const response = await this.httpClient.dbSql(query, params);
3234
3280
  return response.data;
3235
3281
  }
@@ -3237,6 +3283,7 @@ var BlinkDatabase = class {
3237
3283
  * Execute batch SQL operations
3238
3284
  */
3239
3285
  async batch(statements, mode = "write") {
3286
+ assertServerOnly("blink.db.batch");
3240
3287
  const response = await this.httpClient.dbBatch(statements, mode);
3241
3288
  return response.data;
3242
3289
  }
@@ -3299,7 +3346,6 @@ var BlinkStorageImpl = class {
3299
3346
  correctedPath,
3300
3347
  // Use corrected path with proper extension
3301
3348
  {
3302
- upsert: options.upsert,
3303
3349
  onProgress: options.onProgress,
3304
3350
  contentType: detectedContentType
3305
3351
  // Pass detected content type
@@ -3319,7 +3365,7 @@ var BlinkStorageImpl = class {
3319
3365
  if (error instanceof Error && "status" in error) {
3320
3366
  const status = error.status;
3321
3367
  if (status === 409) {
3322
- throw new BlinkStorageError("File already exists. Set upsert: true to overwrite.", 409);
3368
+ throw new BlinkStorageError("File already exists.", 409);
3323
3369
  }
3324
3370
  if (status === 400) {
3325
3371
  throw new BlinkStorageError("Invalid request parameters", 400);
@@ -3364,7 +3410,6 @@ var BlinkStorageImpl = class {
3364
3410
  detectedContentType
3365
3411
  };
3366
3412
  } catch (error) {
3367
- console.warn("File type detection failed, using original path:", error);
3368
3413
  return {
3369
3414
  correctedPath: originalPath,
3370
3415
  detectedContentType: "application/octet-stream"
@@ -5290,7 +5335,6 @@ var BlinkAnalyticsImpl = class {
5290
5335
  } catch (error) {
5291
5336
  this.queue = [...events, ...this.queue];
5292
5337
  this.persistQueue();
5293
- console.error("Failed to send analytics events:", error);
5294
5338
  }
5295
5339
  if (this.queue.length > 0) {
5296
5340
  this.timer = setTimeout(() => this.flush(), BATCH_TIMEOUT);
@@ -5481,6 +5525,45 @@ var BlinkAnalyticsImpl = class {
5481
5525
  }
5482
5526
  };
5483
5527
 
5528
+ // src/functions.ts
5529
+ var BlinkFunctionsImpl = class {
5530
+ httpClient;
5531
+ projectId;
5532
+ constructor(httpClient, projectId, _getToken) {
5533
+ this.httpClient = httpClient;
5534
+ this.projectId = projectId;
5535
+ }
5536
+ /**
5537
+ * Get the project suffix from the full project ID.
5538
+ * Project IDs are formatted as: prj_xxxxx
5539
+ * The suffix is the last 8 characters used in function URLs.
5540
+ */
5541
+ getProjectSuffix() {
5542
+ return this.projectId.slice(-8);
5543
+ }
5544
+ /**
5545
+ * Build the full function URL
5546
+ */
5547
+ buildFunctionUrl(functionSlug, searchParams) {
5548
+ const suffix = this.getProjectSuffix();
5549
+ const baseUrl = `https://${suffix}--${functionSlug}.functions.blink.new`;
5550
+ if (!searchParams || Object.keys(searchParams).length === 0) {
5551
+ return baseUrl;
5552
+ }
5553
+ const url = new URL(baseUrl);
5554
+ Object.entries(searchParams).forEach(([key, value]) => {
5555
+ url.searchParams.set(key, value);
5556
+ });
5557
+ return url.toString();
5558
+ }
5559
+ async invoke(functionSlug, options = {}) {
5560
+ const { method = "POST", body, headers = {}, searchParams } = options;
5561
+ const url = this.buildFunctionUrl(functionSlug, searchParams);
5562
+ const res = await this.httpClient.request(url, { method, body, headers });
5563
+ return { data: res.data, status: res.status, headers: res.headers };
5564
+ }
5565
+ };
5566
+
5484
5567
  // src/client.ts
5485
5568
  var BlinkClientImpl = class {
5486
5569
  auth;
@@ -5491,8 +5574,12 @@ var BlinkClientImpl = class {
5491
5574
  realtime;
5492
5575
  notifications;
5493
5576
  analytics;
5577
+ functions;
5494
5578
  httpClient;
5495
5579
  constructor(config) {
5580
+ if ((config.secretKey || config.serviceToken) && isBrowser) {
5581
+ throw new Error("secretKey/serviceToken is server-only. Do not provide it in browser/React Native clients.");
5582
+ }
5496
5583
  this.auth = new BlinkAuth(config);
5497
5584
  this.httpClient = new HttpClient(
5498
5585
  config,
@@ -5506,6 +5593,11 @@ var BlinkClientImpl = class {
5506
5593
  this.realtime = new BlinkRealtimeImpl(this.httpClient, config.projectId);
5507
5594
  this.notifications = new BlinkNotificationsImpl(this.httpClient);
5508
5595
  this.analytics = new BlinkAnalyticsImpl(this.httpClient, config.projectId);
5596
+ this.functions = new BlinkFunctionsImpl(
5597
+ this.httpClient,
5598
+ config.projectId,
5599
+ () => this.auth.getValidToken()
5600
+ );
5509
5601
  this.auth.onAuthStateChanged((state) => {
5510
5602
  if (state.isAuthenticated && state.user) {
5511
5603
  this.analytics.setUserId(state.user.id);
@@ -5524,6 +5616,6 @@ function createClient(config) {
5524
5616
  return new BlinkClientImpl(config);
5525
5617
  }
5526
5618
 
5527
- export { AsyncStorageAdapter, BlinkAIImpl, BlinkAnalyticsImpl, BlinkDataImpl, BlinkDatabase, BlinkRealtimeChannel, BlinkRealtimeImpl, BlinkStorageImpl, BlinkTable, NoOpStorageAdapter, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isNode, isReactNative, isWeb, platform };
5619
+ export { AsyncStorageAdapter, BlinkAIImpl, BlinkAnalyticsImpl, BlinkDataImpl, BlinkDatabase, BlinkRealtimeChannel, BlinkRealtimeImpl, BlinkStorageImpl, BlinkTable, NoOpStorageAdapter, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isDeno, isNode, isReactNative, isServer, isWeb, platform };
5528
5620
  //# sourceMappingURL=index.mjs.map
5529
5621
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blinkdotnew/sdk",
3
- "version": "2.0.3",
3
+ "version": "2.1.1",
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",
@@ -46,7 +46,8 @@
46
46
  "build": "tsup",
47
47
  "dev": "tsup --watch",
48
48
  "type-check": "tsc --noEmit",
49
- "clean": "rm -rf dist"
49
+ "clean": "rm -rf dist",
50
+ "prepublishOnly": "npm run build"
50
51
  },
51
52
  "dependencies": {},
52
53
  "devDependencies": {