@blocksdiy/blocks-client-sdk 1.17.2 → 1.18.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/ClientSdk.d.ts +34 -0
- package/dist/ClientSdk.d.ts.map +1 -1
- package/dist/ClientSdk.js +59 -0
- package/dist/Integration.d.ts +46 -0
- package/dist/Integration.d.ts.map +1 -0
- package/dist/Integration.js +46 -0
- package/dist/ReactClientSdk.d.ts +73 -0
- package/dist/ReactClientSdk.d.ts.map +1 -1
- package/dist/ReactClientSdk.jsx +86 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +2 -2
package/dist/ClientSdk.d.ts
CHANGED
|
@@ -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
|
package/dist/ClientSdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientSdk.d.ts","sourceRoot":"","sources":["../src/ClientSdk.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClientSdk.d.ts","sourceRoot":"","sources":["../src/ClientSdk.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,SAAS;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,IAAI,CAAoC;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA2B;IAC3D,OAAO,CAAC,oBAAoB,CAAwE;IACpG,OAAO,CAAC,gBAAgB,CAAC,CAA6D;IAEtF;;;;;;;OAOG;gBACS,MAAM,EAAE,YAAY;IAW1B,YAAY;IAiBlB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,EAAE,SAAS,YAAY,GAAG,YAAY,EAAE,YAAY,EAAE,EAAE,GAKN,MAAM,CAAC,EAAE,CAAC;IAGnE;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,EAAE,SAAS,YAAY,GAAG,YAAY,EAAE,YAAY,EAAE,EAAE,GAQ7B,MAAM,CAAC,EAAE,CAAC;IAG5C;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,CAAC,EAAE,SAAS,UAAU,GAAG,UAAU,EAAE,UAAU,EAAE,EAAE,GAKJ,IAAI,CAAC,EAAE,CAAC;IAG3D;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,WAAW,GAAG,WAAW,EAAE,WAAW,EAAE,EAAE,GAKZ,KAAK,CAAC,EAAE,CAAC;IAGxD;;;;;OAKG;IACH,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK7D;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,GAAG,SAAS,eAAe,GAAG,eAAe,EAAE,eAAe,EAAE,GAAG,GAQhB,SAAS,CAAC,GAAG,CAAC;YAG7D,YAAY;IAiCpB,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAyCvG;;;;;;;;;;;;;OAaG;IACH,OAAO;IAIP;;;;;;;;;;;;;;;OAeG;IACH,IAAI,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC,CAEpE;IAED;;;;;;;;;OASG;IACH,gBAAgB,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC;YAOhE,iBAAiB;IAyB/B;;;;;;;;;;OAUG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;IAoBlF;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACG,aAAa,CAAC,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAmBhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,iBAAiB;CAGlB"}
|
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
|
+
}
|
package/dist/ReactClientSdk.d.ts
CHANGED
|
@@ -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":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAYnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEzC,qBAAa,cAAe,SAAQ,SAAS;CAAG;
|
|
1
|
+
{"version":3,"file":"ReactClientSdk.d.ts","sourceRoot":"","sources":["../src/ReactClientSdk.tsx"],"names":[],"mappings":"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"}
|
package/dist/ReactClientSdk.jsx
CHANGED
|
@@ -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
package/dist/index.d.ts.map
CHANGED
|
@@ -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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocksdiy/blocks-client-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.1",
|
|
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.
|
|
51
|
+
"@blocksdiy/react-common": "1.49.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"tsc-alias": "^1.8.10",
|