Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/__tests__/credentialsEndpoint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { describe, beforeAll, afterAll, it, expect } from 'vitest';
import { createHealthServer } from '../backend/server.js';

let server: any;
let port: number;

describe('credentials API endpoints', () => {
beforeAll(() => {
return new Promise((resolve) => {
server = createHealthServer().listen(0, () => {
const address = server.address();
port = typeof address === 'object' && address ? address.port : 0;
resolve(null);
});
});
});

afterAll(() => {
return new Promise((resolve) => server.close(resolve));
});

it('creates and retrieves a credential', async () => {
const createRes = await fetch(`http://localhost:${port}/api/v1/credentials`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Test Cred', type: 'apiKey' })
});
expect(createRes.status).toBe(201);
const created = await createRes.json();
expect(created.name).toBe('Test Cred');

const getRes = await fetch(`http://localhost:${port}/api/v1/credentials/${created.id}`);
expect(getRes.status).toBe(200);
const cred = await getRes.json();
expect(cred.id).toBe(created.id);
});

it('lists credentials', async () => {
const res = await fetch(`http://localhost:${port}/api/v1/credentials`);
expect(res.status).toBe(200);
const list = await res.json();
expect(Array.isArray(list.credentials)).toBe(true);
});
});
46 changes: 46 additions & 0 deletions src/backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ const queueMetrics = {
const workflows = new Map();
let workflowCounter = 1;

// In-memory credentials storage
const credentials = new Map();
let credentialCounter = 1;

function parseJsonBody(req) {
return new Promise((resolve) => {
let body = '';
Expand Down Expand Up @@ -124,6 +128,48 @@ export function createHealthServer() {
res.writeHead(404);
res.end('Not Found');
}
} else if (req.url && req.url.startsWith('/api/v1/credentials')) {
const url = new URL(req.url, 'http://localhost');
const id = url.pathname.split('/')[4];

if (req.method === 'GET' && url.pathname === '/api/v1/credentials') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ credentials: Array.from(credentials.values()) }));
} else if (req.method === 'POST' && url.pathname === '/api/v1/credentials') {
const body = await parseJsonBody(req);
const credential = { id: String(credentialCounter++), ...body };
credentials.set(credential.id, credential);
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(credential));
} else if (req.method === 'GET' && id) {
const cred = credentials.get(id);
if (cred) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(cred));
} else {
res.writeHead(404);
res.end('Not Found');
}
} else if (req.method === 'PUT' && id) {
const body = await parseJsonBody(req);
const cred = credentials.get(id);
if (cred) {
const updated = { ...cred, ...body };
credentials.set(id, updated);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(updated));
} else {
res.writeHead(404);
res.end('Not Found');
}
} else if (req.method === 'DELETE' && id) {
const existed = credentials.delete(id);
res.writeHead(existed ? 200 : 404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ success: existed }));
} else {
res.writeHead(404);
res.end('Not Found');
}
} else {
res.statusCode = 404;
res.end('Not Found');
Expand Down