Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions src/api-client.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function apiRequest(path, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'X-Lua-Client': 'platform-mcp/1.0.0',
},
body: body ? JSON.stringify(body) : undefined,
signal: controller.signal,
Expand Down
29 changes: 29 additions & 0 deletions tests/api-client.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,21 @@
// 401 / 403 / generic-error paths, and query-string handling.

import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
import { readFileSync, readdirSync } from 'node:fs';
import { join, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
import { apiRequest } from '../src/api-client.mjs';

const SOURCE_DIRECTORY = fileURLToPath(new URL('../src/', import.meta.url));
const MCP_PACKAGE = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));

function sourceFiles(directory) {
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
const path = join(directory, entry.name);
return entry.isDirectory() ? sourceFiles(path) : [path];
});
}

function mockFetch(scripted) {
const calls = [];
const fn = async (url, init) => {
Expand Down Expand Up @@ -61,6 +74,22 @@ describe('apiRequest', () => {
expect(fetchFn.calls[0].init.headers['Content-Type']).toBe('application/json');
});

test('identifies direct requests as the versioned platform MCP client', async () => {
const fetchFn = mockFetch(jsonResponse({ ok: true }));
await apiRequest('/agents', { fetchFn });
expect(fetchFn.calls[0].init.headers['X-Lua-Client']).toBe(`platform-mcp/${MCP_PACKAGE.version}`);
});

test('keeps every direct Lua API call behind the identified wrapper', () => {
const directCallers = sourceFiles(SOURCE_DIRECTORY)
.filter((path) => path.endsWith('.mjs'))
.filter((path) => /\b(?:fetch|fetchFn)\s*\(/.test(readFileSync(path, 'utf8')))
.map((path) => relative(SOURCE_DIRECTORY, path))
.sort();

expect(directCallers).toEqual(['api-client.mjs']);
});

test('uses LUA_API_URL env override when set', async () => {
process.env.LUA_API_URL = 'https://api-staging.heylua.ai';
const fetchFn = mockFetch(jsonResponse({ ok: true }));
Expand Down
Loading