@blocksdiy/blocks-client-sdk 1.17.2 → 1.18.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.
@@ -2,6 +2,7 @@ import { Action, type ActionConfig } from "./Action.js";
2
2
  import { Agent, type AgentConfig } from "./Agent.js";
3
3
  import { AgentChat, AgentChatConfig } from "./AgentChat.js";
4
4
  import { Entity, type EntityConfig } from "./Entity.js";
5
+ import { Integration } from "./Integration.js";
5
6
  import { Page, type PageConfig } from "./Page.js";
6
7
  /**
7
8
  * Represents a user's data
@@ -52,6 +53,7 @@ export interface ClientConfig {
52
53
  * - Agents: App agents generated from product-types
53
54
  * - AgentChat: Interact with the agent chat
54
55
  * - User: The user's data
56
+ * - Integrations: Which of the app's integrations are connected for whoever is viewing the app
55
57
  *
56
58
  * @class ClientSdk
57
59
  */
@@ -64,6 +66,9 @@ export declare class ClientSdk {
64
66
  private readonly pages;
65
67
  private readonly agentsMap;
66
68
  private readonly agentChats;
69
+ private readonly integrationsMap;
70
+ private integrationsSnapshot;
71
+ private integrationsLoad?;
67
72
  /**
68
73
  * Creates a new ClientSdk instance
69
74
  * @param {ClientConfig} config - Configuration options
@@ -194,6 +199,35 @@ export declare class ClientSdk {
194
199
  * ```
195
200
  */
196
201
  getUser(): User;
202
+ /**
203
+ * The app's integrations keyed by provider slug, as last loaded by `loadIntegrations()`
204
+ *
205
+ * Empty until the first load completes; a provider the app does not declare is `undefined`. An integration is
206
+ * connected when actions that use it can run for the viewer right now: the builder shared a connection with all
207
+ * users of the app, or the signed-in user connected their own, and it has not expired or been revoked. Optional
208
+ * integrations are never prompted for, so they are often not connected — use this to hide or disable the
209
+ * features that need them. For a visitor of a public app who is not signed in, only a shared connection counts.
210
+ *
211
+ * @returns {Readonly<Record<string, Integration | undefined>>} The loaded integrations
212
+ * @example
213
+ * ```ts
214
+ * await client.loadIntegrations();
215
+ * const canPostToSlack = client.integrations["slack"]?.isConnected ?? false;
216
+ * ```
217
+ */
218
+ get integrations(): Readonly<Record<string, Integration | undefined>>;
219
+ /**
220
+ * Fetches the connection status of every integration the app declares and stores it on the client
221
+ *
222
+ * Status is live — it changes when someone connects or disconnects an integration in the app's settings — so
223
+ * call this again to refresh. Concurrent calls share one request. An integration whose status did not change
224
+ * keeps its instance. If the fetch fails, the previously loaded integrations are kept.
225
+ *
226
+ * @returns {Promise<Readonly<Record<string, Integration | undefined>>>} The loaded integrations, same as `integrations`
227
+ * @throws {Error} If the status could not be fetched
228
+ */
229
+ loadIntegrations(): Promise<Readonly<Record<string, Integration | undefined>>>;
230
+ private fetchIntegrations;
197
231
  /**
198
232
  * Changes a user's role
199
233
  * @param userId - The user ID to change the role for
@@ -1 +1 @@
1
- {"version":3,"file":"ClientSdk.d.ts","sourceRoot":"","sources":["../src/ClientSdk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClientSdk.d.ts","sourceRoot":"","sources":["../src/ClientSdk.ts"],"names":[],"mappings":"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"}
package/dist/ClientSdk.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { DataApiService } from "@blocksdiy/blocks-client-api";
1
2
  import { AppVersionService } from "@blocksdiy/blocks-client-api/appVersionService";
2
3
  import { BlocksApiService } from "@blocksdiy/blocks-client-api/blocksStoreService";
3
4
  import { getGoogleBaseUrl, getHost } from "@blocksdiy/blocks-client-api/envService";
@@ -6,6 +7,7 @@ import { Agent } from "./Agent.js";
6
7
  import { AgentChat } from "./AgentChat.js";
7
8
  import { resolveAgentBlockId } from "./AgentRef.js";
8
9
  import { Entity } from "./Entity.js";
10
+ import { Integration } from "./Integration.js";
9
11
  import { Page } from "./Page.js";
10
12
  /**
11
13
  * Main client SDK for interacting with entities, actions, and pages
@@ -17,6 +19,7 @@ import { Page } from "./Page.js";
17
19
  * - Agents: App agents generated from product-types
18
20
  * - AgentChat: Interact with the agent chat
19
21
  * - User: The user's data
22
+ * - Integrations: Which of the app's integrations are connected for whoever is viewing the app
20
23
  *
21
24
  * @class ClientSdk
22
25
  */
@@ -29,6 +32,9 @@ export class ClientSdk {
29
32
  pages;
30
33
  agentsMap;
31
34
  agentChats;
35
+ integrationsMap;
36
+ integrationsSnapshot = Object.freeze({});
37
+ integrationsLoad;
32
38
  /**
33
39
  * Creates a new ClientSdk instance
34
40
  * @param {ClientConfig} config - Configuration options
@@ -45,6 +51,7 @@ export class ClientSdk {
45
51
  this.pages = new Map();
46
52
  this.agentsMap = new Map();
47
53
  this.agentChats = new Map();
54
+ this.integrationsMap = new Map();
48
55
  }
49
56
  async authenticate() {
50
57
  const headers = {
@@ -261,6 +268,58 @@ export class ClientSdk {
261
268
  getUser() {
262
269
  return this.user;
263
270
  }
271
+ /**
272
+ * The app's integrations keyed by provider slug, as last loaded by `loadIntegrations()`
273
+ *
274
+ * Empty until the first load completes; a provider the app does not declare is `undefined`. An integration is
275
+ * connected when actions that use it can run for the viewer right now: the builder shared a connection with all
276
+ * users of the app, or the signed-in user connected their own, and it has not expired or been revoked. Optional
277
+ * integrations are never prompted for, so they are often not connected — use this to hide or disable the
278
+ * features that need them. For a visitor of a public app who is not signed in, only a shared connection counts.
279
+ *
280
+ * @returns {Readonly<Record<string, Integration | undefined>>} The loaded integrations
281
+ * @example
282
+ * ```ts
283
+ * await client.loadIntegrations();
284
+ * const canPostToSlack = client.integrations["slack"]?.isConnected ?? false;
285
+ * ```
286
+ */
287
+ get integrations() {
288
+ return this.integrationsSnapshot;
289
+ }
290
+ /**
291
+ * Fetches the connection status of every integration the app declares and stores it on the client
292
+ *
293
+ * Status is live — it changes when someone connects or disconnects an integration in the app's settings — so
294
+ * call this again to refresh. Concurrent calls share one request. An integration whose status did not change
295
+ * keeps its instance. If the fetch fails, the previously loaded integrations are kept.
296
+ *
297
+ * @returns {Promise<Readonly<Record<string, Integration | undefined>>>} The loaded integrations, same as `integrations`
298
+ * @throws {Error} If the status could not be fetched
299
+ */
300
+ loadIntegrations() {
301
+ this.integrationsLoad ??= this.fetchIntegrations().finally(() => {
302
+ this.integrationsLoad = undefined;
303
+ });
304
+ return this.integrationsLoad;
305
+ }
306
+ async fetchIntegrations() {
307
+ const response = await new DataApiService({ appId: this.appId, token: this.token }).apiCall("GET", `/data-api/apps/${this.appId}/integrations/status`);
308
+ const { integrations = [] } = (await response.json());
309
+ const next = new Map();
310
+ for (const status of integrations) {
311
+ const current = this.integrationsMap.get(status.provider);
312
+ next.set(status.provider, current?.matches(status) ? current : new Integration(status));
313
+ }
314
+ const changed = next.size !== this.integrationsMap.size ||
315
+ [...next].some(([provider, integration]) => this.integrationsMap.get(provider) !== integration);
316
+ if (changed) {
317
+ this.integrationsMap.clear();
318
+ next.forEach((integration, provider) => this.integrationsMap.set(provider, integration));
319
+ this.integrationsSnapshot = Object.freeze(Object.fromEntries(this.integrationsMap));
320
+ }
321
+ return this.integrationsSnapshot;
322
+ }
264
323
  /**
265
324
  * Changes a user's role
266
325
  * @param userId - The user ID to change the role for
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Connection status of one of the app's integrations, as the platform reports it
3
+ * @interface IntegrationStatus
4
+ * @template P - The integration's provider slug
5
+ * @property {string} provider - The integration's provider slug, as declared on the app (e.g. "slack", "gmail")
6
+ * @property {boolean} connected - Whether actions that use this integration can run for the viewer right now
7
+ * @property {boolean} optional - Whether the app declares the integration as optional
8
+ */
9
+ export interface IntegrationStatus<P extends string = string> {
10
+ provider: P;
11
+ connected: boolean;
12
+ optional: boolean;
13
+ }
14
+ /**
15
+ * Integration class for one of the app's integrations, as seen by whoever is viewing the app
16
+ *
17
+ * An integration is connected when actions that use it can run for the viewer right now: the builder shared a
18
+ * connection with all users of the app, or the signed-in user connected their own, and it has not expired or been
19
+ * revoked. For a visitor of a public app who is not signed in, only a shared connection counts. Optional
20
+ * integrations are never prompted for, so they are often not connected.
21
+ *
22
+ * Instances are immutable snapshots: a refreshed status yields a new instance, so React sees the change.
23
+ *
24
+ * @class Integration
25
+ * @template P - The integration's provider slug
26
+ */
27
+ export declare class Integration<P extends string = string> {
28
+ private readonly _provider;
29
+ private readonly _connected;
30
+ private readonly _optional;
31
+ /**
32
+ * Creates a new Integration instance
33
+ * @param {IntegrationStatus<P>} status - The integration's status as reported by the platform
34
+ */
35
+ constructor(status: IntegrationStatus<P>);
36
+ /** The integration's provider slug, as declared on the app (e.g. "slack") */
37
+ get provider(): P;
38
+ /** Whether actions that use this integration can run for the viewer right now */
39
+ get isConnected(): boolean;
40
+ /** Whether the app declares the integration as optional: users are never prompted to connect it */
41
+ get isOptional(): boolean;
42
+ /** Whether `status` describes this integration exactly, so a refresh can keep this instance */
43
+ matches(status: IntegrationStatus): boolean;
44
+ toJSON(): IntegrationStatus<P>;
45
+ }
46
+ //# sourceMappingURL=Integration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Integration.d.ts","sourceRoot":"","sources":["../src/Integration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC1D,QAAQ,EAAE,CAAC,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAI;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IAEpC;;;OAGG;gBACS,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAMxC,6EAA6E;IAC7E,IAAI,QAAQ,IAAI,CAAC,CAEhB;IAED,iFAAiF;IACjF,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,mGAAmG;IACnG,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,+FAA+F;IAC/F,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO;IAM3C,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC;CAG/B"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Integration class for one of the app's integrations, as seen by whoever is viewing the app
3
+ *
4
+ * An integration is connected when actions that use it can run for the viewer right now: the builder shared a
5
+ * connection with all users of the app, or the signed-in user connected their own, and it has not expired or been
6
+ * revoked. For a visitor of a public app who is not signed in, only a shared connection counts. Optional
7
+ * integrations are never prompted for, so they are often not connected.
8
+ *
9
+ * Instances are immutable snapshots: a refreshed status yields a new instance, so React sees the change.
10
+ *
11
+ * @class Integration
12
+ * @template P - The integration's provider slug
13
+ */
14
+ export class Integration {
15
+ _provider;
16
+ _connected;
17
+ _optional;
18
+ /**
19
+ * Creates a new Integration instance
20
+ * @param {IntegrationStatus<P>} status - The integration's status as reported by the platform
21
+ */
22
+ constructor(status) {
23
+ this._provider = status.provider;
24
+ this._connected = status.connected;
25
+ this._optional = status.optional;
26
+ }
27
+ /** The integration's provider slug, as declared on the app (e.g. "slack") */
28
+ get provider() {
29
+ return this._provider;
30
+ }
31
+ /** Whether actions that use this integration can run for the viewer right now */
32
+ get isConnected() {
33
+ return this._connected;
34
+ }
35
+ /** Whether the app declares the integration as optional: users are never prompted to connect it */
36
+ get isOptional() {
37
+ return this._optional;
38
+ }
39
+ /** Whether `status` describes this integration exactly, so a refresh can keep this instance */
40
+ matches(status) {
41
+ return (status.provider === this._provider && status.connected === this._connected && status.optional === this._optional);
42
+ }
43
+ toJSON() {
44
+ return { provider: this._provider, connected: this._connected, optional: this._optional };
45
+ }
46
+ }
@@ -3,6 +3,7 @@ import type { AgentConfig } from "./Agent.js";
3
3
  import type { AgentChatConfig } from "./AgentChat.js";
4
4
  import { ClientSdk, UpdateUserOptions } from "./ClientSdk.js";
5
5
  import type { EntityAttribution, EntityConfig, EntityType, EntityTypeOnlyMutable } from "./Entity.js";
6
+ import type { Integration } from "./Integration.js";
6
7
  import type { PageConfig } from "./Page.js";
7
8
  export declare class ReactClientSdk extends ClientSdk {
8
9
  }
@@ -686,6 +687,78 @@ export declare const useFileUpload: () => {
686
687
  * ```
687
688
  */
688
689
  export declare const useUser: () => import("./ClientSdk.js").User;
690
+ /**
691
+ * Hook to get the connection status of one of the app's integrations for whoever is viewing the app
692
+ *
693
+ * Use it to render UI conditionally on an integration: hide or disable a feature whose integration is not
694
+ * connected, instead of letting its action fail. Optional integrations are never prompted for, so they are
695
+ * often not connected. An integration is connected when actions that use it can run for the viewer right now:
696
+ * a connection the builder shared with all users of the app, or the signed-in user's own, that has not expired
697
+ * or been revoked. A visitor of a public app who is not signed in has no connection of their own, so for them only
698
+ * shared connections count — gate UI the same way for both.
699
+ *
700
+ * `isConnected` is false while the status is loading, when it failed to load, and for a provider the app does not
701
+ * declare, so gated UI stays hidden until the integration is known to work. The status refreshes when the user
702
+ * returns to the app.
703
+ *
704
+ * @template P - The integration's provider slug, inferred from `provider`
705
+ * @param {P} provider - The integration's provider slug, as declared on the app (e.g. "slack")
706
+ * @returns {Object} Integration status
707
+ * @returns {boolean} isConnected - Whether actions that use the integration can run for the viewer right now
708
+ * @returns {Integration<P> | undefined} integration - `{ provider, isConnected, isOptional }`; undefined while loading,
709
+ * on error, and for a provider the app does not declare
710
+ * @returns {boolean} isLoading - True until the first status arrives
711
+ * @returns {Error | null} error - Set if the status could not be fetched
712
+ * @example
713
+ * ```tsx
714
+ * function ShareButtons({ report }) {
715
+ * const { isConnected: isSlackConnected } = useIntegrationStatus("slack");
716
+ * const { executeFunction: postToSlack } = useExecuteAction(PostReportToSlackAction);
717
+ *
718
+ * return (
719
+ * <div>
720
+ * <Button onClick={downloadReport}>Download</Button>
721
+ * {isSlackConnected && <Button onClick={() => postToSlack({ reportId: report.id })}>Post to Slack</Button>}
722
+ * </div>
723
+ * );
724
+ * }
725
+ * ```
726
+ */
727
+ export declare const useIntegrationStatus: <P extends string>(provider: P) => {
728
+ isConnected: boolean;
729
+ integration: Integration<P> | undefined;
730
+ isLoading: boolean;
731
+ error: Error | null;
732
+ };
733
+ /**
734
+ * Hook to get all of the app's integrations for whoever is viewing the app
735
+ *
736
+ * For gating on a single integration prefer `useIntegrationStatus(provider)`; use this when a component needs
737
+ * several, or lists them. Shares its state with `useIntegrationStatus` (it lives on `client.integrations`), so the
738
+ * status is fetched once. `isConnected` follows the same rules: false while loading, on error, and for undeclared
739
+ * providers.
740
+ *
741
+ * @returns {Object} Integrations
742
+ * @returns {Readonly<Record<string, Integration | undefined>>} integrations - Keyed by provider slug, e.g.
743
+ * `integrations["slack"]?.isConnected`; empty until loaded
744
+ * @returns {Function} isConnected - `(provider: string) => boolean`, e.g. `isConnected("slack")`
745
+ * @returns {boolean} isLoading - True until the first status arrives
746
+ * @returns {Error | null} error - Set if the status could not be fetched
747
+ * @example
748
+ * ```tsx
749
+ * function ConnectedIntegrations() {
750
+ * const { integrations } = useIntegrationsStatus();
751
+ * const connected = Object.entries(integrations).filter(([, integration]) => integration?.isConnected);
752
+ * return <ul>{connected.map(([provider]) => <li key={provider}>{provider}</li>)}</ul>;
753
+ * }
754
+ * ```
755
+ */
756
+ export declare const useIntegrationsStatus: () => {
757
+ integrations: Readonly<Record<string, Integration<string> | undefined>>;
758
+ isConnected: (provider: string) => boolean;
759
+ isLoading: boolean;
760
+ error: Error | null;
761
+ };
689
762
  /**
690
763
  * Hook to manage the application theme mode
691
764
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ReactClientSdk.d.ts","sourceRoot":"","sources":["../src/ReactClientSdk.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReactClientSdk.d.ts","sourceRoot":"","sources":["../src/ReactClientSdk.tsx"],"names":[],"mappings":"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"}
@@ -12,6 +12,10 @@ import { createEntityLiveSync } from "./EntityLiveSync.js";
12
12
  export class ReactClientSdk extends ClientSdk {
13
13
  }
14
14
  const CURRENT_USER_QUERY_KEY = "currentUser";
15
+ const INTEGRATIONS_QUERY_KEY = "integrations";
16
+ const EMPTY_INTEGRATIONS = Object.freeze({});
17
+ // Connecting happens outside the app (its settings, in the platform), so revisit on focus to pick it up.
18
+ const INTEGRATIONS_STALE_TIME = 30_000;
15
19
  // Avoids redundant refetches on quick remounts and window focus flaps without meaningfully delaying anything.
16
20
  const ENTITIES_STALE_TIME = 5_000;
17
21
  const ClientContext = createContext(null);
@@ -1072,6 +1076,88 @@ export const useUser = () => {
1072
1076
  });
1073
1077
  return user;
1074
1078
  };
1079
+ // One query per app: every integration hook shares it, so the status is fetched once however many mount. The
1080
+ // state itself lives on the client (`client.integrations`); the query triggers the first load and the refreshes.
1081
+ const useIntegrationsQuery = () => {
1082
+ const client = useClient();
1083
+ return useQuery({
1084
+ queryKey: [INTEGRATIONS_QUERY_KEY, client.appId],
1085
+ queryFn: () => client.loadIntegrations(),
1086
+ staleTime: INTEGRATIONS_STALE_TIME,
1087
+ refetchOnWindowFocus: true,
1088
+ });
1089
+ };
1090
+ /**
1091
+ * Hook to get the connection status of one of the app's integrations for whoever is viewing the app
1092
+ *
1093
+ * Use it to render UI conditionally on an integration: hide or disable a feature whose integration is not
1094
+ * connected, instead of letting its action fail. Optional integrations are never prompted for, so they are
1095
+ * often not connected. An integration is connected when actions that use it can run for the viewer right now:
1096
+ * a connection the builder shared with all users of the app, or the signed-in user's own, that has not expired
1097
+ * or been revoked. A visitor of a public app who is not signed in has no connection of their own, so for them only
1098
+ * shared connections count — gate UI the same way for both.
1099
+ *
1100
+ * `isConnected` is false while the status is loading, when it failed to load, and for a provider the app does not
1101
+ * declare, so gated UI stays hidden until the integration is known to work. The status refreshes when the user
1102
+ * returns to the app.
1103
+ *
1104
+ * @template P - The integration's provider slug, inferred from `provider`
1105
+ * @param {P} provider - The integration's provider slug, as declared on the app (e.g. "slack")
1106
+ * @returns {Object} Integration status
1107
+ * @returns {boolean} isConnected - Whether actions that use the integration can run for the viewer right now
1108
+ * @returns {Integration<P> | undefined} integration - `{ provider, isConnected, isOptional }`; undefined while loading,
1109
+ * on error, and for a provider the app does not declare
1110
+ * @returns {boolean} isLoading - True until the first status arrives
1111
+ * @returns {Error | null} error - Set if the status could not be fetched
1112
+ * @example
1113
+ * ```tsx
1114
+ * function ShareButtons({ report }) {
1115
+ * const { isConnected: isSlackConnected } = useIntegrationStatus("slack");
1116
+ * const { executeFunction: postToSlack } = useExecuteAction(PostReportToSlackAction);
1117
+ *
1118
+ * return (
1119
+ * <div>
1120
+ * <Button onClick={downloadReport}>Download</Button>
1121
+ * {isSlackConnected && <Button onClick={() => postToSlack({ reportId: report.id })}>Post to Slack</Button>}
1122
+ * </div>
1123
+ * );
1124
+ * }
1125
+ * ```
1126
+ */
1127
+ export const useIntegrationStatus = (provider) => {
1128
+ const { data, isLoading, error } = useIntegrationsQuery();
1129
+ const integration = data?.[provider];
1130
+ return { isConnected: integration?.isConnected ?? false, integration, isLoading, error };
1131
+ };
1132
+ /**
1133
+ * Hook to get all of the app's integrations for whoever is viewing the app
1134
+ *
1135
+ * For gating on a single integration prefer `useIntegrationStatus(provider)`; use this when a component needs
1136
+ * several, or lists them. Shares its state with `useIntegrationStatus` (it lives on `client.integrations`), so the
1137
+ * status is fetched once. `isConnected` follows the same rules: false while loading, on error, and for undeclared
1138
+ * providers.
1139
+ *
1140
+ * @returns {Object} Integrations
1141
+ * @returns {Readonly<Record<string, Integration | undefined>>} integrations - Keyed by provider slug, e.g.
1142
+ * `integrations["slack"]?.isConnected`; empty until loaded
1143
+ * @returns {Function} isConnected - `(provider: string) => boolean`, e.g. `isConnected("slack")`
1144
+ * @returns {boolean} isLoading - True until the first status arrives
1145
+ * @returns {Error | null} error - Set if the status could not be fetched
1146
+ * @example
1147
+ * ```tsx
1148
+ * function ConnectedIntegrations() {
1149
+ * const { integrations } = useIntegrationsStatus();
1150
+ * const connected = Object.entries(integrations).filter(([, integration]) => integration?.isConnected);
1151
+ * return <ul>{connected.map(([provider]) => <li key={provider}>{provider}</li>)}</ul>;
1152
+ * }
1153
+ * ```
1154
+ */
1155
+ export const useIntegrationsStatus = () => {
1156
+ const { data, isLoading, error } = useIntegrationsQuery();
1157
+ const integrations = data ?? EMPTY_INTEGRATIONS;
1158
+ const isConnected = useCallback((provider) => integrations[provider]?.isConnected ?? false, [integrations]);
1159
+ return { integrations, isConnected, isLoading, error };
1160
+ };
1075
1161
  /**
1076
1162
  * Hook to manage the application theme mode
1077
1163
  *
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./Agent.js";
3
3
  export * from "./AgentChat.js";
4
4
  export * from "./ClientSdk.js";
5
5
  export * from "./Entity.js";
6
+ export * from "./Integration.js";
6
7
  export * from "./Page.js";
7
8
  export * from "./ReactClientSdk";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -3,5 +3,6 @@ export * from "./Agent.js";
3
3
  export * from "./AgentChat.js";
4
4
  export * from "./ClientSdk.js";
5
5
  export * from "./Entity.js";
6
+ export * from "./Integration.js";
6
7
  export * from "./Page.js";
7
8
  export * from "./ReactClientSdk";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/blocks-client-sdk",
3
- "version": "1.17.2",
3
+ "version": "1.18.0",
4
4
  "type": "module",
5
5
  "description": "Blocks client sdk",
6
6
  "keywords": [],
@@ -48,7 +48,7 @@
48
48
  "dependencies": {
49
49
  "@tanstack/react-query": "^5.101.0",
50
50
  "@blocksdiy/blocks-client-api": "1.5.0",
51
- "@blocksdiy/react-common": "1.49.0"
51
+ "@blocksdiy/react-common": "1.5.2"
52
52
  },
53
53
  "devDependencies": {
54
54
  "tsc-alias": "^1.8.10",