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
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
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
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.
Correlation IDs
Set correlationIdProvider to send the calling application's own identifier to the Runtime on every
request, or pass one as the third argument to invokeTool for a single call. The per-call value wins.
const client = new ApiMapperClient({
// Invoked once per request, so AsyncLocalStorage resolves per request.
correlationIdProvider: () => asyncLocalStorage.getStore()?.traceId,
// ...
});
const result = await client.invokeTool("crm-lookup", args, "order-4711");
A provider that throws is logged and ignored rather than failing the tool call. When the Runtime does
not echo the value back on X-External-Correlation-Id, the client logs a warning — see
SDK → Correlation IDs for the accepted format.
