doover-js 0.4.7 → 0.5.0-alpha.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.
- package/README.md +31 -0
- package/dist/apis/_args.d.ts +16 -0
- package/dist/apis/_args.js +26 -0
- package/dist/apis/agents-api.d.ts +4 -1
- package/dist/apis/agents-api.js +139 -1
- package/dist/apis/aggregates-api.d.ts +23 -3
- package/dist/apis/aggregates-api.js +33 -4
- package/dist/apis/alarms-api.d.ts +30 -0
- package/dist/apis/alarms-api.js +51 -6
- package/dist/apis/channels-api.d.ts +40 -3
- package/dist/apis/channels-api.js +50 -5
- package/dist/apis/connections-api.d.ts +21 -5
- package/dist/apis/connections-api.js +26 -10
- package/dist/apis/messages-api.d.ts +55 -9
- package/dist/apis/messages-api.js +96 -11
- package/dist/apis/notifications-api.d.ts +52 -0
- package/dist/apis/notifications-api.js +99 -13
- package/dist/apis/permissions-api.d.ts +8 -0
- package/dist/apis/permissions-api.js +11 -2
- package/dist/apis/processors-api.d.ts +35 -0
- package/dist/apis/processors-api.js +64 -8
- package/dist/apis/users-api.d.ts +8 -0
- package/dist/apis/users-api.js +13 -0
- package/dist/client/doover-client.d.ts +4 -8
- package/dist/client/doover-client.js +16 -28
- package/dist/client/stats.d.ts +24 -0
- package/dist/client/stats.js +62 -0
- package/dist/gateway/gateway-client.d.ts +13 -1
- package/dist/gateway/gateway-client.js +54 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +13 -7
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +4 -1
- package/dist/react/useChannelAggregate.js +8 -1
- package/dist/react/useChannelMessages.js +5 -2
- package/dist/react/useChannelSubscription.js +8 -18
- package/dist/react/useInvocationLogs.d.ts +23 -0
- package/dist/react/useInvocationLogs.js +41 -0
- package/dist/react/useMultiAgentAggregates.js +8 -14
- package/dist/react/useMultiAgentChannelMessages.js +8 -13
- package/dist/react/useSendMessage.js +6 -1
- package/dist/react/useSendRpc.js +4 -1
- package/dist/react/useUpdateAggregate.js +9 -3
- package/dist/rpc/errors.d.ts +10 -0
- package/dist/rpc/errors.js +23 -0
- package/dist/rpc/rpc-dispatcher.d.ts +28 -0
- package/dist/rpc/rpc-dispatcher.js +129 -0
- package/dist/test/api-args.test.d.ts +1 -0
- package/dist/test/api-args.test.js +48 -0
- package/dist/test/api-overloads.test.d.ts +9 -0
- package/dist/test/api-overloads.test.js +276 -0
- package/dist/test/gateway-subscriptions.test.d.ts +1 -0
- package/dist/test/gateway-subscriptions.test.js +95 -0
- package/dist/test/react.test.js +36 -0
- package/dist/test/rpc-dispatcher.test.d.ts +1 -0
- package/dist/test/rpc-dispatcher.test.js +190 -0
- package/dist/test/stats-rpc.test.d.ts +1 -0
- package/dist/test/stats-rpc.test.js +69 -0
- package/dist/test/users-api.test.d.ts +1 -0
- package/dist/test/users-api.test.js +19 -0
- package/dist/viewer/doover-data-provider.d.ts +30 -34
- package/dist/viewer/doover-data-provider.js +82 -316
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type UseQueryResult } from "@tanstack/react-query";
|
|
2
|
+
import type { ChannelIdentifier } from "../types/viewer";
|
|
3
|
+
export declare function invocationLogsQueryKey(agentId: string | undefined, channelName: string | undefined, messageId: string | undefined): readonly ["doover", "agent", string | undefined, "channel", string | undefined, "message", string | undefined, "logs"];
|
|
4
|
+
export interface UseInvocationLogsOptions {
|
|
5
|
+
/** Defaults to true. Set false to skip the query (e.g. dialog closed). */
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* react-query retry behaviour. Defaults to false — the logs endpoint
|
|
9
|
+
* commonly 404s while logs are still materialising server-side, and a
|
|
10
|
+
* manual refetch button is friendlier than silent retry.
|
|
11
|
+
*/
|
|
12
|
+
retry?: boolean | number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Fetch the log entries for a single invocation message. The `/logs`
|
|
16
|
+
* endpoint is only meaningful for invocation messages (channel name like
|
|
17
|
+
* `dv-proc-inv-…`); other message types return 404.
|
|
18
|
+
*
|
|
19
|
+
* Generic on `TLog` — the shape of a single log entry. Defaults to `unknown`
|
|
20
|
+
* because log payloads are domain-specific (lambda telemetry, app-level
|
|
21
|
+
* structured logs, etc.) and doover-js does not own the canonical shape.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useInvocationLogs<TLog = unknown>(identifier: ChannelIdentifier, messageId: string | undefined, options?: UseInvocationLogsOptions): UseQueryResult<TLog[]>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.invocationLogsQueryKey = invocationLogsQueryKey;
|
|
4
|
+
exports.useInvocationLogs = useInvocationLogs;
|
|
5
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
6
|
+
const context_1 = require("./context");
|
|
7
|
+
function invocationLogsQueryKey(agentId, channelName, messageId) {
|
|
8
|
+
return [
|
|
9
|
+
"doover",
|
|
10
|
+
"agent",
|
|
11
|
+
agentId,
|
|
12
|
+
"channel",
|
|
13
|
+
channelName,
|
|
14
|
+
"message",
|
|
15
|
+
messageId,
|
|
16
|
+
"logs",
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fetch the log entries for a single invocation message. The `/logs`
|
|
21
|
+
* endpoint is only meaningful for invocation messages (channel name like
|
|
22
|
+
* `dv-proc-inv-…`); other message types return 404.
|
|
23
|
+
*
|
|
24
|
+
* Generic on `TLog` — the shape of a single log entry. Defaults to `unknown`
|
|
25
|
+
* because log payloads are domain-specific (lambda telemetry, app-level
|
|
26
|
+
* structured logs, etc.) and doover-js does not own the canonical shape.
|
|
27
|
+
*/
|
|
28
|
+
function useInvocationLogs(identifier, messageId, options) {
|
|
29
|
+
const client = (0, context_1.useDooverClient)();
|
|
30
|
+
const { agentId, channelName } = identifier;
|
|
31
|
+
return (0, react_query_1.useQuery)({
|
|
32
|
+
queryKey: invocationLogsQueryKey(agentId, channelName, messageId),
|
|
33
|
+
queryFn: () => client.messages.getInvocationLogs(agentId, channelName, messageId),
|
|
34
|
+
enabled: !!agentId &&
|
|
35
|
+
!!channelName &&
|
|
36
|
+
!!messageId &&
|
|
37
|
+
(options?.enabled ?? true),
|
|
38
|
+
retry: options?.retry ?? false,
|
|
39
|
+
staleTime: Infinity,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -65,22 +65,16 @@ function useMultiAgentAggregates(channelName, agentIds, options) {
|
|
|
65
65
|
(0, react_1.useEffect)(() => {
|
|
66
66
|
if (!liveUpdates || agentIds.length === 0)
|
|
67
67
|
return;
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
patchAgentAggregate(agentId, aggregate);
|
|
74
|
-
};
|
|
75
|
-
void client.viewer.subscribeToChannel(identifier, messageCallback, aggregateCallback);
|
|
76
|
-
return { identifier, messageCallback };
|
|
68
|
+
const offs = agentIds.map((agentId) => {
|
|
69
|
+
const channel = { agent_id: agentId, name: channelName };
|
|
70
|
+
return client.gateway.subscribeToChannel(channel, {
|
|
71
|
+
onAggregate: (agg) => patchAgentAggregate(agentId, agg),
|
|
72
|
+
});
|
|
77
73
|
});
|
|
74
|
+
void client.gateway.connect();
|
|
78
75
|
return () => {
|
|
79
|
-
for (const
|
|
80
|
-
|
|
81
|
-
.unsubscribeFromChannel(identifier, messageCallback)
|
|
82
|
-
.catch(() => { });
|
|
83
|
-
}
|
|
76
|
+
for (const off of offs)
|
|
77
|
+
off();
|
|
84
78
|
};
|
|
85
79
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
86
80
|
}, [client, channelName, liveUpdates, agentIds.join(",")]);
|
|
@@ -43,21 +43,16 @@ function useMultiAgentChannelMessages(channelName, agentIds, options) {
|
|
|
43
43
|
(0, react_1.useEffect)(() => {
|
|
44
44
|
if (!liveUpdates || agentIds.length === 0)
|
|
45
45
|
return;
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
prependMessage(
|
|
50
|
-
};
|
|
51
|
-
const aggregateCallback = () => { };
|
|
52
|
-
void client.viewer.subscribeToChannel(identifier, messageCallback, aggregateCallback);
|
|
53
|
-
return { identifier, messageCallback };
|
|
46
|
+
const offs = agentIds.map((agentId) => {
|
|
47
|
+
const channel = { agent_id: agentId, name: channelName };
|
|
48
|
+
return client.gateway.subscribeToChannel(channel, {
|
|
49
|
+
onMessage: (msg) => prependMessage(msg),
|
|
50
|
+
});
|
|
54
51
|
});
|
|
52
|
+
void client.gateway.connect();
|
|
55
53
|
return () => {
|
|
56
|
-
for (const
|
|
57
|
-
|
|
58
|
-
.unsubscribeFromChannel(identifier, messageCallback)
|
|
59
|
-
.catch(() => { });
|
|
60
|
-
}
|
|
54
|
+
for (const off of offs)
|
|
55
|
+
off();
|
|
61
56
|
};
|
|
62
57
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
63
58
|
}, [client, channelName, liveUpdates, agentIds.join(",")]);
|
|
@@ -11,6 +11,11 @@ const context_1 = require("./context");
|
|
|
11
11
|
function useSendMessage(identifier) {
|
|
12
12
|
const client = (0, context_1.useDooverClient)();
|
|
13
13
|
return (0, react_query_1.useMutation)({
|
|
14
|
-
mutationFn: (data) =>
|
|
14
|
+
mutationFn: (data) => {
|
|
15
|
+
if (!identifier.agentId || !identifier.channelName) {
|
|
16
|
+
return Promise.reject(new Error("Identifier must include agentId and channelName"));
|
|
17
|
+
}
|
|
18
|
+
return client.messages.postMessage({ agentId: identifier.agentId, channelName: identifier.channelName }, { data: data });
|
|
19
|
+
},
|
|
15
20
|
});
|
|
16
21
|
}
|
package/dist/react/useSendRpc.js
CHANGED
|
@@ -115,7 +115,10 @@ function useSendRpc(identifier, options) {
|
|
|
115
115
|
? { app_key: options.app_key }
|
|
116
116
|
: {}),
|
|
117
117
|
};
|
|
118
|
-
|
|
118
|
+
if (!identifier.agentId || !identifier.channelName) {
|
|
119
|
+
throw new Error("Identifier must include agentId and channelName");
|
|
120
|
+
}
|
|
121
|
+
return client.rpc.send({ agentId: identifier.agentId, channelName: identifier.channelName }, rpcRequest, {
|
|
119
122
|
onStatus: (status) => appendStatus(commandId, status),
|
|
120
123
|
});
|
|
121
124
|
},
|
|
@@ -16,9 +16,15 @@ function useUpdateAggregate(identifier, options) {
|
|
|
16
16
|
const replace = options?.replace ?? false;
|
|
17
17
|
const params = options?.params;
|
|
18
18
|
return (0, react_query_1.useMutation)({
|
|
19
|
-
mutationFn: (data) =>
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
mutationFn: (data) => {
|
|
20
|
+
if (!identifier.agentId || !identifier.channelName) {
|
|
21
|
+
return Promise.reject(new Error("Identifier must include agentId and channelName"));
|
|
22
|
+
}
|
|
23
|
+
const id = { agentId: identifier.agentId, channelName: identifier.channelName };
|
|
24
|
+
return (replace
|
|
25
|
+
? client.aggregates.putAggregate(id, data, params)
|
|
26
|
+
: client.aggregates.patchAggregate(id, data, params));
|
|
27
|
+
},
|
|
22
28
|
onSuccess: (aggregate) => {
|
|
23
29
|
queryClient.setQueryData((0, useChannelAggregate_1.channelAggregateQueryKey)(identifier.agentId, identifier.channelName), aggregate);
|
|
24
30
|
},
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RpcRequest, RpcStatus } from "../types/common";
|
|
2
|
+
export declare class DooverRpcError extends Error {
|
|
3
|
+
readonly status: RpcStatus<unknown> & {
|
|
4
|
+
code: "error";
|
|
5
|
+
};
|
|
6
|
+
readonly request: RpcRequest;
|
|
7
|
+
constructor(status: RpcStatus<unknown> & {
|
|
8
|
+
code: "error";
|
|
9
|
+
}, request: RpcRequest);
|
|
10
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DooverRpcError = void 0;
|
|
4
|
+
class DooverRpcError extends Error {
|
|
5
|
+
constructor(status, request) {
|
|
6
|
+
const text = typeof status.message === "string"
|
|
7
|
+
? status.message
|
|
8
|
+
: (() => {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.stringify(status.message);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return "Unknown RPC error";
|
|
14
|
+
}
|
|
15
|
+
})();
|
|
16
|
+
super(text);
|
|
17
|
+
this.name = "DooverRpcError";
|
|
18
|
+
this.status = status;
|
|
19
|
+
this.request = request;
|
|
20
|
+
Object.setPrototypeOf(this, DooverRpcError.prototype);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.DooverRpcError = DooverRpcError;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MessagesApi } from "../apis/messages-api";
|
|
2
|
+
import type { DooverStatsCollector } from "../client/stats";
|
|
3
|
+
import type { GatewayClient } from "../gateway/gateway-client";
|
|
4
|
+
import type { RpcRequest, RpcStatus } from "../types/common";
|
|
5
|
+
export interface SendRpcOptions<TPending = undefined> {
|
|
6
|
+
onStatus?: (status: RpcStatus<TPending>) => void;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
}
|
|
10
|
+
interface ChannelIdentifierLike {
|
|
11
|
+
agentId: string;
|
|
12
|
+
channelName: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class RpcDispatcher {
|
|
15
|
+
private readonly gateway;
|
|
16
|
+
private readonly messages;
|
|
17
|
+
private pending;
|
|
18
|
+
private channelRefs;
|
|
19
|
+
private stats;
|
|
20
|
+
constructor(gateway: GatewayClient, messages: MessagesApi);
|
|
21
|
+
setStats(collector: DooverStatsCollector | null): void;
|
|
22
|
+
send<TReq = object, TRes = object, TPending = undefined>(channel: ChannelIdentifierLike, request: RpcRequest<TReq>, options?: SendRpcOptions<TPending>): Promise<TRes>;
|
|
23
|
+
private acquireChannel;
|
|
24
|
+
private releaseChannel;
|
|
25
|
+
private route;
|
|
26
|
+
private settle;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RpcDispatcher = void 0;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
function isRpcMessageData(data) {
|
|
6
|
+
return (typeof data === "object" &&
|
|
7
|
+
data !== null &&
|
|
8
|
+
"status" in data &&
|
|
9
|
+
"method" in data &&
|
|
10
|
+
"request" in data);
|
|
11
|
+
}
|
|
12
|
+
class RpcDispatcher {
|
|
13
|
+
constructor(gateway, messages) {
|
|
14
|
+
this.gateway = gateway;
|
|
15
|
+
this.messages = messages;
|
|
16
|
+
this.pending = new Map();
|
|
17
|
+
this.channelRefs = new Map();
|
|
18
|
+
this.stats = null;
|
|
19
|
+
}
|
|
20
|
+
setStats(collector) {
|
|
21
|
+
this.stats = collector;
|
|
22
|
+
}
|
|
23
|
+
send(channel, request, options) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const channelRef = {
|
|
26
|
+
agent_id: channel.agentId,
|
|
27
|
+
name: channel.channelName,
|
|
28
|
+
};
|
|
29
|
+
const channelKey = `${channelRef.agent_id}/${channelRef.name}`;
|
|
30
|
+
this.acquireChannel(channelKey, channelRef);
|
|
31
|
+
const startedAt = this.stats?.recordRpcStart() ?? null;
|
|
32
|
+
this.messages
|
|
33
|
+
.postMessage(channel.agentId, channel.channelName, {
|
|
34
|
+
type: "rpc",
|
|
35
|
+
...request,
|
|
36
|
+
})
|
|
37
|
+
.then((message) => {
|
|
38
|
+
const pending = {
|
|
39
|
+
resolve: resolve,
|
|
40
|
+
reject,
|
|
41
|
+
onStatus: options?.onStatus,
|
|
42
|
+
request: request,
|
|
43
|
+
channelKey,
|
|
44
|
+
channel: channelRef,
|
|
45
|
+
startedAt,
|
|
46
|
+
};
|
|
47
|
+
if (options?.signal) {
|
|
48
|
+
const onAbort = () => this.settle(message.id, "abort", undefined, options.signal?.reason);
|
|
49
|
+
if (options.signal.aborted) {
|
|
50
|
+
this.releaseChannel(channelKey);
|
|
51
|
+
this.stats?.recordRpcEnd(startedAt, "abort");
|
|
52
|
+
reject(options.signal.reason ?? new Error("Aborted"));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
options.signal.addEventListener("abort", onAbort);
|
|
56
|
+
pending.signal = options.signal;
|
|
57
|
+
pending.abortListener = onAbort;
|
|
58
|
+
}
|
|
59
|
+
if (options?.timeoutMs !== undefined) {
|
|
60
|
+
pending.timer = setTimeout(() => {
|
|
61
|
+
this.settle(message.id, "timeout", undefined, new Error("RPC timed out"));
|
|
62
|
+
}, options.timeoutMs);
|
|
63
|
+
}
|
|
64
|
+
this.pending.set(message.id, pending);
|
|
65
|
+
})
|
|
66
|
+
.catch((err) => {
|
|
67
|
+
// postMessage failed before we registered pending — release and reject.
|
|
68
|
+
this.releaseChannel(channelKey);
|
|
69
|
+
this.stats?.recordRpcEnd(startedAt, "error");
|
|
70
|
+
reject(err);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
acquireChannel(channelKey, channelRef) {
|
|
75
|
+
const existing = this.channelRefs.get(channelKey);
|
|
76
|
+
if (existing) {
|
|
77
|
+
existing.refCount += 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const handlers = {
|
|
81
|
+
onMessageUpdate: (msg, requestData) => this.route(msg, requestData),
|
|
82
|
+
};
|
|
83
|
+
const unsubscribe = this.gateway.subscribeToChannel(channelRef, handlers);
|
|
84
|
+
this.channelRefs.set(channelKey, { unsubscribe, refCount: 1 });
|
|
85
|
+
}
|
|
86
|
+
releaseChannel(channelKey) {
|
|
87
|
+
const entry = this.channelRefs.get(channelKey);
|
|
88
|
+
if (!entry)
|
|
89
|
+
return;
|
|
90
|
+
entry.refCount -= 1;
|
|
91
|
+
if (entry.refCount <= 0) {
|
|
92
|
+
entry.unsubscribe();
|
|
93
|
+
this.channelRefs.delete(channelKey);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
route(msg, _requestData) {
|
|
97
|
+
const pending = this.pending.get(msg.id);
|
|
98
|
+
if (!pending)
|
|
99
|
+
return;
|
|
100
|
+
if (!isRpcMessageData(msg.data))
|
|
101
|
+
return;
|
|
102
|
+
const status = msg.data.status;
|
|
103
|
+
pending.onStatus?.(status);
|
|
104
|
+
if (status.code === "success") {
|
|
105
|
+
this.settle(msg.id, "success", msg.data.response);
|
|
106
|
+
}
|
|
107
|
+
else if (status.code === "error") {
|
|
108
|
+
this.settle(msg.id, "error", undefined, new errors_1.DooverRpcError(status, pending.request));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
settle(messageId, outcome, response, rejection) {
|
|
112
|
+
const pending = this.pending.get(messageId);
|
|
113
|
+
if (!pending)
|
|
114
|
+
return;
|
|
115
|
+
this.pending.delete(messageId);
|
|
116
|
+
if (pending.timer)
|
|
117
|
+
clearTimeout(pending.timer);
|
|
118
|
+
if (pending.signal && pending.abortListener) {
|
|
119
|
+
pending.signal.removeEventListener("abort", pending.abortListener);
|
|
120
|
+
}
|
|
121
|
+
this.releaseChannel(pending.channelKey);
|
|
122
|
+
this.stats?.recordRpcEnd(pending.startedAt, outcome);
|
|
123
|
+
if (outcome === "success")
|
|
124
|
+
pending.resolve(response);
|
|
125
|
+
else
|
|
126
|
+
pending.reject(rejection);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.RpcDispatcher = RpcDispatcher;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const _args_1 = require("../apis/_args");
|
|
5
|
+
describe("resolveChannelArgs", () => {
|
|
6
|
+
it("parses positional (agentId, channelName)", () => {
|
|
7
|
+
const result = (0, _args_1.resolveChannelArgs)(["a1", "c1"]);
|
|
8
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", channelName: "c1", options: undefined });
|
|
9
|
+
});
|
|
10
|
+
it("parses positional with options", () => {
|
|
11
|
+
const result = (0, _args_1.resolveChannelArgs)(["a1", "c1", { x: 7 }]);
|
|
12
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", channelName: "c1", options: { x: 7 } });
|
|
13
|
+
});
|
|
14
|
+
it("parses identifier object", () => {
|
|
15
|
+
const result = (0, _args_1.resolveChannelArgs)([
|
|
16
|
+
{ agentId: "a1", channelName: "c1" },
|
|
17
|
+
]);
|
|
18
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", channelName: "c1", options: undefined });
|
|
19
|
+
});
|
|
20
|
+
it("parses identifier object with options", () => {
|
|
21
|
+
const result = (0, _args_1.resolveChannelArgs)([
|
|
22
|
+
{ agentId: "a1", channelName: "c1" },
|
|
23
|
+
{ x: 7 },
|
|
24
|
+
]);
|
|
25
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", channelName: "c1", options: { x: 7 } });
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe("resolveAgentArgs", () => {
|
|
29
|
+
it("parses positional agentId", () => {
|
|
30
|
+
const result = (0, _args_1.resolveAgentArgs)(["a1"]);
|
|
31
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", options: undefined });
|
|
32
|
+
});
|
|
33
|
+
it("parses positional with options", () => {
|
|
34
|
+
const result = (0, _args_1.resolveAgentArgs)(["a1", { archived: true }]);
|
|
35
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", options: { archived: true } });
|
|
36
|
+
});
|
|
37
|
+
it("parses identifier object", () => {
|
|
38
|
+
const result = (0, _args_1.resolveAgentArgs)([{ agentId: "a1" }]);
|
|
39
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", options: undefined });
|
|
40
|
+
});
|
|
41
|
+
it("parses identifier object with options", () => {
|
|
42
|
+
const result = (0, _args_1.resolveAgentArgs)([
|
|
43
|
+
{ agentId: "a1" },
|
|
44
|
+
{ archived: true },
|
|
45
|
+
]);
|
|
46
|
+
(0, chai_1.expect)(result).to.deep.equal({ agentId: "a1", options: { archived: true } });
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RestClient } from "../http/rest-client";
|
|
2
|
+
interface RecordedCall {
|
|
3
|
+
method: "get" | "post" | "put" | "patch" | "delete" | "request";
|
|
4
|
+
args: unknown[];
|
|
5
|
+
}
|
|
6
|
+
export declare function makeRestStub(): RestClient & {
|
|
7
|
+
calls: RecordedCall[];
|
|
8
|
+
};
|
|
9
|
+
export {};
|