TypeScript SDK
Purpose
The TypeScript SDK provides an ApiMapperClient class and adapters for OpenAI and LangChain.js.
Main Capabilities
- ESM + CJS dual build
- Native
fetch— no runtime dependencies beyond the package itself - Three authentication modes: API key, OAuth2 client credentials, delegated bearer
- Optional structured logger compatible with
console, pino, and winston - Adapters for the OpenAI SDK and LangChain.js
Packages
| Package | Description |
|---|---|
@codedprojects/api-mapper-client |
Core client |
@codedprojects/api-mapper-openai |
OpenAI ChatCompletionTool[] adapter and tool loop |
@codedprojects/api-mapper-langchain |
LangChain.js DynamicStructuredTool adapter |
Installation
npm install @codedprojects/api-mapper-client
# or for OpenAI integration:
npm install @codedprojects/api-mapper-client @codedprojects/api-mapper-openai openai
Construction
import { ApiMapperClient, ApiKeyCredentialProvider } from "@codedprojects/api-mapper-client";
const client = new ApiMapperClient({
baseUrl: process.env.APIMAPPER_BASE_URL!,
tenantId: process.env.APIMAPPER_TENANT_ID!, // UUID string
clientId: "my-app",
systemPromptResourceUri: "apimapper://toolsets/system-prompt",
credentials: new ApiKeyCredentialProvider(process.env.APIMAPPER_API_KEY!),
logger: console, // optional; omit to disable logging
});
See SDK Authentication for OAuth2 and delegated bearer options.
Raw Tool Loop (01-raw-client)
const systemPrompt = await client.getSystemPrompt();
const tools = await client.getTools();
const openAITools = tools.map(t => ({
type: "function" as const,
function: { name: t.name, description: t.description ?? "", parameters: t.inputSchema },
}));
const messages = [
{ role: "system" as const, content: systemPrompt ?? "You are a helpful assistant." },
{ role: "user" as const, content: userMessage },
];
while (true) {
const response = await openai.chat.completions.create({ model: "gpt-4o", messages, tools: openAITools });
const choice = response.choices[0];
messages.push(choice.message);
if (choice.finish_reason !== "tool_calls") {
console.log(choice.message.content);
break;
}
for (const call of choice.message.tool_calls!) {
const args = JSON.parse(call.function.arguments);
const result = await client.invokeTool(call.function.name, args);
messages.push({ role: "tool", tool_call_id: call.id, content: toolResultToText(result!) });
}
}
OpenAI Tool Loop (02-openai-tool-loop)
runToolLoop from @codedprojects/api-mapper-openai handles the full loop automatically.
import { runToolLoop } from "@codedprojects/api-mapper-openai";
const systemPrompt = await client.getSystemPrompt();
const answer = await runToolLoop(client, openai, [
{ role: "system", content: systemPrompt ?? "You are a helpful assistant." },
{ role: "user", content: userMessage },
]);
console.log(answer);
LangChain.js
createApiMapperTools from @codedprojects/api-mapper-langchain returns DynamicStructuredTool[].
import { createApiMapperTools } from "@codedprojects/api-mapper-langchain";
import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents";
const systemPrompt = await client.getSystemPrompt() ?? "You are a helpful assistant.";
const tools = await createApiMapperTools(client);
const agent = await createOpenAIFunctionsAgent({ llm, tools, prompt });
const executor = new AgentExecutor({ agent, tools });
const result = await executor.invoke({ input: userMessage });
Node Backend (03-node-backend)
An Express endpoint that runs a tool loop and returns the answer as JSON.
app.post("/chat", async (req, res) => {
const { message } = req.body;
const systemPrompt = await client.getSystemPrompt();
const answer = await runToolLoop(client, openai, [
{ role: "system", content: systemPrompt ?? "" },
{ role: "user", content: message },
]);
res.json({ answer });
});
Logging
Pass any object that implements { debug, info, warn, error }. The SDK prefix is [ApiMapper].
// pino
import pino from "pino";
const logger = pino();
const client = new ApiMapperClient({ ..., logger });
// winston
import winston from "winston";
const client = new ApiMapperClient({ ..., logger: winston.createLogger(...) });
// console (simplest)
const client = new ApiMapperClient({ ..., logger: console });
Auth header values are never passed to the logger.
