mirror of
https://github.com/aljazceru/dvmcp.git
synced 2025-12-17 05:14:24 +01:00
feat: gh-actions (#2)
This commit is contained in:
26
.github/workflows/test.yml
vendored
Normal file
26
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Bun Runtime
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
NODE_ENV: test
|
||||
run: bun test
|
||||
|
||||
- name: Check formatting
|
||||
run: bun run format --check
|
||||
@@ -1,41 +1,96 @@
|
||||
import { parse } from 'yaml';
|
||||
import { join } from 'path';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import type { MCPServerConfig } from './types';
|
||||
|
||||
interface NostrConfig {
|
||||
privateKey: string;
|
||||
relayUrls: string[];
|
||||
}
|
||||
|
||||
interface MCPConfig {
|
||||
name: string;
|
||||
about: string;
|
||||
clientName: string;
|
||||
clientVersion: string;
|
||||
servers: MCPServerConfig[];
|
||||
}
|
||||
|
||||
interface WhitelistConfig {
|
||||
allowedPubkeys: Set<string> | undefined;
|
||||
}
|
||||
|
||||
interface AppConfig {
|
||||
nostr: NostrConfig;
|
||||
mcp: MCPConfig;
|
||||
whitelist: WhitelistConfig;
|
||||
}
|
||||
import type { AppConfig, MCPServerConfig } from './types';
|
||||
|
||||
const CONFIG_PATH = join(process.cwd(), 'config.yml');
|
||||
const HEX_KEYS_REGEX = /^(?:[0-9a-fA-F]{64})$/;
|
||||
|
||||
if (!existsSync(CONFIG_PATH)) {
|
||||
const TEST_CONFIG: AppConfig = {
|
||||
nostr: {
|
||||
privateKey:
|
||||
'd4d4d7aae7857054596c4c0976b22a73acac3a10d30bf56db35ee038bbf0dd44',
|
||||
relayUrls: ['ws://localhost:3334'],
|
||||
},
|
||||
mcp: {
|
||||
name: 'Test DVM MCP Bridge',
|
||||
about: 'Test MCP-enabled DVM',
|
||||
clientName: 'Test Client',
|
||||
clientVersion: '1.0.0',
|
||||
servers: [],
|
||||
},
|
||||
whitelist: {
|
||||
allowedPubkeys: new Set(),
|
||||
},
|
||||
};
|
||||
|
||||
function validateRequiredField(value: any, fieldName: string): string {
|
||||
if (!value) {
|
||||
throw new Error(`Missing required config field: ${fieldName}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function getConfigValue(
|
||||
value: string | undefined,
|
||||
defaultValue: string
|
||||
): string {
|
||||
return value || defaultValue;
|
||||
}
|
||||
|
||||
function validateRelayUrls(urls: any): string[] {
|
||||
if (!Array.isArray(urls) || urls.length === 0) {
|
||||
throw new Error(
|
||||
'No config.yml file found. Please create one based on config.example.yml'
|
||||
'At least one relay URL must be provided in nostr.relayUrls'
|
||||
);
|
||||
}
|
||||
return urls.map((url: string) => {
|
||||
try {
|
||||
const trimmedUrl = url.trim();
|
||||
new URL(trimmedUrl);
|
||||
if (!trimmedUrl.startsWith('ws://') && !trimmedUrl.startsWith('wss://')) {
|
||||
throw new Error(
|
||||
`Relay URL must start with ws:// or wss://: ${trimmedUrl}`
|
||||
);
|
||||
}
|
||||
return trimmedUrl;
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid relay URL: ${url}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function validateMCPServers(servers: any): MCPServerConfig[] {
|
||||
if (!Array.isArray(servers) || servers.length === 0) {
|
||||
throw new Error(
|
||||
'At least one MCP server must be configured in mcp.servers'
|
||||
);
|
||||
}
|
||||
return servers.map((server: any, index: number) => {
|
||||
if (!server.name || !server.command || !Array.isArray(server.args)) {
|
||||
throw new Error(
|
||||
`Invalid MCP server configuration at index ${index}. Required fields: name, command, args[]`
|
||||
);
|
||||
}
|
||||
return {
|
||||
name: server.name,
|
||||
command: server.command,
|
||||
args: server.args,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function loadConfig(): AppConfig {
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
return TEST_CONFIG;
|
||||
}
|
||||
|
||||
if (!existsSync(CONFIG_PATH)) {
|
||||
throw new Error(
|
||||
'No config.yml file found. Please create one based on config.example.yml'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const configFile = readFileSync(CONFIG_PATH, 'utf8');
|
||||
const rawConfig = parse(configFile);
|
||||
@@ -83,63 +138,4 @@ function loadConfig(): AppConfig {
|
||||
}
|
||||
}
|
||||
|
||||
function validateRequiredField(value: any, fieldName: string): string {
|
||||
if (!value) {
|
||||
throw new Error(`Missing required config field: ${fieldName}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function getConfigValue(
|
||||
value: string | undefined,
|
||||
defaultValue: string
|
||||
): string {
|
||||
return value || defaultValue;
|
||||
}
|
||||
|
||||
function validateRelayUrls(urls: any): string[] {
|
||||
if (!Array.isArray(urls) || urls.length === 0) {
|
||||
throw new Error(
|
||||
'At least one relay URL must be provided in nostr.relayUrls'
|
||||
);
|
||||
}
|
||||
|
||||
return urls.map((url: string) => {
|
||||
try {
|
||||
const trimmedUrl = url.trim();
|
||||
new URL(trimmedUrl);
|
||||
if (!trimmedUrl.startsWith('ws://') && !trimmedUrl.startsWith('wss://')) {
|
||||
throw new Error(
|
||||
`Relay URL must start with ws:// or wss://: ${trimmedUrl}`
|
||||
);
|
||||
}
|
||||
return trimmedUrl;
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid relay URL: ${url}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function validateMCPServers(servers: any): MCPServerConfig[] {
|
||||
if (!Array.isArray(servers) || servers.length === 0) {
|
||||
throw new Error(
|
||||
'At least one MCP server must be configured in mcp.servers'
|
||||
);
|
||||
}
|
||||
|
||||
return servers.map((server: any, index: number) => {
|
||||
if (!server.name || !server.command || !Array.isArray(server.args)) {
|
||||
throw new Error(
|
||||
`Invalid MCP server configuration at index ${index}. Required fields: name, command, args[]`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
name: server.name,
|
||||
command: server.command,
|
||||
args: server.args,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export const CONFIG = loadConfig();
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
export interface NostrConfig {
|
||||
privateKey: string;
|
||||
relayUrls: string[];
|
||||
}
|
||||
|
||||
export interface MCPConfig {
|
||||
name: string;
|
||||
about: string;
|
||||
clientName: string;
|
||||
clientVersion: string;
|
||||
servers: MCPServerConfig[];
|
||||
}
|
||||
|
||||
export interface WhitelistConfig {
|
||||
allowedPubkeys: Set<string> | undefined;
|
||||
}
|
||||
|
||||
export interface AppConfig {
|
||||
nostr: NostrConfig;
|
||||
mcp: MCPConfig;
|
||||
whitelist: WhitelistConfig;
|
||||
}
|
||||
|
||||
export interface MCPServerConfig {
|
||||
name: string;
|
||||
command: string;
|
||||
|
||||
Reference in New Issue
Block a user