@framers/agentos-ext-cloud-cloudflare-pages 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/CloudflareService.ts +0 -606
- package/src/index.ts +0 -129
- package/src/tools/configureDns.ts +0 -130
- package/src/tools/createWorker.ts +0 -58
- package/src/tools/deploy.ts +0 -56
- package/src/tools/listProjects.ts +0 -35
- package/test/CloudflareService.test.ts +0 -409
- package/test/index.test.ts +0 -56
- package/test/tools.test.ts +0 -336
- package/tsconfig.json +0 -22
package/test/tools.test.ts
DELETED
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
3
|
-
import { CfDeployPagesTool } from '../src/tools/deploy.js';
|
|
4
|
-
import { CfListProjectsTool } from '../src/tools/listProjects.js';
|
|
5
|
-
import { CfCreateWorkerTool } from '../src/tools/createWorker.js';
|
|
6
|
-
import { CfConfigureDnsTool } from '../src/tools/configureDns.js';
|
|
7
|
-
import type { CloudflareService } from '../src/CloudflareService.js';
|
|
8
|
-
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
// Mock service factory
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
|
|
13
|
-
function createMockService(): CloudflareService {
|
|
14
|
-
return {
|
|
15
|
-
deployFromGit: vi.fn(),
|
|
16
|
-
listProjects: vi.fn(),
|
|
17
|
-
deployWorker: vi.fn(),
|
|
18
|
-
getZoneByDomain: vi.fn(),
|
|
19
|
-
createDnsRecord: vi.fn(),
|
|
20
|
-
deleteDnsRecord: vi.fn(),
|
|
21
|
-
updateDnsRecord: vi.fn(),
|
|
22
|
-
listDnsRecords: vi.fn(),
|
|
23
|
-
} as unknown as CloudflareService;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// CfDeployPagesTool
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
describe('CfDeployPagesTool', () => {
|
|
31
|
-
let service: CloudflareService;
|
|
32
|
-
let tool: CfDeployPagesTool;
|
|
33
|
-
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
service = createMockService();
|
|
36
|
-
tool = new CfDeployPagesTool(service);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should have correct id and name', () => {
|
|
40
|
-
expect(tool.id).toBe('cfDeployPages');
|
|
41
|
-
expect(tool.name).toBe('cfDeployPages');
|
|
42
|
-
expect(tool.displayName).toBe('Deploy Cloudflare Pages');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should require gitUrl in inputSchema', () => {
|
|
46
|
-
expect(tool.inputSchema.required).toContain('gitUrl');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should return success on successful deploy', async () => {
|
|
50
|
-
const mockResult = {
|
|
51
|
-
id: 'd1', url: 'https://project.pages.dev', environment: 'production',
|
|
52
|
-
projectName: 'my-project', latestStage: { name: 'deploy', status: 'success' },
|
|
53
|
-
};
|
|
54
|
-
(service.deployFromGit as ReturnType<typeof vi.fn>).mockResolvedValue(mockResult);
|
|
55
|
-
|
|
56
|
-
const result = await tool.execute({ gitUrl: 'https://github.com/user/repo' });
|
|
57
|
-
|
|
58
|
-
expect(result.success).toBe(true);
|
|
59
|
-
expect(result.data).toEqual(mockResult);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should forward optional parameters to service', async () => {
|
|
63
|
-
(service.deployFromGit as ReturnType<typeof vi.fn>).mockResolvedValue({});
|
|
64
|
-
|
|
65
|
-
await tool.execute({
|
|
66
|
-
gitUrl: 'https://github.com/user/repo',
|
|
67
|
-
productionBranch: 'main',
|
|
68
|
-
buildCommand: 'npm run build',
|
|
69
|
-
buildOutputDirectory: 'dist',
|
|
70
|
-
envVars: { API_KEY: 'abc' },
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
expect(service.deployFromGit).toHaveBeenCalledWith(
|
|
74
|
-
expect.objectContaining({
|
|
75
|
-
gitUrl: 'https://github.com/user/repo',
|
|
76
|
-
productionBranch: 'main',
|
|
77
|
-
buildCommand: 'npm run build',
|
|
78
|
-
buildOutputDirectory: 'dist',
|
|
79
|
-
envVars: { API_KEY: 'abc' },
|
|
80
|
-
}),
|
|
81
|
-
);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should return error on failure', async () => {
|
|
85
|
-
(service.deployFromGit as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Token invalid'));
|
|
86
|
-
|
|
87
|
-
const result = await tool.execute({ gitUrl: 'https://github.com/user/repo' });
|
|
88
|
-
|
|
89
|
-
expect(result.success).toBe(false);
|
|
90
|
-
expect(result.error).toBe('Token invalid');
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
// CfListProjectsTool
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
|
-
|
|
98
|
-
describe('CfListProjectsTool', () => {
|
|
99
|
-
let service: CloudflareService;
|
|
100
|
-
let tool: CfListProjectsTool;
|
|
101
|
-
|
|
102
|
-
beforeEach(() => {
|
|
103
|
-
service = createMockService();
|
|
104
|
-
tool = new CfListProjectsTool(service);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('should have correct id and name', () => {
|
|
108
|
-
expect(tool.id).toBe('cfListProjects');
|
|
109
|
-
expect(tool.name).toBe('cfListProjects');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('should have no required fields', () => {
|
|
113
|
-
expect(tool.inputSchema.required).toHaveLength(0);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('should return projects on success', async () => {
|
|
117
|
-
const mockProjects = [{ id: 'p1', name: 'my-site', subdomain: 'my-site.pages.dev' }];
|
|
118
|
-
(service.listProjects as ReturnType<typeof vi.fn>).mockResolvedValue(mockProjects);
|
|
119
|
-
|
|
120
|
-
const result = await tool.execute({});
|
|
121
|
-
|
|
122
|
-
expect(result.success).toBe(true);
|
|
123
|
-
expect(result.data).toEqual(mockProjects);
|
|
124
|
-
expect(service.listProjects).toHaveBeenCalledWith(25);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should pass custom limit', async () => {
|
|
128
|
-
(service.listProjects as ReturnType<typeof vi.fn>).mockResolvedValue([]);
|
|
129
|
-
|
|
130
|
-
await tool.execute({ limit: 10 });
|
|
131
|
-
|
|
132
|
-
expect(service.listProjects).toHaveBeenCalledWith(10);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should return error on failure', async () => {
|
|
136
|
-
(service.listProjects as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Rate limited'));
|
|
137
|
-
|
|
138
|
-
const result = await tool.execute({});
|
|
139
|
-
|
|
140
|
-
expect(result.success).toBe(false);
|
|
141
|
-
expect(result.error).toBe('Rate limited');
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// ---------------------------------------------------------------------------
|
|
146
|
-
// CfCreateWorkerTool
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
|
|
149
|
-
describe('CfCreateWorkerTool', () => {
|
|
150
|
-
let service: CloudflareService;
|
|
151
|
-
let tool: CfCreateWorkerTool;
|
|
152
|
-
|
|
153
|
-
beforeEach(() => {
|
|
154
|
-
service = createMockService();
|
|
155
|
-
tool = new CfCreateWorkerTool(service);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should have correct id and name', () => {
|
|
159
|
-
expect(tool.id).toBe('cfCreateWorker');
|
|
160
|
-
expect(tool.name).toBe('cfCreateWorker');
|
|
161
|
-
expect(tool.displayName).toBe('Deploy Cloudflare Worker');
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('should require name and script', () => {
|
|
165
|
-
expect(tool.inputSchema.required).toContain('name');
|
|
166
|
-
expect(tool.inputSchema.required).toContain('script');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('should return worker on success', async () => {
|
|
170
|
-
const mockWorker = {
|
|
171
|
-
id: 'w1', tag: 'v1', etag: 'abc', size: 1024,
|
|
172
|
-
createdOn: '2024-01-01T00:00:00Z', modifiedOn: '2024-01-01T00:00:00Z',
|
|
173
|
-
};
|
|
174
|
-
(service.deployWorker as ReturnType<typeof vi.fn>).mockResolvedValue(mockWorker);
|
|
175
|
-
|
|
176
|
-
const result = await tool.execute({
|
|
177
|
-
name: 'my-worker',
|
|
178
|
-
script: 'export default { fetch() { return new Response("ok"); } }',
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
expect(result.success).toBe(true);
|
|
182
|
-
expect(result.data).toEqual(mockWorker);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('should forward routes and bindings to service', async () => {
|
|
186
|
-
(service.deployWorker as ReturnType<typeof vi.fn>).mockResolvedValue({});
|
|
187
|
-
|
|
188
|
-
await tool.execute({
|
|
189
|
-
name: 'api-worker',
|
|
190
|
-
script: 'export default {}',
|
|
191
|
-
routes: ['example.com/api/*'],
|
|
192
|
-
compatibilityDate: '2024-06-01',
|
|
193
|
-
bindings: { DATABASE_URL: 'postgres://...' },
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
expect(service.deployWorker).toHaveBeenCalledWith(
|
|
197
|
-
expect.objectContaining({
|
|
198
|
-
name: 'api-worker',
|
|
199
|
-
routes: ['example.com/api/*'],
|
|
200
|
-
compatibilityDate: '2024-06-01',
|
|
201
|
-
bindings: { DATABASE_URL: 'postgres://...' },
|
|
202
|
-
}),
|
|
203
|
-
);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it('should return error on failure', async () => {
|
|
207
|
-
(service.deployWorker as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Script too large'));
|
|
208
|
-
|
|
209
|
-
const result = await tool.execute({ name: 'big-worker', script: '...' });
|
|
210
|
-
|
|
211
|
-
expect(result.success).toBe(false);
|
|
212
|
-
expect(result.error).toBe('Script too large');
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// ---------------------------------------------------------------------------
|
|
217
|
-
// CfConfigureDnsTool
|
|
218
|
-
// ---------------------------------------------------------------------------
|
|
219
|
-
|
|
220
|
-
describe('CfConfigureDnsTool', () => {
|
|
221
|
-
let service: CloudflareService;
|
|
222
|
-
let tool: CfConfigureDnsTool;
|
|
223
|
-
|
|
224
|
-
beforeEach(() => {
|
|
225
|
-
service = createMockService();
|
|
226
|
-
tool = new CfConfigureDnsTool(service);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('should have correct id and name', () => {
|
|
230
|
-
expect(tool.id).toBe('cfConfigureDns');
|
|
231
|
-
expect(tool.name).toBe('cfConfigureDns');
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('should require domain', () => {
|
|
235
|
-
expect(tool.inputSchema.required).toContain('domain');
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('should list DNS records by default', async () => {
|
|
239
|
-
const mockZone = { id: 'z1', name: 'example.com', status: 'active', nameServers: [] };
|
|
240
|
-
const mockRecords = [{ id: 'r1', type: 'A', name: 'example.com', content: '1.2.3.4', ttl: 1 }];
|
|
241
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockZone);
|
|
242
|
-
(service.listDnsRecords as ReturnType<typeof vi.fn>).mockResolvedValue(mockRecords);
|
|
243
|
-
|
|
244
|
-
const result = await tool.execute({ domain: 'example.com' });
|
|
245
|
-
|
|
246
|
-
expect(result.success).toBe(true);
|
|
247
|
-
expect(result.data).toEqual(mockRecords);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should add a DNS record', async () => {
|
|
251
|
-
const mockZone = { id: 'z1', name: 'example.com' };
|
|
252
|
-
const mockRecord = { id: 'r2', type: 'A', name: 'api.example.com', content: '5.6.7.8', ttl: 300 };
|
|
253
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockZone);
|
|
254
|
-
(service.createDnsRecord as ReturnType<typeof vi.fn>).mockResolvedValue(mockRecord);
|
|
255
|
-
|
|
256
|
-
const result = await tool.execute({
|
|
257
|
-
domain: 'example.com',
|
|
258
|
-
action: 'add',
|
|
259
|
-
recordType: 'A',
|
|
260
|
-
name: 'api.example.com',
|
|
261
|
-
content: '5.6.7.8',
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
expect(result.success).toBe(true);
|
|
265
|
-
expect(result.data).toEqual(mockRecord);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should validate required fields for add action', async () => {
|
|
269
|
-
const mockZone = { id: 'z1', name: 'example.com' };
|
|
270
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockZone);
|
|
271
|
-
|
|
272
|
-
const result = await tool.execute({
|
|
273
|
-
domain: 'example.com',
|
|
274
|
-
action: 'add',
|
|
275
|
-
// Missing recordType, name, content
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
expect(result.success).toBe(false);
|
|
279
|
-
expect(result.error).toContain('recordType');
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('should remove a DNS record', async () => {
|
|
283
|
-
const mockZone = { id: 'z1', name: 'example.com' };
|
|
284
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockZone);
|
|
285
|
-
(service.deleteDnsRecord as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
|
|
286
|
-
|
|
287
|
-
const result = await tool.execute({
|
|
288
|
-
domain: 'example.com',
|
|
289
|
-
action: 'remove',
|
|
290
|
-
recordId: 'r1',
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
expect(result.success).toBe(true);
|
|
294
|
-
expect(service.deleteDnsRecord).toHaveBeenCalledWith('z1', 'r1');
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it('should validate recordId for remove action', async () => {
|
|
298
|
-
const mockZone = { id: 'z1', name: 'example.com' };
|
|
299
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockZone);
|
|
300
|
-
|
|
301
|
-
const result = await tool.execute({
|
|
302
|
-
domain: 'example.com',
|
|
303
|
-
action: 'remove',
|
|
304
|
-
// Missing recordId
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
expect(result.success).toBe(false);
|
|
308
|
-
expect(result.error).toContain('recordId');
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it('should update a DNS record', async () => {
|
|
312
|
-
const mockZone = { id: 'z1', name: 'example.com' };
|
|
313
|
-
const updatedRecord = { id: 'r1', type: 'A', name: 'www', content: '9.9.9.9', ttl: 1 };
|
|
314
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockZone);
|
|
315
|
-
(service.updateDnsRecord as ReturnType<typeof vi.fn>).mockResolvedValue(updatedRecord);
|
|
316
|
-
|
|
317
|
-
const result = await tool.execute({
|
|
318
|
-
domain: 'example.com',
|
|
319
|
-
action: 'update',
|
|
320
|
-
recordId: 'r1',
|
|
321
|
-
content: '9.9.9.9',
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
expect(result.success).toBe(true);
|
|
325
|
-
expect(result.data).toEqual(updatedRecord);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
it('should return error on service failure', async () => {
|
|
329
|
-
(service.getZoneByDomain as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Zone not found'));
|
|
330
|
-
|
|
331
|
-
const result = await tool.execute({ domain: 'nonexistent.com' });
|
|
332
|
-
|
|
333
|
-
expect(result.success).toBe(false);
|
|
334
|
-
expect(result.error).toBe('Zone not found');
|
|
335
|
-
});
|
|
336
|
-
});
|
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
|
-
}
|