@dainprotocol/service-sdk 2.0.66 → 2.0.68

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.
Files changed (101) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +8 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/service/index.d.ts +4 -2
  5. package/dist/service/index.js +8 -1
  6. package/dist/service/index.js.map +1 -1
  7. package/dist/service/nodeService.d.ts +4 -2
  8. package/dist/service/nodeService.js +8 -1
  9. package/dist/service/nodeService.js.map +1 -1
  10. package/dist/service/oauth2Manager.js +3 -2
  11. package/dist/service/oauth2Manager.js.map +1 -1
  12. package/dist/service/server.js +84 -9
  13. package/dist/service/server.js.map +1 -1
  14. package/dist/service/service.js +15 -2
  15. package/dist/service/service.js.map +1 -1
  16. package/dist/service/skills.d.ts +106 -0
  17. package/dist/service/skills.js +156 -0
  18. package/dist/service/skills.js.map +1 -0
  19. package/dist/service/trigger-forwarder.d.ts +47 -0
  20. package/dist/service/trigger-forwarder.js +91 -0
  21. package/dist/service/trigger-forwarder.js.map +1 -0
  22. package/dist/service/types.d.ts +4 -0
  23. package/dist/service/webhooks.d.ts +109 -10
  24. package/dist/service/webhooks.js +184 -30
  25. package/dist/service/webhooks.js.map +1 -1
  26. package/package.json +1 -1
  27. package/dist/__tests__/api-sdk.test.d.ts +0 -1
  28. package/dist/__tests__/api-sdk.test.js +0 -102
  29. package/dist/__tests__/api-sdk.test.js.map +0 -1
  30. package/dist/__tests__/auth.test.d.ts +0 -1
  31. package/dist/__tests__/auth.test.js +0 -110
  32. package/dist/__tests__/auth.test.js.map +0 -1
  33. package/dist/__tests__/citations-plugin.test.d.ts +0 -1
  34. package/dist/__tests__/citations-plugin.test.js +0 -491
  35. package/dist/__tests__/citations-plugin.test.js.map +0 -1
  36. package/dist/__tests__/context-behavior.test.d.ts +0 -1
  37. package/dist/__tests__/context-behavior.test.js +0 -290
  38. package/dist/__tests__/context-behavior.test.js.map +0 -1
  39. package/dist/__tests__/convertToVercelTool.test.d.ts +0 -1
  40. package/dist/__tests__/convertToVercelTool.test.js +0 -527
  41. package/dist/__tests__/convertToVercelTool.test.js.map +0 -1
  42. package/dist/__tests__/core.test.d.ts +0 -1
  43. package/dist/__tests__/core.test.js +0 -154
  44. package/dist/__tests__/core.test.js.map +0 -1
  45. package/dist/__tests__/crypto-plugin.test.d.ts +0 -1
  46. package/dist/__tests__/crypto-plugin.test.js +0 -694
  47. package/dist/__tests__/crypto-plugin.test.js.map +0 -1
  48. package/dist/__tests__/humanActions.test.d.ts +0 -1
  49. package/dist/__tests__/humanActions.test.js +0 -221
  50. package/dist/__tests__/humanActions.test.js.map +0 -1
  51. package/dist/__tests__/integration.test.d.ts +0 -1
  52. package/dist/__tests__/integration.test.js +0 -1573
  53. package/dist/__tests__/integration.test.js.map +0 -1
  54. package/dist/__tests__/mealMeSchemas.test.d.ts +0 -576
  55. package/dist/__tests__/mealMeSchemas.test.js +0 -627
  56. package/dist/__tests__/mealMeSchemas.test.js.map +0 -1
  57. package/dist/__tests__/oauth-context-simple.test.d.ts +0 -1
  58. package/dist/__tests__/oauth-context-simple.test.js +0 -90
  59. package/dist/__tests__/oauth-context-simple.test.js.map +0 -1
  60. package/dist/__tests__/oauth-context.test.d.ts +0 -1
  61. package/dist/__tests__/oauth-context.test.js +0 -282
  62. package/dist/__tests__/oauth-context.test.js.map +0 -1
  63. package/dist/__tests__/oauth.test.d.ts +0 -1
  64. package/dist/__tests__/oauth.test.js +0 -378
  65. package/dist/__tests__/oauth.test.js.map +0 -1
  66. package/dist/__tests__/oauth2-client-context.test.d.ts +0 -1
  67. package/dist/__tests__/oauth2-client-context.test.js +0 -165
  68. package/dist/__tests__/oauth2-client-context.test.js.map +0 -1
  69. package/dist/__tests__/oauth2-client-integration.test.d.ts +0 -1
  70. package/dist/__tests__/oauth2-client-integration.test.js +0 -182
  71. package/dist/__tests__/oauth2-client-integration.test.js.map +0 -1
  72. package/dist/__tests__/oauth2-client-simple.test.d.ts +0 -1
  73. package/dist/__tests__/oauth2-client-simple.test.js +0 -144
  74. package/dist/__tests__/oauth2-client-simple.test.js.map +0 -1
  75. package/dist/__tests__/oauth2-context.test.d.ts +0 -1
  76. package/dist/__tests__/oauth2-context.test.js +0 -201
  77. package/dist/__tests__/oauth2-context.test.js.map +0 -1
  78. package/dist/__tests__/oauth2-datasource.test.d.ts +0 -1
  79. package/dist/__tests__/oauth2-datasource.test.js +0 -251
  80. package/dist/__tests__/oauth2-datasource.test.js.map +0 -1
  81. package/dist/__tests__/plugin.test.d.ts +0 -1
  82. package/dist/__tests__/plugin.test.js +0 -900
  83. package/dist/__tests__/plugin.test.js.map +0 -1
  84. package/dist/__tests__/processes.test.d.ts +0 -1
  85. package/dist/__tests__/processes.test.js +0 -239
  86. package/dist/__tests__/processes.test.js.map +0 -1
  87. package/dist/__tests__/streaming.test.d.ts +0 -1
  88. package/dist/__tests__/streaming.test.js +0 -592
  89. package/dist/__tests__/streaming.test.js.map +0 -1
  90. package/dist/__tests__/testEnums.d.ts +0 -1
  91. package/dist/__tests__/testEnums.js +0 -73
  92. package/dist/__tests__/testEnums.js.map +0 -1
  93. package/dist/__tests__/testOptionals.test.d.ts +0 -1
  94. package/dist/__tests__/testOptionals.test.js +0 -83
  95. package/dist/__tests__/testOptionals.test.js.map +0 -1
  96. package/dist/__tests__/types.test.d.ts +0 -1
  97. package/dist/__tests__/types.test.js +0 -98
  98. package/dist/__tests__/types.test.js.map +0 -1
  99. package/dist/service/zod-json-converter.d.ts +0 -14
  100. package/dist/service/zod-json-converter.js +0 -203
  101. package/dist/service/zod-json-converter.js.map +0 -1
@@ -1,900 +0,0 @@
1
- "use strict";
2
- // File: src/__tests__/plugin.test.ts
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- const tslib_1 = require("tslib");
5
- const client_auth_1 = require("@/client/client-auth");
6
- const client_1 = require("@/client/client");
7
- const ed25519_1 = require("@noble/curves/ed25519");
8
- const bs58_1 = tslib_1.__importDefault(require("bs58"));
9
- const nodeService_1 = require("@/service/nodeService");
10
- const core_1 = require("@/service/core");
11
- const zod_1 = require("zod");
12
- const time_plugin_1 = require("@/plugins/time-plugin");
13
- const crypto_plugin_1 = require("@/plugins/crypto-plugin");
14
- describe("DAIN Framework Plugin System", () => {
15
- const privateKey = ed25519_1.ed25519.utils.randomPrivateKey();
16
- const publicKey = ed25519_1.ed25519.getPublicKey(privateKey);
17
- const address = bs58_1.default.encode(publicKey);
18
- const clientPrivateKey = ed25519_1.ed25519.utils.randomPrivateKey();
19
- const agentAuth = new client_auth_1.DainClientAuth({
20
- privateKeyBase58: bs58_1.default.encode(clientPrivateKey),
21
- agentId: "agent-12",
22
- orgId: "org-12",
23
- });
24
- // Create a TimePlugin instance
25
- const timePlugin = new time_plugin_1.TimePlugin({ includeTimezone: true });
26
- // Create a CryptoPlugin instance with test wallet data
27
- const testWallets = [
28
- { chain: "sol", address: "SolTestAddress123456789" },
29
- { chain: "eth", address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }
30
- ];
31
- const cryptoPlugin = new crypto_plugin_1.CryptoPlugin(testWallets);
32
- // Create a wallet info tool to specifically test crypto plugin
33
- const walletInfoTool = (0, core_1.createTool)({
34
- id: "wallet-info",
35
- name: "Wallet Info Tool",
36
- description: "Shows information about connected wallets",
37
- input: zod_1.z.object({}),
38
- output: zod_1.z.object({
39
- connectedWallets: zod_1.z.array(zod_1.z.object({
40
- chain: zod_1.z.string(),
41
- address: zod_1.z.string()
42
- })),
43
- walletsCount: zod_1.z.number()
44
- }),
45
- handler: async ({}, agentInfo, context) => {
46
- // Extract wallet information from crypto plugin
47
- const cryptoData = context.extraData?.plugins?.['crypto-plugin'];
48
- console.log(`Wallet handler: received crypto plugin data:`, cryptoData);
49
- let wallets = [];
50
- if (cryptoData && cryptoData.wallets) {
51
- wallets = cryptoData.wallets;
52
- }
53
- return {
54
- text: `Found ${wallets.length} wallet(s)`,
55
- data: {
56
- connectedWallets: wallets,
57
- walletsCount: wallets.length
58
- },
59
- ui: null
60
- };
61
- }
62
- });
63
- // Create a test context
64
- const testContext = {
65
- id: "test-context",
66
- name: "Test Context",
67
- description: "A test context for plugin testing",
68
- getContextData: async (agentInfo, context) => {
69
- // Use the time plugin data if available
70
- const timeData = context?.plugins?.["time-plugin"] || {};
71
- return {
72
- message: "This is test context data",
73
- timestamp: Date.now(),
74
- pluginData: timeData
75
- };
76
- }
77
- };
78
- // Create a test widget
79
- const testWidget = {
80
- id: "test-widget",
81
- name: "Test Widget",
82
- description: "A test widget for plugin testing",
83
- icon: "🧪",
84
- getWidget: async (agentInfo, context) => {
85
- // Use the crypto plugin data if available
86
- const cryptoData = context?.plugins?.["crypto-plugin"] || {};
87
- return {
88
- text: "This is a test widget",
89
- data: {
90
- type: "text",
91
- content: "This is a test widget",
92
- timestamp: Date.now(),
93
- wallets: cryptoData?.wallets || []
94
- },
95
- ui: { type: "text" }
96
- };
97
- }
98
- };
99
- // Initialize the connection to the DAIN service with both plugins
100
- const dainConnection = new client_1.DainServiceConnection("http://localhost:4484", agentAuth, {
101
- plugins: [timePlugin, cryptoPlugin]
102
- });
103
- // Create a test tool
104
- const echoTool = (0, core_1.createTool)({
105
- id: "echo",
106
- name: "Echo Tool",
107
- description: "Echoes back the input with plugin data",
108
- input: zod_1.z.object({ message: zod_1.z.string() }),
109
- output: zod_1.z.object({ message: zod_1.z.string(), plugins: zod_1.z.any() }),
110
- handler: async ({ message }, agentInfo, context) => {
111
- console.log("Context:", JSON.stringify(context, null, 2));
112
- // Use the TimePlugin helper to get plugin data from context
113
- const timeData = timePlugin.getTimeDataFromContext(context);
114
- const clientTimezone = timePlugin.getClientTimezone(context);
115
- console.log(`Tool handling: received client timestamp ${timeData.clientTimestamp}`);
116
- if (clientTimezone) {
117
- console.log(`Client timezone: ${clientTimezone}`);
118
- }
119
- return {
120
- text: `Echoed: ${message}`,
121
- data: {
122
- message,
123
- plugins: context.extraData?.plugins || {}
124
- },
125
- ui: null,
126
- };
127
- },
128
- });
129
- // Initialize the DAIN service with both plugins
130
- const dainService = (0, nodeService_1.defineDAINService)({
131
- metadata: {
132
- title: "Plugin Test Service",
133
- description: "A DAIN service for testing plugins",
134
- version: "1.0.0",
135
- author: "Test Author",
136
- tags: ["plugin", "test"],
137
- },
138
- identity: {
139
- publicKey: bs58_1.default.encode(publicKey),
140
- agentId: "plugin-agent",
141
- orgId: "plugin-org",
142
- privateKey: bs58_1.default.encode(privateKey),
143
- },
144
- tools: [echoTool, walletInfoTool],
145
- plugins: [timePlugin, cryptoPlugin],
146
- contexts: [testContext],
147
- widgets: [testWidget],
148
- exampleQueries: [
149
- { category: "General", queries: ["How does this work?", "Show me the weather"] }
150
- ]
151
- });
152
- let server;
153
- beforeAll(async () => {
154
- server = await dainService.startNode({ port: 4484 });
155
- await new Promise(resolve => setTimeout(resolve, 500)); // Give server time to start
156
- });
157
- afterAll(async () => {
158
- await server.shutdown();
159
- });
160
- it("should process plugin data in requests and responses", async () => {
161
- // Call the echo tool with a message
162
- const result = await dainConnection.callTool("echo", { message: "Hello, plugins!" });
163
- console.log("Tool result:", JSON.stringify(result, null, 2));
164
- // Verify that the message was echoed correctly
165
- expect(result.data.message).toBe("Hello, plugins!");
166
- // Verify that the time plugin data is in the response
167
- expect(result.plugins).toBeDefined();
168
- expect(result.plugins["time-plugin"]).toBeDefined();
169
- // Use the TimePlugin helper to get typed response data
170
- const timeData = timePlugin.getResponseData(result);
171
- expect(timeData).toBeDefined();
172
- // Check the time plugin data
173
- expect(timeData.clientTimestamp).toBeDefined();
174
- expect(timeData.serviceTimestamp).toBeDefined();
175
- expect(timeData.roundtripTime).toBeDefined();
176
- expect(timeData.timezone).toBeDefined();
177
- // The service timestamp should be later than the client timestamp
178
- expect(timeData.serviceTimestamp).toBeGreaterThanOrEqual(timeData.clientTimestamp);
179
- // The roundtrip time should be non-negative
180
- expect(timeData.roundtripTime).toBeGreaterThanOrEqual(0);
181
- // The timezone should be a non-empty string
182
- expect(typeof timeData.timezone).toBe("string");
183
- expect(timeData.timezone.length).toBeGreaterThan(0);
184
- console.log("Time plugin data:", timeData);
185
- // Use TimePlugin's helper methods for displaying timestamps nicely
186
- console.log(`Request started at: ${timePlugin.formatTimestamp(timeData.clientTimestamp)}`);
187
- console.log(`Response created at: ${timePlugin.formatTimestamp(timeData.serviceTimestamp)}`);
188
- console.log(`Roundtrip time: ${timeData.roundtripTime}ms`);
189
- console.log(`Client timezone: ${timeData.timezone}`);
190
- // Demonstrate the elapsed time calculation helper
191
- const processingTime = timePlugin.calculateElapsedTime(timeData.clientTimestamp, timeData.serviceTimestamp);
192
- console.log(`Service processing time: ${processingTime}ms`);
193
- });
194
- it("should verify crypto plugin automatically sends wallet data to server", async () => {
195
- // Call the wallet info tool
196
- const result = await dainConnection.callTool("wallet-info", {});
197
- console.log("Wallet info result:", JSON.stringify(result, null, 2));
198
- // Verify that wallet information was received by the service
199
- expect(result.data.walletsCount).toBe(testWallets.length);
200
- expect(result.data.connectedWallets.length).toBe(testWallets.length);
201
- // Check that the wallet information matches what we provided
202
- const solWallet = result.data.connectedWallets.find(w => w.chain === "sol");
203
- expect(solWallet).toBeDefined();
204
- expect(solWallet?.address).toBe("SolTestAddress123456789");
205
- const ethWallet = result.data.connectedWallets.find(w => w.chain === "eth");
206
- expect(ethWallet).toBeDefined();
207
- expect(ethWallet?.address).toBe("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
208
- // Verify that time plugin data is also present in the response
209
- // This confirms both plugins work together
210
- expect(result.plugins).toBeDefined();
211
- expect(result.plugins["time-plugin"]).toBeDefined();
212
- console.log("Wallet information was successfully transferred from client to service");
213
- });
214
- it("should work with streaming responses", async () => {
215
- const events = [];
216
- // Call the echo tool with streaming enabled
217
- const result = await dainConnection.callTool("echo", { message: "Hello with streaming!" }, {
218
- onUIUpdate: (update) => {
219
- events.push({ type: 'ui', timestamp: Date.now(), data: update });
220
- }
221
- });
222
- // Add the final result to the events
223
- events.push({ type: 'result', timestamp: Date.now(), data: result });
224
- // Verify the result has plugin data
225
- expect(result.plugins).toBeDefined();
226
- expect(result.plugins["time-plugin"]).toBeDefined();
227
- // Get typed plugin data using helper
228
- const timeData = timePlugin.getResponseData(result);
229
- expect(timeData).toBeDefined();
230
- expect(timeData.roundtripTime).toBeDefined();
231
- console.log("Streaming result time data:", timeData);
232
- console.log(`Streaming roundtrip time: ${timeData.roundtripTime}ms`);
233
- });
234
- it("should work when calling a tool and getting context", async () => {
235
- // Call the echo tool and get context
236
- const result = await dainConnection.callToolAndGetNewContext("echo", {
237
- message: "Hello with context!"
238
- });
239
- // Verify the result has plugin data
240
- expect(result.plugins).toBeDefined();
241
- expect(result.plugins["time-plugin"]).toBeDefined();
242
- // Get typed plugin data using helper
243
- const timeData = timePlugin.getResponseData(result);
244
- expect(timeData).toBeDefined();
245
- expect(timeData.roundtripTime).toBeDefined();
246
- // Verify the tool result
247
- expect(result.toolResult.data.message).toBe("Hello with context!");
248
- console.log("Context result time data:", timeData);
249
- console.log(`Context roundtrip time: ${timeData.roundtripTime}ms`);
250
- });
251
- it("should use helper methods to create custom time responses", async () => {
252
- // Create a mock context with plugin data
253
- const mockContext = {
254
- extraData: {
255
- plugins: {
256
- "time-plugin": {
257
- clientTimestamp: Date.now() - 100, // 100ms ago
258
- timezone: "Europe/London"
259
- }
260
- }
261
- }
262
- };
263
- // Use helper to extract the plugin data
264
- const inputData = timePlugin.getTimeDataFromContext(mockContext);
265
- expect(inputData.clientTimestamp).toBeDefined();
266
- expect(inputData.timezone).toBe("Europe/London");
267
- // Use helper to create a response
268
- const response = timePlugin.createTimestampResponse(inputData);
269
- expect(response.clientTimestamp).toBe(inputData.clientTimestamp);
270
- expect(response.serviceTimestamp).toBeDefined();
271
- expect(response.timezone).toBe("Europe/London");
272
- // Calculate processing time
273
- const processingTime = timePlugin.calculateElapsedTime(response.clientTimestamp, response.serviceTimestamp);
274
- console.log(`Mock request: client timestamp is ${timePlugin.formatTimestamp(inputData.clientTimestamp)}`);
275
- console.log(`Mock response: service timestamp is ${timePlugin.formatTimestamp(response.serviceTimestamp)}`);
276
- console.log(`Mock processing time: ${processingTime}ms`);
277
- });
278
- it("should demonstrate the createResponse method for plugin responses", async () => {
279
- console.log("=== DEMONSTRATING createResponse METHOD ===");
280
- // Scenario 1: Create a minimal response with just required fields
281
- const minimalResponse = timePlugin.createResponse({
282
- clientTimestamp: 1742160000000,
283
- serviceTimestamp: 1742160000050
284
- });
285
- console.log("Minimal Response:", minimalResponse);
286
- expect(minimalResponse.clientTimestamp).toBe(1742160000000);
287
- expect(minimalResponse.serviceTimestamp).toBe(1742160000050);
288
- expect(minimalResponse.timezone).toBeUndefined();
289
- expect(minimalResponse.roundtripTime).toBeUndefined();
290
- // Scenario 2: Create a complete response with all fields
291
- const completeResponse = timePlugin.createResponse({
292
- clientTimestamp: 1742160000100,
293
- serviceTimestamp: 1742160000150,
294
- timezone: "America/Chicago",
295
- roundtripTime: 75
296
- });
297
- console.log("Complete Response:", completeResponse);
298
- expect(completeResponse.clientTimestamp).toBe(1742160000100);
299
- expect(completeResponse.serviceTimestamp).toBe(1742160000150);
300
- expect(completeResponse.timezone).toBe("America/Chicago");
301
- expect(completeResponse.roundtripTime).toBe(75);
302
- // Scenario 3: Using createResponse to transform or annotate data
303
- const rawData = {
304
- clientTimestamp: Date.now() - 200,
305
- serviceTimestamp: Date.now() - 100
306
- };
307
- // Add a timezone and calculate a roundtrip time
308
- const enhancedResponse = timePlugin.createResponse({
309
- ...rawData,
310
- timezone: "UTC",
311
- roundtripTime: rawData.serviceTimestamp - rawData.clientTimestamp
312
- });
313
- console.log("Enhanced Response:", enhancedResponse);
314
- expect(enhancedResponse.timezone).toBe("UTC");
315
- expect(enhancedResponse.roundtripTime).toBe(100);
316
- // Scenario 4: Practical example - modifying an existing plugin response
317
- const existingResponse = {
318
- clientTimestamp: 1742160000200,
319
- serviceTimestamp: 1742160000300,
320
- timezone: "Europe/Berlin"
321
- };
322
- // Add roundtrip time to an existing response
323
- const updatedResponse = timePlugin.createResponse({
324
- ...existingResponse,
325
- roundtripTime: 120 // Custom roundtrip calculation
326
- });
327
- console.log("Updated Response:", updatedResponse);
328
- expect(updatedResponse).toEqual({
329
- clientTimestamp: 1742160000200,
330
- serviceTimestamp: 1742160000300,
331
- timezone: "Europe/Berlin",
332
- roundtripTime: 120
333
- });
334
- // Scenario 5: Integration with other helper methods
335
- const now = Date.now();
336
- const sampleInput = { clientTimestamp: now - 150, timezone: "Asia/Tokyo" };
337
- // Create a response using multiple helper methods together
338
- const integratedResponse = timePlugin.createResponse({
339
- clientTimestamp: sampleInput.clientTimestamp,
340
- serviceTimestamp: now,
341
- timezone: sampleInput.timezone,
342
- roundtripTime: timePlugin.calculateElapsedTime(sampleInput.clientTimestamp, now)
343
- });
344
- console.log("Integrated Response:", integratedResponse);
345
- console.log(`From ${timePlugin.formatTimestamp(integratedResponse.clientTimestamp)}`);
346
- console.log(`To ${timePlugin.formatTimestamp(integratedResponse.serviceTimestamp)}`);
347
- console.log(`Elapsed: ${integratedResponse.roundtripTime}ms in ${integratedResponse.timezone}`);
348
- expect(integratedResponse.roundtripTime).toBe(150);
349
- expect(integratedResponse.timezone).toBe("Asia/Tokyo");
350
- });
351
- it("should demonstrate practical usage of createTimingResponse for real-world scenarios", async () => {
352
- console.log("\n=== DEMONSTRATING PRACTICAL USAGE OF TIME PLUGIN ===\n");
353
- // Example 1: Measuring execution time of an expensive operation
354
- const simulateExpensiveOperation = async (duration) => {
355
- return new Promise(resolve => setTimeout(() => resolve(`Operation completed`), duration));
356
- };
357
- console.log("Example 1: Measuring database query performance");
358
- console.log("----------------------------------------------");
359
- const dbQueryStart = Date.now();
360
- // Simulate a database query that takes 50ms
361
- await simulateExpensiveOperation(50);
362
- // Generate timing information for this operation
363
- const dbQueryTiming = timePlugin.createTimingResponse(dbQueryStart, {
364
- operationType: "database-query",
365
- includeTimezone: true,
366
- metadata: {
367
- table: "users",
368
- rowsReturned: 250,
369
- indexUsed: "user_id_idx"
370
- }
371
- });
372
- console.log(`Database query timing: ${JSON.stringify(dbQueryTiming, null, 2)}`);
373
- console.log(`Query started at: ${timePlugin.formatTimestamp(dbQueryTiming.clientTimestamp)}`);
374
- console.log(`Query completed at: ${timePlugin.formatTimestamp(dbQueryTiming.serviceTimestamp)}`);
375
- console.log(`Query took approximately: ${dbQueryTiming.roundtripTime}ms`);
376
- expect(dbQueryTiming.roundtripTime).toBeGreaterThanOrEqual(50);
377
- expect(dbQueryTiming.timezone).toBeDefined();
378
- // Example 2: API request/response cycle with multiple operations
379
- console.log("\nExample 2: Full API request cycle with multiple operations");
380
- console.log("------------------------------------------------------");
381
- // Simulate a complete API request handler with multiple operations
382
- const handleApiRequest = async (requestData) => {
383
- // 1. Record request start time
384
- const requestStart = Date.now();
385
- // 2. Validate request (10ms)
386
- await simulateExpensiveOperation(10);
387
- const validationTiming = timePlugin.createTimingResponse(requestStart, {
388
- operationType: "request-validation"
389
- });
390
- // 3. Process data (30ms)
391
- const processingStart = Date.now();
392
- await simulateExpensiveOperation(30);
393
- const processingTiming = timePlugin.createTimingResponse(processingStart, {
394
- operationType: "data-processing"
395
- });
396
- // 4. Generate response with detailed timing information
397
- return {
398
- data: { result: "Success", id: requestData.id },
399
- timing: {
400
- total: timePlugin.createTimingResponse(requestStart),
401
- validation: validationTiming,
402
- processing: processingTiming
403
- }
404
- };
405
- };
406
- // Simulate an API request
407
- const apiResponse = await handleApiRequest({ id: 12345, action: "getData" });
408
- console.log("API Response:", JSON.stringify(apiResponse, null, 2));
409
- console.log(`Total request time: ${apiResponse.timing.total.roundtripTime}ms`);
410
- console.log(`- Validation time: ${apiResponse.timing.validation.roundtripTime}ms`);
411
- console.log(`- Processing time: ${apiResponse.timing.processing.roundtripTime}ms`);
412
- expect(apiResponse.timing.total.roundtripTime).toBeGreaterThanOrEqual(40);
413
- expect(apiResponse.timing.validation.roundtripTime).toBeGreaterThanOrEqual(10);
414
- expect(apiResponse.timing.processing.roundtripTime).toBeGreaterThanOrEqual(30);
415
- // Show how this would be integrated into a real DAIN plugin response
416
- const pluginResponse = {
417
- data: apiResponse.data,
418
- plugins: {
419
- "time-plugin": timePlugin.createTimingResponse(apiResponse.timing.total.clientTimestamp, {
420
- includeTimezone: true
421
- })
422
- }
423
- };
424
- console.log("\nFinal plugin response:");
425
- console.log(JSON.stringify(pluginResponse, null, 2));
426
- expect(pluginResponse.plugins["time-plugin"].roundtripTime).toBeGreaterThanOrEqual(40);
427
- expect(pluginResponse.plugins["time-plugin"].timezone).toBeDefined();
428
- });
429
- it("should verify multiple plugins can work together and consistently provide data", async () => {
430
- // We'll call wallet-info tool multiple times sequentially to ensure different timestamps
431
- const result1 = await dainConnection.callTool("wallet-info", {});
432
- // Small delay to ensure different timestamps
433
- await new Promise(resolve => setTimeout(resolve, 10));
434
- const result2 = await dainConnection.callTool("wallet-info", {});
435
- await new Promise(resolve => setTimeout(resolve, 10));
436
- const result3 = await dainConnection.callTool("wallet-info", {});
437
- const results = [result1, result2, result3];
438
- // Verify all calls received wallet data
439
- results.forEach((result, index) => {
440
- console.log(`Call ${index + 1} wallet count:`, result.data.walletsCount);
441
- expect(result.data.walletsCount).toBe(testWallets.length);
442
- // Each call should also have time plugin data
443
- expect(result.plugins["time-plugin"]).toBeDefined();
444
- // Times should be different for each call (now that we're using sequential requests)
445
- if (index > 0) {
446
- const prevTimeData = timePlugin.getResponseData(results[index - 1]);
447
- const currTimeData = timePlugin.getResponseData(result);
448
- // With sequential requests and delay, timestamps should now be different
449
- expect(currTimeData?.clientTimestamp).not.toBe(prevTimeData?.clientTimestamp);
450
- expect(currTimeData?.serviceTimestamp).not.toBe(prevTimeData?.serviceTimestamp);
451
- }
452
- });
453
- // Modify wallet data during the test
454
- const newWallet = { chain: "arb", address: "0xArbTestWalletAddress" };
455
- cryptoPlugin.addWallet(newWallet);
456
- // Call again and verify the new wallet data was sent
457
- const finalResult = await dainConnection.callTool("wallet-info", {});
458
- expect(finalResult.data.walletsCount).toBe(testWallets.length + 1); // Added one more wallet
459
- // Verify the new wallet is in the result
460
- const arbWallet = finalResult.data.connectedWallets.find(w => w.chain === "arb");
461
- expect(arbWallet).toBeDefined();
462
- expect(arbWallet?.address).toBe("0xArbTestWalletAddress");
463
- console.log("Multiple plugin test complete - wallet data is consistently provided");
464
- });
465
- it("should ensure getAllContexts returns an array when plugins are used", async () => {
466
- // Get all contexts using a connection with plugins enabled
467
- const contexts = await dainConnection.getAllContexts();
468
- // Log out the contexts for debugging
469
- console.log("Contexts with plugins:", contexts);
470
- // Verify that the result is an array
471
- expect(Array.isArray(contexts)).toBe(true);
472
- // Contexts might be empty in this test, but the type should be correct
473
- // The point is to verify we're not getting an object with plugins property instead of an array
474
- if (contexts.length > 0) {
475
- // If there are contexts, verify they have the expected structure
476
- expect(contexts[0]).toHaveProperty('id');
477
- expect(contexts[0]).toHaveProperty('name');
478
- expect(contexts[0]).toHaveProperty('description');
479
- expect(contexts[0]).toHaveProperty('data');
480
- }
481
- });
482
- it("should ensure getContext returns a context object when plugins are used", async () => {
483
- // Only run this test if there are contexts available
484
- const allContexts = await dainConnection.getAllContexts();
485
- if (allContexts.length === 0) {
486
- console.log("Skipping getContext test as no contexts are available");
487
- return;
488
- }
489
- // Get the first context using a connection with plugins enabled
490
- const contextId = allContexts[0].id;
491
- const context = await dainConnection.getContext(contextId);
492
- // Log out the context for debugging
493
- console.log("Context with plugins:", context);
494
- // Verify that the result is a context object, not a response with plugins
495
- expect(context).toHaveProperty('id');
496
- expect(context).toHaveProperty('name');
497
- expect(context).toHaveProperty('description');
498
- expect(context).toHaveProperty('data');
499
- // Make sure the context has the correct ID
500
- expect(context.id).toBe(contextId);
501
- });
502
- it("should ensure getAllWidgets returns an array when plugins are used", async () => {
503
- // Get all widgets using a connection with plugins enabled
504
- const widgets = await dainConnection.getAllWidgets();
505
- // Log out the widgets for debugging
506
- console.log("Widgets with plugins:", widgets);
507
- // Verify that the result is an array
508
- expect(Array.isArray(widgets)).toBe(true);
509
- // Widgets might be empty in this test, but the type should be correct
510
- // The point is to verify we're not getting an object with plugins property instead of an array
511
- if (widgets.length > 0) {
512
- // If there are widgets, verify they have the expected structure
513
- expect(widgets[0]).toHaveProperty('id');
514
- expect(widgets[0]).toHaveProperty('name');
515
- expect(widgets[0]).toHaveProperty('description');
516
- expect(widgets[0]).toHaveProperty('icon');
517
- expect(widgets[0]).toHaveProperty('text');
518
- }
519
- });
520
- it("should ensure getWidget returns a widget object when plugins are used", async () => {
521
- // Only run this test if there are widgets available
522
- const allWidgets = await dainConnection.getAllWidgets();
523
- if (allWidgets.length === 0) {
524
- console.log("Skipping getWidget test as no widgets are available");
525
- return;
526
- }
527
- // Get the first widget using a connection with plugins enabled
528
- const widgetId = allWidgets[0].id;
529
- const widget = await dainConnection.getWidget(widgetId);
530
- // Log out the widget for debugging
531
- console.log("Widget with plugins:", widget);
532
- // Verify that the result is a widget object, not a response with plugins
533
- expect(widget).toHaveProperty('id');
534
- expect(widget).toHaveProperty('name');
535
- expect(widget).toHaveProperty('description');
536
- expect(widget).toHaveProperty('icon');
537
- expect(widget).toHaveProperty('text');
538
- // Make sure the widget has the correct ID
539
- expect(widget.id).toBe(widgetId);
540
- });
541
- it("should ensure listDatasources and postAllDatasources handle plugins correctly", async () => {
542
- // Try calling the methods to ensure they work properly with plugins enabled
543
- const datasources1 = await dainConnection.listDatasources();
544
- expect(Array.isArray(datasources1)).toBe(true);
545
- const datasources2 = await dainConnection.postAllDatasources();
546
- expect(Array.isArray(datasources2)).toBe(true);
547
- });
548
- it("should ensure getDatasource returns a datasource object when plugins are used", async () => {
549
- // Skip the datasource test until we have a proper way to register datasources for testing
550
- console.log("Skipping active getDatasource test as it requires datasource registration");
551
- });
552
- it("should ensure getAllToolsAsJsonSchema properly handles plugin data", async () => {
553
- // Call getAllToolsAsJsonSchema with plugins enabled
554
- const result = await dainConnection.getAllToolsAsJsonSchema();
555
- // Log for debugging
556
- console.log("getAllToolsAsJsonSchema result:", result);
557
- // Verify the result structure
558
- expect(result).toHaveProperty('tools');
559
- expect(result).toHaveProperty('reccomendedPrompts');
560
- expect(Array.isArray(result.tools)).toBe(true);
561
- // Verify tools contain expected properties
562
- if (result.tools.length > 0) {
563
- const tool = result.tools[0];
564
- expect(tool).toHaveProperty('id');
565
- expect(tool).toHaveProperty('name');
566
- expect(tool).toHaveProperty('description');
567
- expect(tool).toHaveProperty('inputSchema');
568
- }
569
- // The plugins themselves shouldn't be in the result - they should be handled internally
570
- expect(result).not.toHaveProperty('plugins');
571
- });
572
- it("should ensure getMetadata properly handles plugin data", async () => {
573
- // Call getMetadata with plugins enabled
574
- const metadata = await dainConnection.getMetadata();
575
- // Log for debugging
576
- console.log("getMetadata result:", metadata);
577
- // Verify metadata structure
578
- expect(metadata).toHaveProperty('title');
579
- expect(metadata).toHaveProperty('description');
580
- expect(metadata).toHaveProperty('version');
581
- // The plugins themselves shouldn't be in the result - they should be handled internally
582
- expect(metadata).not.toHaveProperty('plugins');
583
- });
584
- it("should ensure getWidgets properly handles plugin data", async () => {
585
- // Call getWidgets with plugins enabled
586
- const widgets = await dainConnection.getWidgets();
587
- // Log for debugging
588
- console.log("getWidgets result:", widgets);
589
- // Verify the result is an array, even when plugins are used
590
- expect(Array.isArray(widgets)).toBe(true);
591
- // Verify widgets structure if any exist
592
- if (widgets.length > 0) {
593
- const widgetId = widgets[0];
594
- expect(typeof widgetId).toBe('string');
595
- }
596
- });
597
- it("should ensure getExampleQueries properly handles plugin data", async () => {
598
- // Call getExampleQueries with plugins enabled
599
- const queries = await dainConnection.getExampleQueries();
600
- // Log for debugging
601
- console.log("getExampleQueries result:", queries);
602
- // Verify the result is an array, even when plugins are used
603
- expect(Array.isArray(queries)).toBe(true);
604
- // The plugins themselves shouldn't be in the result - they should be handled internally
605
- if (queries.length > 0) {
606
- // Example queries can be strings or objects with category and queries
607
- const firstQuery = queries[0];
608
- if (typeof firstQuery === 'string') {
609
- expect(typeof firstQuery).toBe('string');
610
- }
611
- else {
612
- expect(firstQuery).toHaveProperty('category');
613
- expect(firstQuery).toHaveProperty('queries');
614
- expect(Array.isArray(firstQuery.queries)).toBe(true);
615
- }
616
- }
617
- });
618
- });
619
- /**
620
- * Additional plugin tests specifically for handling plugin data in API responses
621
- * Tests all API methods both with and without data, ensuring proper handling of plugin-wrapped responses
622
- */
623
- describe("Plugin Data Handling in API Responses", () => {
624
- // Generate keys for both services
625
- const fullPrivateKey = ed25519_1.ed25519.utils.randomPrivateKey();
626
- const fullPublicKey = ed25519_1.ed25519.getPublicKey(fullPrivateKey);
627
- const emptyPrivateKey = ed25519_1.ed25519.utils.randomPrivateKey();
628
- const emptyPublicKey = ed25519_1.ed25519.getPublicKey(emptyPrivateKey);
629
- // Client auth
630
- const clientPrivateKey = ed25519_1.ed25519.utils.randomPrivateKey();
631
- const clientAuth = new client_auth_1.DainClientAuth({
632
- privateKeyBase58: bs58_1.default.encode(clientPrivateKey),
633
- agentId: "api-client",
634
- orgId: "api-org",
635
- });
636
- // Create test plugins
637
- const timePlugin = new time_plugin_1.TimePlugin({ includeTimezone: true });
638
- const testWallets = [
639
- { chain: "sol", address: "ApiTestSolAddress123" }
640
- ];
641
- const cryptoPlugin = new crypto_plugin_1.CryptoPlugin(testWallets);
642
- // Create test context, pinnable, datasource
643
- const testContext = {
644
- id: "api-context",
645
- name: "API Test Context",
646
- description: "Context for API plugin tests",
647
- getContextData: async (agentInfo, context) => {
648
- // Include plugin data in the response for verification
649
- return {
650
- value: "Context data",
651
- timestamp: Date.now(),
652
- pluginInfo: context?.plugins || {}
653
- };
654
- }
655
- };
656
- const testWidget = {
657
- id: "api-widget",
658
- name: "API Test Widget",
659
- description: "Widget for API plugin tests",
660
- icon: "🔧",
661
- getWidget: async (agentInfo, context) => {
662
- return {
663
- text: "API Test Widget",
664
- data: {
665
- type: "text",
666
- content: "API Test Widget",
667
- timestamp: Date.now(),
668
- pluginInfo: context?.plugins || {}
669
- },
670
- ui: { type: "text" }
671
- };
672
- }
673
- };
674
- const testDatasource = {
675
- id: "api-datasource",
676
- name: "API Test Datasource",
677
- description: "Datasource for API plugin tests",
678
- type: "json",
679
- input: zod_1.z.object({
680
- query: zod_1.z.string().optional()
681
- }),
682
- getDatasource: async (agentInfo, params, context) => {
683
- return {
684
- results: ["Result 1", "Result 2"],
685
- timestamp: Date.now(),
686
- pluginInfo: context?.plugins || {}
687
- };
688
- }
689
- };
690
- // Create test tool
691
- const testTool = (0, core_1.createTool)({
692
- id: "api-tool",
693
- name: "API Test Tool",
694
- description: "Tool for API plugin tests",
695
- input: zod_1.z.object({ data: zod_1.z.string() }),
696
- output: zod_1.z.object({ result: zod_1.z.string() }),
697
- handler: async ({ data }, agentInfo, context) => {
698
- return {
699
- text: `Processed: ${data}`,
700
- data: {
701
- result: data,
702
- pluginInfo: context.extraData?.plugins || {}
703
- },
704
- ui: null
705
- };
706
- }
707
- });
708
- // Service with all data types
709
- const fullService = (0, nodeService_1.defineDAINService)({
710
- metadata: {
711
- title: "Full API Test Service",
712
- description: "Service with all data types for testing plugin handling",
713
- version: "1.0.0",
714
- author: "Test",
715
- tags: ["test"]
716
- },
717
- identity: {
718
- publicKey: bs58_1.default.encode(fullPublicKey),
719
- agentId: "full-agent",
720
- orgId: "full-org",
721
- privateKey: bs58_1.default.encode(fullPrivateKey)
722
- },
723
- tools: [testTool],
724
- plugins: [timePlugin, cryptoPlugin],
725
- contexts: [testContext],
726
- widgets: [testWidget],
727
- datasources: [testDatasource],
728
- exampleQueries: [
729
- { category: "Test", queries: ["Test query 1", "Test query 2"] }
730
- ]
731
- });
732
- // Service with minimal data
733
- const emptyService = (0, nodeService_1.defineDAINService)({
734
- metadata: {
735
- title: "Empty API Test Service",
736
- description: "Service with minimal data for testing plugin handling",
737
- version: "1.0.0",
738
- author: "Test",
739
- tags: ["test"]
740
- },
741
- identity: {
742
- publicKey: bs58_1.default.encode(emptyPublicKey),
743
- agentId: "empty-agent",
744
- orgId: "empty-org",
745
- privateKey: bs58_1.default.encode(emptyPrivateKey)
746
- },
747
- tools: [testTool],
748
- plugins: [timePlugin, cryptoPlugin],
749
- contexts: [],
750
- widgets: [],
751
- datasources: [],
752
- exampleQueries: []
753
- });
754
- // Client connections
755
- const fullConnection = new client_1.DainServiceConnection("http://localhost:4581", clientAuth, { plugins: [timePlugin, cryptoPlugin] });
756
- const emptyConnection = new client_1.DainServiceConnection("http://localhost:4582", clientAuth, { plugins: [timePlugin, cryptoPlugin] });
757
- // Server instances
758
- let fullServer;
759
- let emptyServer;
760
- beforeAll(async () => {
761
- fullServer = await fullService.startNode({ port: 4581 });
762
- emptyServer = await emptyService.startNode({ port: 4582 });
763
- await new Promise(resolve => setTimeout(resolve, 500)); // Server startup time
764
- });
765
- afterAll(async () => {
766
- await fullServer?.shutdown();
767
- await emptyServer?.shutdown();
768
- });
769
- // TEST METADATA
770
- it("getMetadata handles plugins with either service", async () => {
771
- // With data
772
- const fullMetadata = await fullConnection.getMetadata();
773
- expect(fullMetadata).toHaveProperty('title');
774
- expect(fullMetadata).not.toHaveProperty('plugins');
775
- // Without data
776
- const emptyMetadata = await emptyConnection.getMetadata();
777
- expect(emptyMetadata).toHaveProperty('title');
778
- expect(emptyMetadata).not.toHaveProperty('plugins');
779
- });
780
- // TEST TOOLS
781
- it("getTools handles plugins with either service", async () => {
782
- // With data
783
- const fullTools = await fullConnection.getTools();
784
- expect(Array.isArray(fullTools)).toBe(true);
785
- expect(fullTools.length).toBeGreaterThan(0);
786
- expect(fullTools[0]).not.toHaveProperty('plugins');
787
- // Without data
788
- const emptyTools = await emptyConnection.getTools();
789
- expect(Array.isArray(emptyTools)).toBe(true);
790
- expect(emptyTools.length).toBeGreaterThan(0);
791
- expect(emptyTools[0]).not.toHaveProperty('plugins');
792
- });
793
- it("getAllToolsAsJsonSchema handles plugins with either service", async () => {
794
- // With data
795
- const fullTools = await fullConnection.getAllToolsAsJsonSchema();
796
- expect(fullTools).toHaveProperty('tools');
797
- expect(Array.isArray(fullTools.tools)).toBe(true);
798
- expect(fullTools).not.toHaveProperty('plugins');
799
- // Without data
800
- const emptyTools = await emptyConnection.getAllToolsAsJsonSchema();
801
- expect(emptyTools).toHaveProperty('tools');
802
- expect(Array.isArray(emptyTools.tools)).toBe(true);
803
- expect(emptyTools).not.toHaveProperty('plugins');
804
- });
805
- // TEST CONTEXTS
806
- it("getAllContexts handles plugins with either service", async () => {
807
- // With data
808
- const fullContexts = await fullConnection.getAllContexts();
809
- expect(Array.isArray(fullContexts)).toBe(true);
810
- expect(fullContexts.length).toBeGreaterThan(0);
811
- expect(fullContexts[0]).toHaveProperty('data');
812
- expect(fullContexts[0]).not.toHaveProperty('plugins');
813
- // Without data - should return empty array, not object with plugins
814
- const emptyContexts = await emptyConnection.getAllContexts();
815
- expect(Array.isArray(emptyContexts)).toBe(true);
816
- expect(emptyContexts.length).toBe(0);
817
- });
818
- it("getContext handles plugins with full service", async () => {
819
- const contexts = await fullConnection.getAllContexts();
820
- const context = await fullConnection.getContext(contexts[0].id);
821
- expect(context).toHaveProperty('id');
822
- expect(context).toHaveProperty('data');
823
- expect(context).not.toHaveProperty('plugins');
824
- // Context data should have the structure defined in testContext
825
- expect(context.data).toHaveProperty('value');
826
- expect(context.data).toHaveProperty('timestamp');
827
- });
828
- // TEST WIDGETS
829
- it("getAllWidgets handles plugins with either service", async () => {
830
- // With data
831
- const fullWidgets = await fullConnection.getAllWidgets();
832
- expect(Array.isArray(fullWidgets)).toBe(true);
833
- expect(fullWidgets.length).toBeGreaterThan(0);
834
- expect(fullWidgets[0]).toHaveProperty('icon');
835
- expect(fullWidgets[0]).toHaveProperty('text');
836
- expect(fullWidgets[0]).not.toHaveProperty('plugins');
837
- // Without data - should return empty array, not object with plugins
838
- const emptyWidgets = await emptyConnection.getAllWidgets();
839
- expect(Array.isArray(emptyWidgets)).toBe(true);
840
- expect(emptyWidgets.length).toBe(0);
841
- });
842
- it("getWidget handles plugins with full service", async () => {
843
- const widgets = await fullConnection.getAllWidgets();
844
- const widget = await fullConnection.getWidget(widgets[0].id);
845
- expect(widget).toHaveProperty('id');
846
- expect(widget).toHaveProperty('icon');
847
- expect(widget).toHaveProperty('text');
848
- expect(widget).not.toHaveProperty('plugins');
849
- // Widget data should have the structure defined in testWidget or be empty
850
- // Some implementations might return empty widget objects in tests
851
- if (widget.data && Object.keys(widget.data).length > 0) {
852
- expect(widget.data).toHaveProperty('content');
853
- expect(widget.data).toHaveProperty('timestamp');
854
- }
855
- });
856
- it("getWidgets handles plugins with either service", async () => {
857
- // With data
858
- const fullWidgetIds = await fullConnection.getWidgets();
859
- expect(Array.isArray(fullWidgetIds)).toBe(true);
860
- expect(fullWidgetIds.length).toBeGreaterThan(0);
861
- expect(typeof fullWidgetIds[0]).toBe('string');
862
- // Without data
863
- const emptyWidgetIds = await emptyConnection.getWidgets();
864
- expect(Array.isArray(emptyWidgetIds)).toBe(true);
865
- expect(emptyWidgetIds.length).toBe(0);
866
- });
867
- // TEST DATASOURCES
868
- it("listDatasources handles plugins with either service", async () => {
869
- // With data
870
- const fullDatasources = await fullConnection.listDatasources();
871
- expect(Array.isArray(fullDatasources)).toBe(true);
872
- expect(fullDatasources.length).toBeGreaterThan(0);
873
- expect(fullDatasources[0]).not.toHaveProperty('plugins');
874
- // Without data
875
- const emptyDatasources = await emptyConnection.listDatasources();
876
- expect(Array.isArray(emptyDatasources)).toBe(true);
877
- expect(emptyDatasources.length).toBe(0);
878
- });
879
- it("getDatasource handles plugins with full service", async () => {
880
- const datasource = await fullConnection.getDatasource("api-datasource", { query: "test" });
881
- expect(datasource).toHaveProperty('id');
882
- expect(datasource).toHaveProperty('data');
883
- expect(datasource).not.toHaveProperty('plugins');
884
- // Datasource data should have the structure defined in testDatasource
885
- expect(datasource.data).toHaveProperty('results');
886
- expect(Array.isArray(datasource.data.results)).toBe(true);
887
- });
888
- // TEST EXAMPLE QUERIES
889
- it("getExampleQueries handles plugins with either service", async () => {
890
- // With data
891
- const fullQueries = await fullConnection.getExampleQueries();
892
- expect(Array.isArray(fullQueries)).toBe(true);
893
- expect(fullQueries.length).toBeGreaterThan(0);
894
- // Without data
895
- const emptyQueries = await emptyConnection.getExampleQueries();
896
- expect(Array.isArray(emptyQueries)).toBe(true);
897
- expect(emptyQueries.length).toBe(0);
898
- });
899
- });
900
- //# sourceMappingURL=plugin.test.js.map