@framers/agentos-ext-cloud-vercel 0.1.0 → 0.1.2

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.
@@ -1,63 +0,0 @@
1
- // @ts-nocheck
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import { createExtensionPack } from '../src/index.js';
4
-
5
- const mockFetch = vi.fn();
6
- vi.stubGlobal('fetch', mockFetch);
7
-
8
- function okResponse(data: any = {}) {
9
- return { ok: true, status: 200, text: async () => JSON.stringify(data), json: async () => data } as Response;
10
- }
11
-
12
- describe('createExtensionPack (Vercel)', () => {
13
- beforeEach(() => {
14
- vi.clearAllMocks();
15
- mockFetch.mockResolvedValue(okResponse({ user: { id: 'u1' } }));
16
- });
17
-
18
- it('should return a valid ExtensionPack', () => {
19
- const pack = createExtensionPack({ secrets: { 'vercel.token': 'tok' } });
20
- expect(pack.name).toBe('@framers/agentos-ext-cloud-vercel');
21
- expect(pack.version).toBe('0.1.0');
22
- expect(pack.descriptors).toHaveLength(5);
23
- });
24
-
25
- it('should register correct tool IDs', () => {
26
- const pack = createExtensionPack({ secrets: { 'vercel.token': 'tok' } });
27
- const ids = pack.descriptors.map((d) => d.id);
28
- expect(ids).toContain('vercelDeploy');
29
- expect(ids).toContain('vercelListProjects');
30
- expect(ids).toContain('vercelGetDeployment');
31
- expect(ids).toContain('vercelConfigureDomain');
32
- expect(ids).toContain('vercelSetEnvVars');
33
- });
34
-
35
- it('should set all descriptors to kind "tool"', () => {
36
- const pack = createExtensionPack({ secrets: { 'vercel.token': 'tok' } });
37
- for (const d of pack.descriptors) {
38
- expect(d.kind).toBe('tool');
39
- }
40
- });
41
-
42
- it('onActivate should throw without token', async () => {
43
- const pack = createExtensionPack({ secrets: {} });
44
- await expect(pack.onActivate!()).rejects.toThrow(/token/i);
45
- });
46
-
47
- it('onActivate should succeed with valid token', async () => {
48
- const pack = createExtensionPack({ secrets: { 'vercel.token': 'valid' } });
49
- await expect(pack.onActivate!()).resolves.toBeUndefined();
50
- expect(mockFetch).toHaveBeenCalled();
51
- });
52
-
53
- it('onDeactivate should complete without error', async () => {
54
- const pack = createExtensionPack({ secrets: { 'vercel.token': 'valid' } });
55
- await pack.onActivate!();
56
- await expect(pack.onDeactivate!()).resolves.toBeUndefined();
57
- });
58
-
59
- it('should resolve token from options', () => {
60
- const pack = createExtensionPack({ options: { token: 'opt-tok' } });
61
- expect(pack.descriptors).toHaveLength(5);
62
- });
63
- });
@@ -1,332 +0,0 @@
1
- // @ts-nocheck
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import { VercelDeployTool } from '../src/tools/deploy.js';
4
- import { VercelListProjectsTool } from '../src/tools/listProjects.js';
5
- import { VercelGetDeploymentTool } from '../src/tools/getDeployment.js';
6
- import { VercelSetEnvVarsTool } from '../src/tools/setEnvVars.js';
7
- import { VercelConfigureDomainTool } from '../src/tools/configureDomain.js';
8
- import type { VercelService } from '../src/VercelService.js';
9
-
10
- // ---------------------------------------------------------------------------
11
- // Mock service factory
12
- // ---------------------------------------------------------------------------
13
-
14
- function createMockService(): VercelService {
15
- return {
16
- deployFromGit: vi.fn(),
17
- listProjects: vi.fn(),
18
- getDeployment: vi.fn(),
19
- setEnvVars: vi.fn(),
20
- listEnvVars: vi.fn(),
21
- addDomain: vi.fn(),
22
- removeDomain: vi.fn(),
23
- listDomains: vi.fn(),
24
- getDomainConfig: vi.fn(),
25
- } as unknown as VercelService;
26
- }
27
-
28
- // ---------------------------------------------------------------------------
29
- // VercelDeployTool
30
- // ---------------------------------------------------------------------------
31
-
32
- describe('VercelDeployTool', () => {
33
- let service: VercelService;
34
- let tool: VercelDeployTool;
35
-
36
- beforeEach(() => {
37
- service = createMockService();
38
- tool = new VercelDeployTool(service);
39
- });
40
-
41
- it('should have correct id and name', () => {
42
- expect(tool.id).toBe('vercelDeploy');
43
- expect(tool.name).toBe('vercelDeploy');
44
- expect(tool.displayName).toBe('Deploy to Vercel');
45
- });
46
-
47
- it('should require gitUrl in inputSchema', () => {
48
- expect(tool.inputSchema.required).toContain('gitUrl');
49
- expect(tool.inputSchema.properties.gitUrl).toBeDefined();
50
- });
51
-
52
- it('should return success on successful deploy', async () => {
53
- const mockResult = { id: 'dpl_1', url: 'https://app.vercel.app', readyState: 'BUILDING', inspectorUrl: '', projectId: 'p1' };
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
- expect(service.deployFromGit).toHaveBeenCalledWith(
61
- expect.objectContaining({ gitUrl: 'https://github.com/user/repo' }),
62
- );
63
- });
64
-
65
- it('should forward optional parameters to service', async () => {
66
- (service.deployFromGit as ReturnType<typeof vi.fn>).mockResolvedValue({});
67
-
68
- await tool.execute({
69
- gitUrl: 'https://github.com/user/repo',
70
- projectName: 'my-proj',
71
- framework: 'nextjs',
72
- buildCommand: 'npm run build',
73
- outputDirectory: '.next',
74
- envVars: { NODE_ENV: 'production' },
75
- });
76
-
77
- expect(service.deployFromGit).toHaveBeenCalledWith(
78
- expect.objectContaining({
79
- projectName: 'my-proj',
80
- framework: 'nextjs',
81
- buildCommand: 'npm run build',
82
- outputDirectory: '.next',
83
- envVars: { NODE_ENV: 'production' },
84
- }),
85
- );
86
- });
87
-
88
- it('should return error on failure', async () => {
89
- (service.deployFromGit as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Auth failed'));
90
-
91
- const result = await tool.execute({ gitUrl: 'https://github.com/user/repo' });
92
-
93
- expect(result.success).toBe(false);
94
- expect(result.error).toBe('Auth failed');
95
- });
96
- });
97
-
98
- // ---------------------------------------------------------------------------
99
- // VercelListProjectsTool
100
- // ---------------------------------------------------------------------------
101
-
102
- describe('VercelListProjectsTool', () => {
103
- let service: VercelService;
104
- let tool: VercelListProjectsTool;
105
-
106
- beforeEach(() => {
107
- service = createMockService();
108
- tool = new VercelListProjectsTool(service);
109
- });
110
-
111
- it('should have correct id and name', () => {
112
- expect(tool.id).toBe('vercelListProjects');
113
- expect(tool.name).toBe('vercelListProjects');
114
- });
115
-
116
- it('should have no required fields', () => {
117
- expect(tool.inputSchema.required).toHaveLength(0);
118
- });
119
-
120
- it('should return projects on success', async () => {
121
- const mockProjects = [
122
- { id: 'p1', name: 'app-1', framework: 'nextjs', createdAt: 1000, updatedAt: 2000 },
123
- ];
124
- (service.listProjects as ReturnType<typeof vi.fn>).mockResolvedValue(mockProjects);
125
-
126
- const result = await tool.execute({});
127
-
128
- expect(result.success).toBe(true);
129
- expect(result.data).toEqual(mockProjects);
130
- expect(service.listProjects).toHaveBeenCalledWith(20);
131
- });
132
-
133
- it('should pass custom limit', async () => {
134
- (service.listProjects as ReturnType<typeof vi.fn>).mockResolvedValue([]);
135
-
136
- await tool.execute({ limit: 5 });
137
-
138
- expect(service.listProjects).toHaveBeenCalledWith(5);
139
- });
140
-
141
- it('should return error on failure', async () => {
142
- (service.listProjects as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('API error'));
143
-
144
- const result = await tool.execute({});
145
-
146
- expect(result.success).toBe(false);
147
- expect(result.error).toBe('API error');
148
- });
149
- });
150
-
151
- // ---------------------------------------------------------------------------
152
- // VercelGetDeploymentTool
153
- // ---------------------------------------------------------------------------
154
-
155
- describe('VercelGetDeploymentTool', () => {
156
- let service: VercelService;
157
- let tool: VercelGetDeploymentTool;
158
-
159
- beforeEach(() => {
160
- service = createMockService();
161
- tool = new VercelGetDeploymentTool(service);
162
- });
163
-
164
- it('should have correct id and name', () => {
165
- expect(tool.id).toBe('vercelGetDeployment');
166
- expect(tool.name).toBe('vercelGetDeployment');
167
- });
168
-
169
- it('should require deploymentId', () => {
170
- expect(tool.inputSchema.required).toContain('deploymentId');
171
- });
172
-
173
- it('should return deployment on success', async () => {
174
- const mockDeployment = {
175
- uid: 'dpl_1', name: 'app', url: 'https://app.vercel.app',
176
- state: 'READY' as const, created: 5000,
177
- };
178
- (service.getDeployment as ReturnType<typeof vi.fn>).mockResolvedValue(mockDeployment);
179
-
180
- const result = await tool.execute({ deploymentId: 'dpl_1' });
181
-
182
- expect(result.success).toBe(true);
183
- expect(result.data).toEqual(mockDeployment);
184
- });
185
-
186
- it('should return error on failure', async () => {
187
- (service.getDeployment as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Not found'));
188
-
189
- const result = await tool.execute({ deploymentId: 'bad_id' });
190
-
191
- expect(result.success).toBe(false);
192
- expect(result.error).toBe('Not found');
193
- });
194
- });
195
-
196
- // ---------------------------------------------------------------------------
197
- // VercelSetEnvVarsTool
198
- // ---------------------------------------------------------------------------
199
-
200
- describe('VercelSetEnvVarsTool', () => {
201
- let service: VercelService;
202
- let tool: VercelSetEnvVarsTool;
203
-
204
- beforeEach(() => {
205
- service = createMockService();
206
- tool = new VercelSetEnvVarsTool(service);
207
- });
208
-
209
- it('should have correct id and name', () => {
210
- expect(tool.id).toBe('vercelSetEnvVars');
211
- expect(tool.name).toBe('vercelSetEnvVars');
212
- });
213
-
214
- it('should require projectId', () => {
215
- expect(tool.inputSchema.required).toContain('projectId');
216
- });
217
-
218
- it('should set env vars and return count', async () => {
219
- (service.setEnvVars as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
220
-
221
- const result = await tool.execute({
222
- projectId: 'p1',
223
- vars: { API_KEY: 'abc', SECRET: 'xyz' },
224
- });
225
-
226
- expect(result.success).toBe(true);
227
- expect(result.data).toEqual({ set: 2 });
228
- expect(service.setEnvVars).toHaveBeenCalledWith(
229
- 'p1',
230
- { API_KEY: 'abc', SECRET: 'xyz' },
231
- ['production', 'preview', 'development'],
232
- );
233
- });
234
-
235
- it('should list env vars when action is "list"', async () => {
236
- const mockVars = [{ key: 'NODE_ENV', value: 'production', target: ['production'], type: 'plain' }];
237
- (service.listEnvVars as ReturnType<typeof vi.fn>).mockResolvedValue(mockVars);
238
-
239
- const result = await tool.execute({ projectId: 'p1', action: 'list' });
240
-
241
- expect(result.success).toBe(true);
242
- expect(result.data).toEqual(mockVars);
243
- });
244
-
245
- it('should return error when no vars provided for set action', async () => {
246
- const result = await tool.execute({ projectId: 'p1' });
247
-
248
- expect(result.success).toBe(false);
249
- expect(result.error).toContain('No environment variables');
250
- });
251
-
252
- it('should return error on service failure', async () => {
253
- (service.setEnvVars as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Forbidden'));
254
-
255
- const result = await tool.execute({ projectId: 'p1', vars: { KEY: 'val' } });
256
-
257
- expect(result.success).toBe(false);
258
- expect(result.error).toBe('Forbidden');
259
- });
260
- });
261
-
262
- // ---------------------------------------------------------------------------
263
- // VercelConfigureDomainTool
264
- // ---------------------------------------------------------------------------
265
-
266
- describe('VercelConfigureDomainTool', () => {
267
- let service: VercelService;
268
- let tool: VercelConfigureDomainTool;
269
-
270
- beforeEach(() => {
271
- service = createMockService();
272
- tool = new VercelConfigureDomainTool(service);
273
- });
274
-
275
- it('should have correct id and name', () => {
276
- expect(tool.id).toBe('vercelConfigureDomain');
277
- expect(tool.name).toBe('vercelConfigureDomain');
278
- });
279
-
280
- it('should require projectId and domain', () => {
281
- expect(tool.inputSchema.required).toContain('projectId');
282
- expect(tool.inputSchema.required).toContain('domain');
283
- });
284
-
285
- it('should add a domain and check DNS config', async () => {
286
- const mockDomain = { name: 'example.com', verified: true, configured: false };
287
- (service.addDomain as ReturnType<typeof vi.fn>).mockResolvedValue(mockDomain);
288
- (service.getDomainConfig as ReturnType<typeof vi.fn>).mockResolvedValue({ misconfigured: true });
289
-
290
- const result = await tool.execute({ projectId: 'p1', domain: 'example.com' });
291
-
292
- expect(result.success).toBe(true);
293
- expect(service.addDomain).toHaveBeenCalledWith('p1', 'example.com', { gitBranch: undefined });
294
- });
295
-
296
- it('should remove a domain', async () => {
297
- (service.removeDomain as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
298
-
299
- const result = await tool.execute({ projectId: 'p1', domain: 'example.com', action: 'remove' });
300
-
301
- expect(result.success).toBe(true);
302
- expect(service.removeDomain).toHaveBeenCalledWith('p1', 'example.com');
303
- });
304
-
305
- it('should list domains', async () => {
306
- const mockDomains = [{ name: 'a.com', verified: true, configured: true }];
307
- (service.listDomains as ReturnType<typeof vi.fn>).mockResolvedValue(mockDomains);
308
-
309
- const result = await tool.execute({ projectId: 'p1', domain: 'a.com', action: 'list' });
310
-
311
- expect(result.success).toBe(true);
312
- expect(result.data).toEqual(mockDomains);
313
- });
314
-
315
- it('should check DNS configuration', async () => {
316
- (service.getDomainConfig as ReturnType<typeof vi.fn>).mockResolvedValue({ misconfigured: false });
317
-
318
- const result = await tool.execute({ projectId: 'p1', domain: 'example.com', action: 'check' });
319
-
320
- expect(result.success).toBe(true);
321
- expect((result.data as any).dnsInstructions).toContain('properly configured');
322
- });
323
-
324
- it('should return error on failure', async () => {
325
- (service.addDomain as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('Project not found'));
326
-
327
- const result = await tool.execute({ projectId: 'bad', domain: 'x.com' });
328
-
329
- expect(result.success).toBe(false);
330
- expect(result.error).toBe('Project not found');
331
- });
332
- });
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
- }