@framers/agentos-ext-cloud-digitalocean 0.1.0 → 0.1.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/manifest.json +2 -2
- package/package.json +14 -6
- package/src/DigitalOceanService.ts +0 -514
- package/src/index.ts +0 -130
- package/src/tools/createApp.ts +0 -69
- package/src/tools/createDroplet.ts +0 -74
- package/src/tools/deleteResource.ts +0 -64
- package/src/tools/deployApp.ts +0 -41
- package/src/tools/listResources.ts +0 -66
- package/src/tools/manageDns.ts +0 -131
- package/test/DigitalOceanService.test.ts +0 -435
- package/test/index.test.ts +0 -58
- package/test/tools.test.ts +0 -478
- package/tsconfig.json +0 -22
package/test/tools.test.ts
DELETED
|
@@ -1,478 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
3
|
-
import { DOCreateAppTool } from '../src/tools/createApp.js';
|
|
4
|
-
import { DOCreateDropletTool } from '../src/tools/createDroplet.js';
|
|
5
|
-
import { DODeleteResourceTool } from '../src/tools/deleteResource.js';
|
|
6
|
-
import { DODeployAppTool } from '../src/tools/deployApp.js';
|
|
7
|
-
import { DOListResourcesTool } from '../src/tools/listResources.js';
|
|
8
|
-
import { DOManageDnsTool } from '../src/tools/manageDns.js';
|
|
9
|
-
import type { DigitalOceanService } from '../src/DigitalOceanService.js';
|
|
10
|
-
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// Mock service factory
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
|
|
15
|
-
function createMockService(): DigitalOceanService {
|
|
16
|
-
return {
|
|
17
|
-
createApp: vi.fn(),
|
|
18
|
-
createDroplet: vi.fn(),
|
|
19
|
-
deleteApp: vi.fn(),
|
|
20
|
-
deleteDroplet: vi.fn(),
|
|
21
|
-
createDeployment: vi.fn(),
|
|
22
|
-
listApps: vi.fn(),
|
|
23
|
-
listDroplets: vi.fn(),
|
|
24
|
-
listDomains: vi.fn(),
|
|
25
|
-
addDomain: vi.fn(),
|
|
26
|
-
listDomainRecords: vi.fn(),
|
|
27
|
-
createDomainRecord: vi.fn(),
|
|
28
|
-
updateDomainRecord: vi.fn(),
|
|
29
|
-
deleteDomainRecord: vi.fn(),
|
|
30
|
-
} as unknown as DigitalOceanService;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
// DOCreateAppTool
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
|
|
37
|
-
describe('DOCreateAppTool', () => {
|
|
38
|
-
let service: DigitalOceanService;
|
|
39
|
-
let tool: DOCreateAppTool;
|
|
40
|
-
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
service = createMockService();
|
|
43
|
-
tool = new DOCreateAppTool(service);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should have correct id and name', () => {
|
|
47
|
-
expect(tool.id).toBe('doCreateApp');
|
|
48
|
-
expect(tool.name).toBe('doCreateApp');
|
|
49
|
-
expect(tool.displayName).toBe('Create DO App');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should require name and gitUrl', () => {
|
|
53
|
-
expect(tool.inputSchema.required).toContain('name');
|
|
54
|
-
expect(tool.inputSchema.required).toContain('gitUrl');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should return app on success', async () => {
|
|
58
|
-
const mockApp = { id: 'app-1', name: 'my-app', defaultIngress: 'https://my-app.ondigitalocean.app' };
|
|
59
|
-
(service.createApp as ReturnType<typeof vi.fn>).mockResolvedValue(mockApp);
|
|
60
|
-
|
|
61
|
-
const result = await tool.execute({
|
|
62
|
-
name: 'my-app',
|
|
63
|
-
gitUrl: 'https://github.com/user/repo',
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
expect(result.success).toBe(true);
|
|
67
|
-
expect(result.data).toEqual(mockApp);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should forward all optional parameters', async () => {
|
|
71
|
-
(service.createApp as ReturnType<typeof vi.fn>).mockResolvedValue({});
|
|
72
|
-
|
|
73
|
-
await tool.execute({
|
|
74
|
-
name: 'my-app',
|
|
75
|
-
gitUrl: 'https://github.com/user/repo',
|
|
76
|
-
branch: 'develop',
|
|
77
|
-
region: 'sfo',
|
|
78
|
-
buildCommand: 'npm run build',
|
|
79
|
-
runCommand: 'npm start',
|
|
80
|
-
outputDir: 'dist',
|
|
81
|
-
isStatic: true,
|
|
82
|
-
envVars: { NODE_ENV: 'production' },
|
|
83
|
-
instanceSizeSlug: 'basic-xs',
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
expect(service.createApp).toHaveBeenCalledWith(
|
|
87
|
-
expect.objectContaining({
|
|
88
|
-
branch: 'develop',
|
|
89
|
-
region: 'sfo',
|
|
90
|
-
isStatic: true,
|
|
91
|
-
instanceSizeSlug: 'basic-xs',
|
|
92
|
-
}),
|
|
93
|
-
);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should return error on failure', async () => {
|
|
97
|
-
(service.createApp as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Quota exceeded'));
|
|
98
|
-
|
|
99
|
-
const result = await tool.execute({ name: 'app', gitUrl: 'https://github.com/u/r' });
|
|
100
|
-
|
|
101
|
-
expect(result.success).toBe(false);
|
|
102
|
-
expect(result.error).toBe('Quota exceeded');
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// ---------------------------------------------------------------------------
|
|
107
|
-
// DOCreateDropletTool
|
|
108
|
-
// ---------------------------------------------------------------------------
|
|
109
|
-
|
|
110
|
-
describe('DOCreateDropletTool', () => {
|
|
111
|
-
let service: DigitalOceanService;
|
|
112
|
-
let tool: DOCreateDropletTool;
|
|
113
|
-
|
|
114
|
-
beforeEach(() => {
|
|
115
|
-
service = createMockService();
|
|
116
|
-
tool = new DOCreateDropletTool(service);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should have correct id and name', () => {
|
|
120
|
-
expect(tool.id).toBe('doCreateDroplet');
|
|
121
|
-
expect(tool.name).toBe('doCreateDroplet');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should require name, region, size, and image', () => {
|
|
125
|
-
expect(tool.inputSchema.required).toEqual(['name', 'region', 'size', 'image']);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('should return droplet on success', async () => {
|
|
129
|
-
const mockDroplet = { id: 12345, name: 'my-server', status: 'new', region: { slug: 'nyc1' } };
|
|
130
|
-
(service.createDroplet as ReturnType<typeof vi.fn>).mockResolvedValue(mockDroplet);
|
|
131
|
-
|
|
132
|
-
const result = await tool.execute({
|
|
133
|
-
name: 'my-server',
|
|
134
|
-
region: 'nyc1',
|
|
135
|
-
size: 's-1vcpu-1gb',
|
|
136
|
-
image: 'ubuntu-24-04-x64',
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
expect(result.success).toBe(true);
|
|
140
|
-
expect(result.data).toEqual(mockDroplet);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should forward ssh keys and tags', async () => {
|
|
144
|
-
(service.createDroplet as ReturnType<typeof vi.fn>).mockResolvedValue({});
|
|
145
|
-
|
|
146
|
-
await tool.execute({
|
|
147
|
-
name: 'srv',
|
|
148
|
-
region: 'sfo3',
|
|
149
|
-
size: 's-2vcpu-4gb',
|
|
150
|
-
image: 'debian-12-x64',
|
|
151
|
-
sshKeys: ['fingerprint1'],
|
|
152
|
-
tags: ['web', 'prod'],
|
|
153
|
-
backups: true,
|
|
154
|
-
ipv6: true,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
expect(service.createDroplet).toHaveBeenCalledWith(
|
|
158
|
-
expect.objectContaining({
|
|
159
|
-
sshKeys: ['fingerprint1'],
|
|
160
|
-
tags: ['web', 'prod'],
|
|
161
|
-
backups: true,
|
|
162
|
-
ipv6: true,
|
|
163
|
-
}),
|
|
164
|
-
);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should return error on failure', async () => {
|
|
168
|
-
(service.createDroplet as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Invalid size'));
|
|
169
|
-
|
|
170
|
-
const result = await tool.execute({
|
|
171
|
-
name: 'srv', region: 'nyc1', size: 'invalid', image: 'ubuntu',
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
expect(result.success).toBe(false);
|
|
175
|
-
expect(result.error).toBe('Invalid size');
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// ---------------------------------------------------------------------------
|
|
180
|
-
// DODeleteResourceTool
|
|
181
|
-
// ---------------------------------------------------------------------------
|
|
182
|
-
|
|
183
|
-
describe('DODeleteResourceTool', () => {
|
|
184
|
-
let service: DigitalOceanService;
|
|
185
|
-
let tool: DODeleteResourceTool;
|
|
186
|
-
|
|
187
|
-
beforeEach(() => {
|
|
188
|
-
service = createMockService();
|
|
189
|
-
tool = new DODeleteResourceTool(service);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('should have correct id and name', () => {
|
|
193
|
-
expect(tool.id).toBe('doDeleteResource');
|
|
194
|
-
expect(tool.name).toBe('doDeleteResource');
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('should require resourceType and resourceId', () => {
|
|
198
|
-
expect(tool.inputSchema.required).toContain('resourceType');
|
|
199
|
-
expect(tool.inputSchema.required).toContain('resourceId');
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should delete an app', async () => {
|
|
203
|
-
(service.deleteApp as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
|
|
204
|
-
|
|
205
|
-
const result = await tool.execute({ resourceType: 'app', resourceId: 'app-uuid-123' });
|
|
206
|
-
|
|
207
|
-
expect(result.success).toBe(true);
|
|
208
|
-
expect(result.data?.message).toContain('app-uuid-123');
|
|
209
|
-
expect(service.deleteApp).toHaveBeenCalledWith('app-uuid-123');
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('should delete a droplet', async () => {
|
|
213
|
-
(service.deleteDroplet as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
|
|
214
|
-
|
|
215
|
-
const result = await tool.execute({ resourceType: 'droplet', resourceId: '12345' });
|
|
216
|
-
|
|
217
|
-
expect(result.success).toBe(true);
|
|
218
|
-
expect(service.deleteDroplet).toHaveBeenCalledWith(12345);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it('should return error for invalid droplet ID', async () => {
|
|
222
|
-
const result = await tool.execute({ resourceType: 'droplet', resourceId: 'not-a-number' });
|
|
223
|
-
|
|
224
|
-
expect(result.success).toBe(false);
|
|
225
|
-
expect(result.error).toContain('Invalid droplet ID');
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('should return error on service failure', async () => {
|
|
229
|
-
(service.deleteApp as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Not found'));
|
|
230
|
-
|
|
231
|
-
const result = await tool.execute({ resourceType: 'app', resourceId: 'bad-id' });
|
|
232
|
-
|
|
233
|
-
expect(result.success).toBe(false);
|
|
234
|
-
expect(result.error).toBe('Not found');
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
|
-
// DODeployAppTool
|
|
240
|
-
// ---------------------------------------------------------------------------
|
|
241
|
-
|
|
242
|
-
describe('DODeployAppTool', () => {
|
|
243
|
-
let service: DigitalOceanService;
|
|
244
|
-
let tool: DODeployAppTool;
|
|
245
|
-
|
|
246
|
-
beforeEach(() => {
|
|
247
|
-
service = createMockService();
|
|
248
|
-
tool = new DODeployAppTool(service);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('should have correct id and name', () => {
|
|
252
|
-
expect(tool.id).toBe('doDeployApp');
|
|
253
|
-
expect(tool.name).toBe('doDeployApp');
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('should require appId', () => {
|
|
257
|
-
expect(tool.inputSchema.required).toContain('appId');
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it('should return deployment on success', async () => {
|
|
261
|
-
const mockDeployment = { id: 'dep-1', phase: 'BUILDING', progress: {} };
|
|
262
|
-
(service.createDeployment as ReturnType<typeof vi.fn>).mockResolvedValue(mockDeployment);
|
|
263
|
-
|
|
264
|
-
const result = await tool.execute({ appId: 'app-1' });
|
|
265
|
-
|
|
266
|
-
expect(result.success).toBe(true);
|
|
267
|
-
expect(result.data).toEqual(mockDeployment);
|
|
268
|
-
expect(service.createDeployment).toHaveBeenCalledWith('app-1', undefined);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('should pass forceBuild parameter', async () => {
|
|
272
|
-
(service.createDeployment as ReturnType<typeof vi.fn>).mockResolvedValue({});
|
|
273
|
-
|
|
274
|
-
await tool.execute({ appId: 'app-1', forceBuild: true });
|
|
275
|
-
|
|
276
|
-
expect(service.createDeployment).toHaveBeenCalledWith('app-1', true);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('should return error on failure', async () => {
|
|
280
|
-
(service.createDeployment as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('App suspended'));
|
|
281
|
-
|
|
282
|
-
const result = await tool.execute({ appId: 'bad-app' });
|
|
283
|
-
|
|
284
|
-
expect(result.success).toBe(false);
|
|
285
|
-
expect(result.error).toBe('App suspended');
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// ---------------------------------------------------------------------------
|
|
290
|
-
// DOListResourcesTool
|
|
291
|
-
// ---------------------------------------------------------------------------
|
|
292
|
-
|
|
293
|
-
describe('DOListResourcesTool', () => {
|
|
294
|
-
let service: DigitalOceanService;
|
|
295
|
-
let tool: DOListResourcesTool;
|
|
296
|
-
|
|
297
|
-
beforeEach(() => {
|
|
298
|
-
service = createMockService();
|
|
299
|
-
tool = new DOListResourcesTool(service);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('should have correct id and name', () => {
|
|
303
|
-
expect(tool.id).toBe('doListResources');
|
|
304
|
-
expect(tool.name).toBe('doListResources');
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
it('should have no required fields', () => {
|
|
308
|
-
expect(tool.inputSchema.required).toHaveLength(0);
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it('should list both apps and droplets by default', async () => {
|
|
312
|
-
const mockApps = [{ id: 'app-1', name: 'my-app' }];
|
|
313
|
-
const mockDroplets = [{ id: 111, name: 'my-server' }];
|
|
314
|
-
(service.listApps as ReturnType<typeof vi.fn>).mockResolvedValue(mockApps);
|
|
315
|
-
(service.listDroplets as ReturnType<typeof vi.fn>).mockResolvedValue(mockDroplets);
|
|
316
|
-
|
|
317
|
-
const result = await tool.execute({});
|
|
318
|
-
|
|
319
|
-
expect(result.success).toBe(true);
|
|
320
|
-
expect(result.data?.apps).toEqual(mockApps);
|
|
321
|
-
expect(result.data?.droplets).toEqual(mockDroplets);
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('should list only apps when resourceType is "apps"', async () => {
|
|
325
|
-
(service.listApps as ReturnType<typeof vi.fn>).mockResolvedValue([]);
|
|
326
|
-
|
|
327
|
-
const result = await tool.execute({ resourceType: 'apps' });
|
|
328
|
-
|
|
329
|
-
expect(result.success).toBe(true);
|
|
330
|
-
expect(result.data?.apps).toEqual([]);
|
|
331
|
-
expect(result.data?.droplets).toBeUndefined();
|
|
332
|
-
expect(service.listDroplets).not.toHaveBeenCalled();
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it('should list only droplets when resourceType is "droplets"', async () => {
|
|
336
|
-
(service.listDroplets as ReturnType<typeof vi.fn>).mockResolvedValue([]);
|
|
337
|
-
|
|
338
|
-
const result = await tool.execute({ resourceType: 'droplets' });
|
|
339
|
-
|
|
340
|
-
expect(result.success).toBe(true);
|
|
341
|
-
expect(result.data?.droplets).toEqual([]);
|
|
342
|
-
expect(result.data?.apps).toBeUndefined();
|
|
343
|
-
expect(service.listApps).not.toHaveBeenCalled();
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
it('should return error on failure', async () => {
|
|
347
|
-
(service.listApps as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Unauthorized'));
|
|
348
|
-
|
|
349
|
-
const result = await tool.execute({});
|
|
350
|
-
|
|
351
|
-
expect(result.success).toBe(false);
|
|
352
|
-
expect(result.error).toBe('Unauthorized');
|
|
353
|
-
});
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
// ---------------------------------------------------------------------------
|
|
357
|
-
// DOManageDnsTool
|
|
358
|
-
// ---------------------------------------------------------------------------
|
|
359
|
-
|
|
360
|
-
describe('DOManageDnsTool', () => {
|
|
361
|
-
let service: DigitalOceanService;
|
|
362
|
-
let tool: DOManageDnsTool;
|
|
363
|
-
|
|
364
|
-
beforeEach(() => {
|
|
365
|
-
service = createMockService();
|
|
366
|
-
tool = new DOManageDnsTool(service);
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
it('should have correct id and name', () => {
|
|
370
|
-
expect(tool.id).toBe('doManageDns');
|
|
371
|
-
expect(tool.name).toBe('doManageDns');
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('should require action', () => {
|
|
375
|
-
expect(tool.inputSchema.required).toContain('action');
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it('should list domains', async () => {
|
|
379
|
-
const mockDomains = [{ name: 'example.com', ttl: 1800, zone_file: '...' }];
|
|
380
|
-
(service.listDomains as ReturnType<typeof vi.fn>).mockResolvedValue(mockDomains);
|
|
381
|
-
|
|
382
|
-
const result = await tool.execute({ action: 'list-domains' });
|
|
383
|
-
|
|
384
|
-
expect(result.success).toBe(true);
|
|
385
|
-
expect(result.data).toEqual(mockDomains);
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
it('should add a domain', async () => {
|
|
389
|
-
const mockDomain = { name: 'example.com', ttl: 1800 };
|
|
390
|
-
(service.addDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockDomain);
|
|
391
|
-
|
|
392
|
-
const result = await tool.execute({ action: 'add-domain', domain: 'example.com' });
|
|
393
|
-
|
|
394
|
-
expect(result.success).toBe(true);
|
|
395
|
-
expect(result.data).toEqual(mockDomain);
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
it('should validate domain for add-domain action', async () => {
|
|
399
|
-
const result = await tool.execute({ action: 'add-domain' });
|
|
400
|
-
|
|
401
|
-
expect(result.success).toBe(false);
|
|
402
|
-
expect(result.error).toContain('Domain name is required');
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
it('should list domain records', async () => {
|
|
406
|
-
const mockRecords = [{ id: 1, type: 'A', name: '@', data: '1.2.3.4' }];
|
|
407
|
-
(service.listDomainRecords as ReturnType<typeof vi.fn>).mockResolvedValue(mockRecords);
|
|
408
|
-
|
|
409
|
-
const result = await tool.execute({ action: 'list', domain: 'example.com' });
|
|
410
|
-
|
|
411
|
-
expect(result.success).toBe(true);
|
|
412
|
-
expect(result.data).toEqual(mockRecords);
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
it('should add a DNS record', async () => {
|
|
416
|
-
const mockRecord = { id: 2, type: 'A', name: 'www', data: '5.6.7.8' };
|
|
417
|
-
(service.createDomainRecord as ReturnType<typeof vi.fn>).mockResolvedValue(mockRecord);
|
|
418
|
-
|
|
419
|
-
const result = await tool.execute({
|
|
420
|
-
action: 'add',
|
|
421
|
-
domain: 'example.com',
|
|
422
|
-
recordType: 'A',
|
|
423
|
-
name: 'www',
|
|
424
|
-
data: '5.6.7.8',
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
expect(result.success).toBe(true);
|
|
428
|
-
expect(result.data).toEqual(mockRecord);
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
it('should validate required fields for add action', async () => {
|
|
432
|
-
const result = await tool.execute({
|
|
433
|
-
action: 'add',
|
|
434
|
-
domain: 'example.com',
|
|
435
|
-
// Missing recordType, name, data
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
expect(result.success).toBe(false);
|
|
439
|
-
expect(result.error).toContain('recordType');
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
it('should delete a DNS record', async () => {
|
|
443
|
-
(service.deleteDomainRecord as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
|
|
444
|
-
|
|
445
|
-
const result = await tool.execute({
|
|
446
|
-
action: 'delete',
|
|
447
|
-
domain: 'example.com',
|
|
448
|
-
recordId: 42,
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
expect(result.success).toBe(true);
|
|
452
|
-
expect(service.deleteDomainRecord).toHaveBeenCalledWith('example.com', 42);
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
it('should update a DNS record', async () => {
|
|
456
|
-
const mockUpdated = { id: 42, type: 'A', name: 'www', data: '9.9.9.9' };
|
|
457
|
-
(service.updateDomainRecord as ReturnType<typeof vi.fn>).mockResolvedValue(mockUpdated);
|
|
458
|
-
|
|
459
|
-
const result = await tool.execute({
|
|
460
|
-
action: 'update',
|
|
461
|
-
domain: 'example.com',
|
|
462
|
-
recordId: 42,
|
|
463
|
-
data: '9.9.9.9',
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
expect(result.success).toBe(true);
|
|
467
|
-
expect(result.data).toEqual(mockUpdated);
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
it('should return error on service failure', async () => {
|
|
471
|
-
(service.listDomains as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Auth error'));
|
|
472
|
-
|
|
473
|
-
const result = await tool.execute({ action: 'list-domains' });
|
|
474
|
-
|
|
475
|
-
expect(result.success).toBe(false);
|
|
476
|
-
expect(result.error).toBe('Auth error');
|
|
477
|
-
});
|
|
478
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"lib": ["ES2022"],
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"noEmitOnError": false,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"declaration": true,
|
|
14
|
-
"declarationMap": true,
|
|
15
|
-
"sourceMap": true,
|
|
16
|
-
"resolveJsonModule": true,
|
|
17
|
-
"moduleResolution": "Bundler",
|
|
18
|
-
"types": ["node"]
|
|
19
|
-
},
|
|
20
|
-
"include": ["src/**/*"],
|
|
21
|
-
"exclude": ["node_modules", "dist", "test"]
|
|
22
|
-
}
|