#Lib and SDK Survey
#Go
#Installation
go get github.com/telepact/telepact/lib/go#Usage
API:
- fn.greet:
subject: string
->:
Ok_:
message: stringServer:
package main
import (
"fmt"
"log"
telepact "github.com/telepact/telepact/lib/go"
)
func main() {
files, err := telepact.NewTelepactSchemaFiles("./directory/containing/api/files")
if err != nil {
log.Fatal(err)
}
schema, err := telepact.TelepactSchemaFromFileJSONMap(files.FilenamesToJSON)
if err != nil {
log.Fatal(err)
}
// The schema directory may contain multiple *.telepact.yaml and
// *.telepact.json files. Subdirectories are rejected.
functionRoutes := map[string]telepact.FunctionRoute{
"fn.greet": func(functionName string, requestMessage telepact.Message) (telepact.Message, error) {
arguments, ok := requestMessage.Body[functionName].(map[string]any)
if !ok {
return telepact.Message{}, fmt.Errorf("unexpected %s payload", functionName)
}
subject, _ := arguments["subject"].(string)
return telepact.NewMessage(
map[string]any{},
map[string]any{
"Ok_": map[string]any{
"message": fmt.Sprintf("Hello %s!", subject),
},
},
), nil
},
}
serverOptions := telepact.NewServerOptions()
// Set this to false when your schema does not define union.Auth_.
serverOptions.Middleware = func(request telepact.Message, functionRouter *telepact.FunctionRouter) (telepact.Message, error) {
functionName, err := request.BodyTarget()
if err != nil {
return telepact.Message{}, err
}
log.Printf("Function started: %s", functionName)
defer log.Printf("Function finished: %s", functionName)
return functionRouter.Route(request)
}
functionRouter := telepact.NewFunctionRouter(functionRoutes)
server, err := telepact.NewServer(schema, functionRouter, serverOptions)
if err != nil {
log.Fatal(err)
}
// Wire up request/response bytes from your transport of choice
transport.Receive(func(requestBytes []byte) ([]byte, error) {
response, err := server.Process(requestBytes)
if err != nil {
return nil, err
}
return response.Bytes, nil
})
}Client:
package main
import (
"context"
"log"
telepact "github.com/telepact/telepact/lib/go"
)
func main() {
adapter := func(ctx context.Context, request telepact.Message, serializer *telepact.Serializer) (telepact.Message, error) {
requestBytes, err := serializer.Serialize(request)
if err != nil {
return telepact.Message{}, err
}
// Wire up request/response bytes to your transport of choice
responseBytes, err := transport.Send(ctx, requestBytes)
if err != nil {
return telepact.Message{}, err
}
return serializer.Deserialize(responseBytes)
}
clientOptions := telepact.NewClientOptions()
client, err := telepact.NewClient(adapter, clientOptions)
if err != nil {
log.Fatal(err)
}
response, err := client.Request(
telepact.NewMessage(
map[string]any{},
map[string]any{
"fn.greet": map[string]any{"subject": "Telepact"},
},
),
)
if err != nil {
log.Fatal(err)
}
log.Printf("Response: %+v", response)
}For more concrete usage examples, see the tests.
#Java
#Java version
Requires Java 21.
#Installation
<dependency>
<groupId>io.github.telepact</groupId>
<artifactId>telepact</artifactId>
</dependency>#Usage
API:
- fn.greet:
subject: string
->:
Ok_:
message: stringServer:
import io.github.telepact.Client;
import io.github.telepact.FunctionRoute;
import io.github.telepact.FunctionRouter;
import io.github.telepact.Message;
import io.github.telepact.Serializer;
import io.github.telepact.Server;
import io.github.telepact.TelepactSchema;
import io.github.telepact.TelepactSchemaFiles;
var files = new TelepactSchemaFiles("./directory/containing/api/files");
var schema = TelepactSchema.fromFileJsonMap(files.filenamesToJson);
// The schema directory may contain multiple *.telepact.yaml and
// *.telepact.json files. Subdirectories are rejected.
Map<String, FunctionRoute> functionRoutes = Map.of(
"fn.greet",
(functionName, requestMessage) -> {
var arguments = (Map<String, Object>) requestMessage.body.get(functionName);
var subject = (String) arguments.get("subject");
return new Message(Map.of(), Map.of("Ok_", Map.of("message", "Hello %s!".formatted(subject))));
}
);
var options = new Server.Options();
// Set this to false when your schema does not define union.Auth_.
options.middleware = (requestMessage, functionRouter) -> {
var functionName = requestMessage.getBodyTarget();
try {
log.info("Function started", Map.of("function", functionName));
return functionRouter.route(requestMessage);
} finally {
log.info("Function finished", Map.of("function", functionName));
}
};
var functionRouter = new FunctionRouter(functionRoutes);
var server = new Server(schema, functionRouter, options);
// Wire up request/response bytes from your transport of choice
transport.receive((requestBytes) -> {
var response = server.process(requestBytes);
return response.bytes;
});Client:
BiFunction<Message, Serializer, Future<Message>> adapter = (m, s) -> {
return CompletableFuture.supplyAsync(() -> {
var requestBytes = s.serialize(m);
// Wire up request/response bytes to your transport of choice
var responseBytes = transport.send(requestBytes);
return s.deserialize(responseBytes);
});
};
var options = new Client.Options();
var client = new Client(adapter, options);
var request = new Message(
Map.of(),
Map.of("fn.greet", Map.of("subject", "World"))
);
var response = client.request(request);
if ("Ok_".equals(response.getBodyTarget())) {
var okPayload = response.getBodyPayload();
System.out.println(okPayload.get("message"));
} else {
throw new RuntimeException("Unexpected response: " + response.body);
}For more concrete usage examples, see the tests.
#Python
#Installation
pip install --pre telepact#Usage
API:
- fn.greet:
subject: string
->:
Ok_:
message: stringServer:
from telepact import Client, FunctionRouter, Message, Serializer, Server, TelepactSchema
schema = TelepactSchema.from_directory('/directory/containing/api/files')
# The schema directory may contain multiple *.telepact.yaml and
# *.telepact.json files. Subdirectories are rejected.
async def greet(function_name: str, request_message: 'Message') -> 'Message':
arguments = request_message.body[function_name]
subject = arguments['subject']
return Message({}, {'Ok_': {'message': f'Hello {subject}!'}})
async def middleware(request_message: 'Message', function_router) -> 'Message':
function_name = request_message.get_body_target()
try:
log.info("Function started", {'function': function_name})
return await function_router.route(request_message)
finally:
log.info("Function finished", {'function': function_name})
options = Server.Options()
# Set this to False when your schema does not define union.Auth_.
options.middleware = middleware
function_router = FunctionRouter({'fn.greet': greet})
server = Server(schema, function_router, options)
# Wire up request/response bytes from your transport of choice
async def transport_handler(request_bytes: bytes) -> bytes:
response = await server.process(request_bytes)
return response.bytes
transport.receive(transport_handler)Client:
async def adapter(m: Message, s: Serializer) -> Message:
request_bytes = s.serialize(m)
# Wire up request/response bytes to your transport of choice
response_bytes = await transport.send(request_bytes)
return s.deserialize(response_bytes)
options = Client.Options()
client = Client(adapter, options)
# Inside your async application code:
request = Message({}, {'fn.greet': {'subject': 'World'}})
response = await client.request(request)
if response.get_body_target() == 'Ok_':
ok_payload = response.get_body_payload()
print(ok_payload['message'])
else:
raise RuntimeError(f"Unexpected response: {response.body}")For more concrete usage examples, see the tests.
#TypeScript
#Installation
npm install telepact#Usage
API:
- fn.greet:
subject: string
->:
Ok_:
message: stringServer:
import * as fs from 'fs';
import * as path from 'path';
import { FunctionRouter, Message, Server, ServerOptions, TelepactSchema, TelepactSchemaFiles } from 'telepact';
const files = new TelepactSchemaFiles('/directory/containing/api/files', fs, path);
const schema = TelepactSchema.fromFileJsonMap(files.filenamesToJson);
// The schema directory may contain multiple *.telepact.yaml and
// *.telepact.json files. Subdirectories are rejected.
const functionRoutes = {
'fn.greet': async (functionName: string, requestMessage: Message): Promise<Message> => {
const argument = requestMessage.body[functionName] as Record<string, any>;
const subject = argument['subject'];
return new Message({}, {Ok_: {message: `Hello ${subject}!`}});
},
};
const options = new ServerOptions();
// Set this to false when your schema does not define union.Auth_.
options.middleware = async (requestMessage: Message, functionRouter): Promise<Message> => {
const functionName = requestMessage.getBodyTarget();
try {
log.info("Function started", {function: functionName});
return await functionRouter.route(requestMessage);
} finally {
log.info("Function finished", {function: functionName});
}
};
const functionRouter = new FunctionRouter(functionRoutes);
const server = new Server(schema, functionRouter, options);
// Wire up request/response bytes from your transport of choice
transport.receive(async (requestBytes: Uint8Array): Promise<Uint8Array> => {
const response = await server.process(requestBytes);
return response.bytes;
});Client:
import { Client, ClientOptions, Message, Serializer } from 'telepact';
const adapter: (m: Message, s: Serializer) => Promise<Message> = async (m, s) => {
const requestBytes = s.serialize(m);
// Wire up request/response bytes to your transport of choice
const responseBytes = await transport.send(requestBytes);
return s.deserialize(responseBytes);
};
const options = new ClientOptions();
const client = new Client(adapter, options);
// Inside an async function in your application:
const request = new Message({}, { 'fn.greet': { subject: 'World' } });
const response = await client.request(request);
if (response.getBodyTarget() === 'Ok_') {
const okPayload = response.getBodyPayload();
console.log(okPayload.message);
} else {
throw new Error(`Unexpected response: ${JSON.stringify(response.body)}`);
}#See also
Transport Guide for browser TypeScript +
fetchand WebSocket examplesClient Paths for choosing between plain JSON, the runtime library, and generated code
Demos for runnable end-to-end examples
#CLI
The CLI is a tool for various development jobs, such as fetching API schemas, starting schema-backed mock servers for testing purposes, and optionally generating code.
#Installation
uv tool install --prerelease=allow telepact-cli#Usage
#telepact --help
Usage: telepact [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
codegen Generate code bindings for a Telepact API schema.
compare Compare two Telepact API schemas for backwards compatibility.
demo-server Start a demo Telepact server.
fetch Fetch a Telepact API schema to store locally.
mock Start a mock server for a Telepact API schema.#telepact codegen --help
Usage: telepact codegen [OPTIONS]
Generate code bindings for a Telepact API schema.
Options:
--schema-http-url TEXT telepact schema directory
--schema-dir TEXT telepact schema directory
--lang TEXT Language target (one of "java", "py", "ts", or "go")
[required]
--out TEXT Output directory [required]
--package TEXT Package name (required when --lang is "java" or "go")
--help Show this message and exit.#telepact compare --help
Usage: telepact compare [OPTIONS]
Compare two Telepact API schemas for backwards compatibility.
Options:
--new-schema-dir TEXT New telepact schema directory [required]
--old-schema-dir TEXT Old telepact schema directory [required]
--help Show this message and exit.#telepact fetch --help
Usage: telepact fetch [OPTIONS]
Fetch a Telepact API schema to store locally.
Options:
--http-url TEXT HTTP URL of a Telepact API [required]
--output-dir TEXT Directory of Telepact schemas [required]
--help Show this message and exit.#telepact mock --help
Usage: telepact mock [OPTIONS]
Start a mock server for a Telepact API schema.
Options:
--http-url TEXT HTTP URL of a Telepact API
--dir TEXT Directory of Telepact schemas
--port INTEGER Port to run the mock server on
--path TEXT Path to expose the mock API (default: /api)
--generated-collection-length-min INTEGER
Minimum length of generated collections
--generated-collection-length-max INTEGER
Maximum length of generated collections
--disable-optional-field-generation
Disable generation of optional fields
(enabled by default)
--disable-message-response-generation
Disable generation of message responses
(enabled by default)
--disable-random-optional-field-generation
Disable randomization of optional field
generation (enabled by default)
--help Show this message and exit.NOTE: The mock command is an empowering development tool for clients. You do not need to develop against a live server; you can use the mock command to set up a "middle-man" server that will validate requests for schema compliance and return schema-compliant auto-generated responses (which can be overridden with manual stubs if desired.)
#Console
The Console is a debugging tool that allows you to easily connect to your running Telepact server, visualize your API with interactive documentation, and submit live requests to your server.
#Installation
npm install -g telepact-console#Usage
npx telepact-console -p 8080Then you can access the UI in your browser at http://localhost:8080.
When launched through the npm CLI, the Console proxies absolute live HTTP and WebSocket URLs through its own localhost server first while keeping the self-hosted build unchanged for same-domain embeds.
#Docker
The Console is also available as a docker image, which can be installed directly from Releases. You can copy the link for the Console from the release assets.
Example:
curl -L -o telepact-docker.tar.gz https://github.com/Telepact/telepact/releases/download/{version}/docker-image-telepact-console-{version}.tar.gz
docker load < telepact-docker.tar.gzStarting the docker container:
docker run -p 8080:8080 telepact-console:{version}For a more concrete usage example, see self-hosting example.
#Prettier Plugin
Formats .telepact.yaml and .telepact.yml schema files to match the checked-in Telepact schema style:
///docstrings are emitted as YAML|block scalarsTelepact field values stay in inline JSON form
#Installation
npm install prettier-plugin-telepact#Usage
Add the plugin to your Prettier config:
{
"plugins": ["prettier-plugin-telepact"]
}