@blinkdotnew/sdk 2.5.1 → 2.6.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
@@ -310,8 +310,8 @@ interface TableOperations<T = any> {
310
310
  declare class BlinkError extends Error {
311
311
  code?: string | undefined;
312
312
  status?: number | undefined;
313
- details?: any;
314
- constructor(message: string, code?: string | undefined, status?: number | undefined, details?: any);
313
+ details?: any | undefined;
314
+ constructor(message: string, code?: string | undefined, status?: number | undefined, details?: any | undefined);
315
315
  }
316
316
  interface StorageUploadOptions {
317
317
  /**
@@ -798,6 +798,32 @@ interface SendEmailRequest {
798
798
  subject: string;
799
799
  html?: string;
800
800
  text?: string;
801
+ /**
802
+ * Pick which sender this email goes out from.
803
+ *
804
+ * Two accepted shapes — the server disambiguates by whether the value
805
+ * contains an `@` character:
806
+ * - **Full address** (any string containing `@`, e.g.
807
+ * `"support@mail.acme.com"`) — sends from that specific verified
808
+ * sender. The address must be set up in Settings → Email beforehand;
809
+ * unverified addresses are rejected by the server with HTTP 403. On
810
+ * the SDK side this surfaces as a `BlinkNotificationsError` whose
811
+ * `.status === 403` and `.details?.code === 'UNVERIFIED_SENDER'` —
812
+ * the SDK-level `.code` is always `'NOTIFICATIONS_ERROR'`, so branch
813
+ * on `.status` + `.details` (not `.code`) to detect this case.
814
+ * - **Display name** (any string without `@`, e.g. `"Acme Support"`) —
815
+ * keeps the project's default sender address but overrides the
816
+ * visible name in the recipient's inbox. Useful for tagging different
817
+ * message types ("Acme Receipts", "Acme Updates") without verifying
818
+ * more senders.
819
+ *
820
+ * A display name MUST NOT contain `@`. If it does, the server interprets
821
+ * it as a sending address and rejects with 403 `UNVERIFIED_SENDER`.
822
+ *
823
+ * Omit to use the project's default sender (the one flagged "Default"
824
+ * in Settings → Email — same one auth emails like password reset and
825
+ * magic links use).
826
+ */
801
827
  from?: string;
802
828
  replyTo?: string;
803
829
  cc?: string | string[];
@@ -915,7 +941,17 @@ declare class HttpClient {
915
941
  private readonly secretKey?;
916
942
  private getToken;
917
943
  private getValidToken?;
918
- constructor(config: BlinkClientConfig, getToken: () => string | null, getValidToken?: () => Promise<string | null>);
944
+ private forceRefreshToken?;
945
+ constructor(config: BlinkClientConfig, getToken: () => string | null, getValidToken?: () => Promise<string | null>, forceRefreshToken?: () => Promise<string | null>);
946
+ /**
947
+ * Whether a 401 on this request is worth recovering from by forcing a
948
+ * user-token refresh and retrying once.
949
+ *
950
+ * Only meaningful for user-JWT auth: server-side `secretKey` 401s are real
951
+ * authorization failures a refresh cannot fix, and publishable-key requests
952
+ * carry no user token to refresh.
953
+ */
954
+ private canAttemptTokenRefresh;
919
955
  private shouldAttachPublishableKey;
920
956
  private shouldSkipSecretKey;
921
957
  private getAuthorizationHeader;
@@ -1007,17 +1043,17 @@ declare class HttpClient {
1007
1043
  * Stream AI text generation - uses Vercel AI SDK's pipeUIMessageStreamToResponse (Data Stream Protocol)
1008
1044
  */
1009
1045
  streamAiText(prompt: string, options: {
1010
- model?: string | undefined;
1011
- messages?: {
1046
+ model?: string;
1047
+ messages?: Array<{
1012
1048
  role: string;
1013
1049
  content: string | any[];
1014
- }[] | undefined;
1015
- search?: boolean | undefined;
1016
- maxSteps?: number | undefined;
1017
- experimental_continueSteps?: boolean | undefined;
1018
- maxTokens?: number | undefined;
1019
- temperature?: number | undefined;
1020
- signal?: AbortSignal | undefined;
1050
+ }>;
1051
+ search?: boolean;
1052
+ maxSteps?: number;
1053
+ experimental_continueSteps?: boolean;
1054
+ maxTokens?: number;
1055
+ temperature?: number;
1056
+ signal?: AbortSignal;
1021
1057
  } | undefined, onChunk: (chunk: string) => void): Promise<any>;
1022
1058
  aiObject(prompt: string, options?: {
1023
1059
  model?: string;
@@ -1031,11 +1067,11 @@ declare class HttpClient {
1031
1067
  * Stream AI object generation - uses Vercel AI SDK's pipeTextStreamToResponse
1032
1068
  */
1033
1069
  streamAiObject(prompt: string, options: {
1034
- model?: string | undefined;
1035
- output?: "object" | "array" | "enum" | undefined;
1070
+ model?: string;
1071
+ output?: "object" | "array" | "enum";
1036
1072
  schema?: any;
1037
- enum?: string[] | undefined;
1038
- signal?: AbortSignal | undefined;
1073
+ enum?: string[];
1074
+ signal?: AbortSignal;
1039
1075
  } | undefined, onPartial: (partial: any) => void): Promise<any>;
1040
1076
  aiImage(prompt: string, options?: {
1041
1077
  model?: string;
@@ -1259,6 +1295,7 @@ declare class BlinkAuth {
1259
1295
  private initializationPromise;
1260
1296
  private isInitialized;
1261
1297
  private storage;
1298
+ private refreshPromise;
1262
1299
  constructor(config: BlinkClientConfig);
1263
1300
  /**
1264
1301
  * Generate project-scoped storage key
@@ -1646,6 +1683,18 @@ declare class BlinkAuth {
1646
1683
  * Refresh access token using refresh token
1647
1684
  */
1648
1685
  refreshToken(): Promise<boolean>;
1686
+ /**
1687
+ * Force a server-side token refresh and return the resulting access token.
1688
+ *
1689
+ * Used by the HTTP client to recover from a 401 even when the client-side
1690
+ * expiry heuristics believe the access token is still valid (clock skew, a
1691
+ * restored session with a stale `issued_at`, or a refresh race). Delegates to
1692
+ * {@link refreshToken} so it shares the single-flight guard.
1693
+ *
1694
+ * @returns The new access token, or null if refresh was not possible.
1695
+ */
1696
+ forceRefreshAccessToken(): Promise<string | null>;
1697
+ private performTokenRefresh;
1649
1698
  /**
1650
1699
  * Add auth state change listener
1651
1700
  */
package/dist/index.d.ts CHANGED
@@ -310,8 +310,8 @@ interface TableOperations<T = any> {
310
310
  declare class BlinkError extends Error {
311
311
  code?: string | undefined;
312
312
  status?: number | undefined;
313
- details?: any;
314
- constructor(message: string, code?: string | undefined, status?: number | undefined, details?: any);
313
+ details?: any | undefined;
314
+ constructor(message: string, code?: string | undefined, status?: number | undefined, details?: any | undefined);
315
315
  }
316
316
  interface StorageUploadOptions {
317
317
  /**
@@ -798,6 +798,32 @@ interface SendEmailRequest {
798
798
  subject: string;
799
799
  html?: string;
800
800
  text?: string;
801
+ /**
802
+ * Pick which sender this email goes out from.
803
+ *
804
+ * Two accepted shapes — the server disambiguates by whether the value
805
+ * contains an `@` character:
806
+ * - **Full address** (any string containing `@`, e.g.
807
+ * `"support@mail.acme.com"`) — sends from that specific verified
808
+ * sender. The address must be set up in Settings → Email beforehand;
809
+ * unverified addresses are rejected by the server with HTTP 403. On
810
+ * the SDK side this surfaces as a `BlinkNotificationsError` whose
811
+ * `.status === 403` and `.details?.code === 'UNVERIFIED_SENDER'` —
812
+ * the SDK-level `.code` is always `'NOTIFICATIONS_ERROR'`, so branch
813
+ * on `.status` + `.details` (not `.code`) to detect this case.
814
+ * - **Display name** (any string without `@`, e.g. `"Acme Support"`) —
815
+ * keeps the project's default sender address but overrides the
816
+ * visible name in the recipient's inbox. Useful for tagging different
817
+ * message types ("Acme Receipts", "Acme Updates") without verifying
818
+ * more senders.
819
+ *
820
+ * A display name MUST NOT contain `@`. If it does, the server interprets
821
+ * it as a sending address and rejects with 403 `UNVERIFIED_SENDER`.
822
+ *
823
+ * Omit to use the project's default sender (the one flagged "Default"
824
+ * in Settings → Email — same one auth emails like password reset and
825
+ * magic links use).
826
+ */
801
827
  from?: string;
802
828
  replyTo?: string;
803
829
  cc?: string | string[];
@@ -915,7 +941,17 @@ declare class HttpClient {
915
941
  private readonly secretKey?;
916
942
  private getToken;
917
943
  private getValidToken?;
918
- constructor(config: BlinkClientConfig, getToken: () => string | null, getValidToken?: () => Promise<string | null>);
944
+ private forceRefreshToken?;
945
+ constructor(config: BlinkClientConfig, getToken: () => string | null, getValidToken?: () => Promise<string | null>, forceRefreshToken?: () => Promise<string | null>);
946
+ /**
947
+ * Whether a 401 on this request is worth recovering from by forcing a
948
+ * user-token refresh and retrying once.
949
+ *
950
+ * Only meaningful for user-JWT auth: server-side `secretKey` 401s are real
951
+ * authorization failures a refresh cannot fix, and publishable-key requests
952
+ * carry no user token to refresh.
953
+ */
954
+ private canAttemptTokenRefresh;
919
955
  private shouldAttachPublishableKey;
920
956
  private shouldSkipSecretKey;
921
957
  private getAuthorizationHeader;
@@ -1007,17 +1043,17 @@ declare class HttpClient {
1007
1043
  * Stream AI text generation - uses Vercel AI SDK's pipeUIMessageStreamToResponse (Data Stream Protocol)
1008
1044
  */
1009
1045
  streamAiText(prompt: string, options: {
1010
- model?: string | undefined;
1011
- messages?: {
1046
+ model?: string;
1047
+ messages?: Array<{
1012
1048
  role: string;
1013
1049
  content: string | any[];
1014
- }[] | undefined;
1015
- search?: boolean | undefined;
1016
- maxSteps?: number | undefined;
1017
- experimental_continueSteps?: boolean | undefined;
1018
- maxTokens?: number | undefined;
1019
- temperature?: number | undefined;
1020
- signal?: AbortSignal | undefined;
1050
+ }>;
1051
+ search?: boolean;
1052
+ maxSteps?: number;
1053
+ experimental_continueSteps?: boolean;
1054
+ maxTokens?: number;
1055
+ temperature?: number;
1056
+ signal?: AbortSignal;
1021
1057
  } | undefined, onChunk: (chunk: string) => void): Promise<any>;
1022
1058
  aiObject(prompt: string, options?: {
1023
1059
  model?: string;
@@ -1031,11 +1067,11 @@ declare class HttpClient {
1031
1067
  * Stream AI object generation - uses Vercel AI SDK's pipeTextStreamToResponse
1032
1068
  */
1033
1069
  streamAiObject(prompt: string, options: {
1034
- model?: string | undefined;
1035
- output?: "object" | "array" | "enum" | undefined;
1070
+ model?: string;
1071
+ output?: "object" | "array" | "enum";
1036
1072
  schema?: any;
1037
- enum?: string[] | undefined;
1038
- signal?: AbortSignal | undefined;
1073
+ enum?: string[];
1074
+ signal?: AbortSignal;
1039
1075
  } | undefined, onPartial: (partial: any) => void): Promise<any>;
1040
1076
  aiImage(prompt: string, options?: {
1041
1077
  model?: string;
@@ -1259,6 +1295,7 @@ declare class BlinkAuth {
1259
1295
  private initializationPromise;
1260
1296
  private isInitialized;
1261
1297
  private storage;
1298
+ private refreshPromise;
1262
1299
  constructor(config: BlinkClientConfig);
1263
1300
  /**
1264
1301
  * Generate project-scoped storage key
@@ -1646,6 +1683,18 @@ declare class BlinkAuth {
1646
1683
  * Refresh access token using refresh token
1647
1684
  */
1648
1685
  refreshToken(): Promise<boolean>;
1686
+ /**
1687
+ * Force a server-side token refresh and return the resulting access token.
1688
+ *
1689
+ * Used by the HTTP client to recover from a 401 even when the client-side
1690
+ * expiry heuristics believe the access token is still valid (clock skew, a
1691
+ * restored session with a stale `issued_at`, or a refresh race). Delegates to
1692
+ * {@link refreshToken} so it shares the single-flight guard.
1693
+ *
1694
+ * @returns The new access token, or null if refresh was not possible.
1695
+ */
1696
+ forceRefreshAccessToken(): Promise<string | null>;
1697
+ private performTokenRefresh;
1649
1698
  /**
1650
1699
  * Add auth state change listener
1651
1700
  */