@dev-fastn-ai/react-core 2.4.12 → 2.4.14
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/README.md +137 -1
- package/dist/core/provider.d.ts +2 -2
- package/dist/core/use-configuration-form.d.ts +2 -2
- package/dist/core/use-configurations.d.ts +2 -2
- package/dist/core/use-field-options.d.ts +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.esm.js +2 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -156,6 +156,8 @@ interface Connector {
|
|
|
156
156
|
imageUri?: string;
|
|
157
157
|
status: ConnectorStatus;
|
|
158
158
|
actions: ConnectorAction[];
|
|
159
|
+
isMultiConnection?: boolean;
|
|
160
|
+
connectorsDetails?: Record<string, any> | null;
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
enum ConnectorStatus {
|
|
@@ -167,7 +169,8 @@ enum ConnectorStatus {
|
|
|
167
169
|
interface ConnectorAction {
|
|
168
170
|
name: string;
|
|
169
171
|
actionType: ConnectorActionType | string;
|
|
170
|
-
onClick?: () => Promise<ConnectorActionResult>;
|
|
172
|
+
onClick?: (args?: { connectionId?: string; connectionIds?: string[] }) => Promise<ConnectorActionResult>;
|
|
173
|
+
onSubmit?: (formData: Record<string, Primitive>, args?: { connectionId?: string; connectionIds?: string[] }) => Promise<ConnectorActionResult>;
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
interface ConnectorActionResult {
|
|
@@ -1223,6 +1226,139 @@ function MultiLevelSelectForm() {
|
|
|
1223
1226
|
|
|
1224
1227
|
---
|
|
1225
1228
|
|
|
1229
|
+
### **Multi-Connection Support**
|
|
1230
|
+
|
|
1231
|
+
Some connectors support multiple simultaneous connections (e.g. connecting to multiple workspaces or accounts). When `connector.isMultiConnection` is `true`, you can add and remove individual connections.
|
|
1232
|
+
|
|
1233
|
+
#### Detecting Multi-Connection Connectors
|
|
1234
|
+
|
|
1235
|
+
```tsx
|
|
1236
|
+
function ConnectorCard({ connector }) {
|
|
1237
|
+
const isMultiConn = connector.isMultiConnection;
|
|
1238
|
+
const isActive = connector.status === "ACTIVE";
|
|
1239
|
+
|
|
1240
|
+
const handleActionClick = (action) => {
|
|
1241
|
+
if (action.actionType === "ACTIVATION" && isMultiConn && isActive) {
|
|
1242
|
+
// Connector is already active — show a "Manage Connections" UI
|
|
1243
|
+
// instead of the normal activation flow
|
|
1244
|
+
openManageConnectionsModal();
|
|
1245
|
+
} else {
|
|
1246
|
+
// Normal activation/deactivation flow
|
|
1247
|
+
action.onClick?.();
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1251
|
+
// ...
|
|
1252
|
+
}
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
#### Adding a New Connection
|
|
1256
|
+
|
|
1257
|
+
Pass a `connectionId` when activating to create a named connection:
|
|
1258
|
+
|
|
1259
|
+
```tsx
|
|
1260
|
+
// Non-form action (direct OAuth or no-input activation)
|
|
1261
|
+
const activateAction = connector.actions.find(a => a.actionType === "ACTIVATION");
|
|
1262
|
+
await activateAction?.onClick?.({ connectionId: "my-new-connection" });
|
|
1263
|
+
|
|
1264
|
+
// Form-based action (connector requires input fields)
|
|
1265
|
+
await activateAction?.onSubmit?.(formData, { connectionId: "my-new-connection" });
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
The `connectionId` is sent in the API request body as `connections: ["my-new-connection"]`.
|
|
1269
|
+
|
|
1270
|
+
#### Disconnecting a Specific Connection
|
|
1271
|
+
|
|
1272
|
+
Pass both the connection name and its connector ID keys when deactivating:
|
|
1273
|
+
|
|
1274
|
+
```tsx
|
|
1275
|
+
const deactivateAction = connector.actions.find(a => a.actionType === "DEACTIVATION");
|
|
1276
|
+
|
|
1277
|
+
await deactivateAction?.onClick?.({
|
|
1278
|
+
connectionId: "my-connection-name", // the connection name
|
|
1279
|
+
connectionIds: ["_knexa_e494e021-4f8d-..."], // connector ID keys from connectorsDetails
|
|
1280
|
+
});
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
#### Reading Existing Connections
|
|
1284
|
+
|
|
1285
|
+
Existing connections are in `connector.connectorsDetails?.connectionsIds` — a map of connector ID keys to arrays of connection names:
|
|
1286
|
+
|
|
1287
|
+
```tsx
|
|
1288
|
+
const connectionsIds = connector.connectorsDetails?.connectionsIds;
|
|
1289
|
+
|
|
1290
|
+
// Example structure:
|
|
1291
|
+
// {
|
|
1292
|
+
// "_knexa_e494e021-...": ["default", "my-connection"],
|
|
1293
|
+
// "_knexa_abc12345-...": ["my-connection"]
|
|
1294
|
+
// }
|
|
1295
|
+
|
|
1296
|
+
// Process into a deduplicated list:
|
|
1297
|
+
const connectionMap = new Map();
|
|
1298
|
+
if (connectionsIds) {
|
|
1299
|
+
Object.entries(connectionsIds).forEach(([key, names]) => {
|
|
1300
|
+
names.forEach((name) => {
|
|
1301
|
+
if (connectionMap.has(name)) {
|
|
1302
|
+
connectionMap.get(name).keys.push(key);
|
|
1303
|
+
} else {
|
|
1304
|
+
connectionMap.set(name, { name, keys: [key] });
|
|
1305
|
+
}
|
|
1306
|
+
});
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
const connections = Array.from(connectionMap.values());
|
|
1310
|
+
// connections = [{ name: "default", keys: ["_knexa_e494e021-..."] }, ...]
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
#### Full Example: Manage Connections Modal
|
|
1314
|
+
|
|
1315
|
+
```tsx
|
|
1316
|
+
function ManageConnectionsModal({ connector, onClose }) {
|
|
1317
|
+
const [connectionName, setConnectionName] = useState("");
|
|
1318
|
+
|
|
1319
|
+
const activateAction = connector.actions.find(a => a.actionType === "ACTIVATION");
|
|
1320
|
+
const deactivateAction = connector.actions.find(a => a.actionType === "DEACTIVATION");
|
|
1321
|
+
|
|
1322
|
+
// Process existing connections from connectorsDetails
|
|
1323
|
+
const connectionsIds = connector.connectorsDetails?.connectionsIds;
|
|
1324
|
+
const connections = processConnections(connectionsIds); // deduplicated list
|
|
1325
|
+
|
|
1326
|
+
const handleConnect = async () => {
|
|
1327
|
+
const connId = connectionName.trim();
|
|
1328
|
+
if (!connId) return;
|
|
1329
|
+
await activateAction?.onClick?.({ connectionId: connId });
|
|
1330
|
+
setConnectionName("");
|
|
1331
|
+
};
|
|
1332
|
+
|
|
1333
|
+
const handleDisconnect = async (connName, connIdKeys) => {
|
|
1334
|
+
await deactivateAction?.onClick?.({
|
|
1335
|
+
connectionId: connName,
|
|
1336
|
+
connectionIds: connIdKeys,
|
|
1337
|
+
});
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
return (
|
|
1341
|
+
<div>
|
|
1342
|
+
{/* Add new connection */}
|
|
1343
|
+
<input value={connectionName} onChange={e => setConnectionName(e.target.value)} />
|
|
1344
|
+
<button onClick={handleConnect}>Connect</button>
|
|
1345
|
+
|
|
1346
|
+
{/* List existing connections */}
|
|
1347
|
+
{connections.map(conn => (
|
|
1348
|
+
<div key={conn.name}>
|
|
1349
|
+
<span>{conn.name}</span>
|
|
1350
|
+
<button onClick={() => handleDisconnect(conn.name, conn.keys)}>
|
|
1351
|
+
Disconnect
|
|
1352
|
+
</button>
|
|
1353
|
+
</div>
|
|
1354
|
+
))}
|
|
1355
|
+
</div>
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
```
|
|
1359
|
+
|
|
1360
|
+
---
|
|
1361
|
+
|
|
1226
1362
|
### **Error Handling and Loading States**
|
|
1227
1363
|
|
|
1228
1364
|
```tsx
|
package/dist/core/provider.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { QueryClient } from "@tanstack/react-query";
|
|
2
|
-
import { Fastn } from "@fastn-ai/core";
|
|
3
|
-
import type { FastnConfig } from "@fastn-ai/core";
|
|
2
|
+
import { Fastn } from "@dev-fastn-ai/core";
|
|
3
|
+
import type { FastnConfig } from "@dev-fastn-ai/core";
|
|
4
4
|
export declare const FastnProvider: ({ children, config, queryClient, }: {
|
|
5
5
|
children: React.ReactNode;
|
|
6
6
|
config: FastnConfig;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GetConfigurationFormInput } from "@fastn-ai/core";
|
|
2
|
-
export declare const useConfigurationForm: (input: GetConfigurationFormInput) => import("@tanstack/react-query").UseQueryResult<import("@fastn-ai/core").ConfigurationForm, Error>;
|
|
1
|
+
import { GetConfigurationFormInput } from "@dev-fastn-ai/core";
|
|
2
|
+
export declare const useConfigurationForm: (input: GetConfigurationFormInput) => import("@tanstack/react-query").UseQueryResult<import("@dev-fastn-ai/core").ConfigurationForm, Error>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GetConfigurationsInput } from "@fastn-ai/core";
|
|
2
|
-
export declare const useConfigurations: (input: GetConfigurationsInput) => import("@tanstack/react-query").UseQueryResult<import("@fastn-ai/core").Configuration[], Error>;
|
|
1
|
+
import { GetConfigurationsInput } from "@dev-fastn-ai/core";
|
|
2
|
+
export declare const useConfigurations: (input: GetConfigurationsInput) => import("@tanstack/react-query").UseQueryResult<import("@dev-fastn-ai/core").Configuration[], Error>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectorField, SelectOption, FormData } from "@fastn-ai/core";
|
|
1
|
+
import type { ConnectorField, SelectOption, FormData } from "@dev-fastn-ai/core";
|
|
2
2
|
/**
|
|
3
3
|
* Custom hook to manage async select field options with search, pagination, and error handling using React Query.
|
|
4
4
|
*
|
package/dist/index.cjs.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var reactQuery = require('@tanstack/react-query');
|
|
6
|
-
var core = require('@fastn-ai/core');
|
|
6
|
+
var core = require('@dev-fastn-ai/core');
|
|
7
7
|
|
|
8
8
|
const FastnContext = react.createContext(null);
|
|
9
9
|
const FastnProvider = ({ children, config, queryClient, }) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
3
3
|
import { QueryClient } from '@tanstack/react-query';
|
|
4
|
-
import * as
|
|
5
|
-
import { FastnConfig, GetConfigurationsInput, GetConfigurationFormInput, ConnectorField, FormData, SelectOption } from '@fastn-ai/core';
|
|
6
|
-
export * from '@fastn-ai/core';
|
|
4
|
+
import * as _dev_fastn_ai_core from '@dev-fastn-ai/core';
|
|
5
|
+
import { FastnConfig, GetConfigurationsInput, GetConfigurationFormInput, ConnectorField, FormData, SelectOption } from '@dev-fastn-ai/core';
|
|
6
|
+
export * from '@dev-fastn-ai/core';
|
|
7
7
|
|
|
8
8
|
declare const FastnProvider: ({ children, config, queryClient, }: {
|
|
9
9
|
children: React.ReactNode;
|
|
@@ -11,11 +11,11 @@ declare const FastnProvider: ({ children, config, queryClient, }: {
|
|
|
11
11
|
queryClient?: QueryClient;
|
|
12
12
|
}) => react_jsx_runtime.JSX.Element;
|
|
13
13
|
|
|
14
|
-
declare const useConfigurations: (input: GetConfigurationsInput) => _tanstack_react_query.UseQueryResult<
|
|
14
|
+
declare const useConfigurations: (input: GetConfigurationsInput) => _tanstack_react_query.UseQueryResult<_dev_fastn_ai_core.Configuration[], Error>;
|
|
15
15
|
|
|
16
|
-
declare const useConfigurationForm: (input: GetConfigurationFormInput) => _tanstack_react_query.UseQueryResult<
|
|
16
|
+
declare const useConfigurationForm: (input: GetConfigurationFormInput) => _tanstack_react_query.UseQueryResult<_dev_fastn_ai_core.ConfigurationForm, Error>;
|
|
17
17
|
|
|
18
|
-
declare const useConnectors: () => _tanstack_react_query.UseQueryResult<
|
|
18
|
+
declare const useConnectors: () => _tanstack_react_query.UseQueryResult<_dev_fastn_ai_core.Connector[], Error>;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Custom hook to manage async select field options with search, pagination, and error handling using React Query.
|
package/dist/index.esm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { createContext, useMemo, useContext, useEffect, useState, useCallback } from 'react';
|
|
3
3
|
import { QueryClientProvider, QueryClient, useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
4
|
-
import { Fastn } from '@fastn-ai/core';
|
|
5
|
-
export * from '@fastn-ai/core';
|
|
4
|
+
import { Fastn } from '@dev-fastn-ai/core';
|
|
5
|
+
export * from '@dev-fastn-ai/core';
|
|
6
6
|
|
|
7
7
|
const FastnContext = createContext(null);
|
|
8
8
|
const FastnProvider = ({ children, config, queryClient, }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev-fastn-ai/react-core",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.14",
|
|
4
4
|
"description": "React hooks and components for integrating Fastn AI connector marketplace into your applications. Built on top of @fastn-ai/core with React Query for optimal performance.",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
"license": "MIT",
|
|
53
53
|
"repository": {
|
|
54
54
|
"type": "git",
|
|
55
|
-
"url": "https://github.com/
|
|
55
|
+
"url": "https://github.com/fastn-ai/react-core.git"
|
|
56
56
|
},
|
|
57
57
|
"bugs": {
|
|
58
|
-
"url": "https://github.com/
|
|
58
|
+
"url": "https://github.com/fastn-ai/react-core/issues"
|
|
59
59
|
},
|
|
60
60
|
"homepage": "https://docs.fastn.ai",
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@dev-fastn-ai/core": "^2.
|
|
62
|
+
"@dev-fastn-ai/core": "^2.4.14",
|
|
63
63
|
"@fastn-ai/core": "^1.0.8",
|
|
64
64
|
"@types/lodash": "^4.17.20",
|
|
65
65
|
"lodash": "^4.17.21"
|
|
@@ -89,4 +89,4 @@
|
|
|
89
89
|
"publishConfig": {
|
|
90
90
|
"access": "public"
|
|
91
91
|
}
|
|
92
|
-
}
|
|
92
|
+
}
|