Massimo is an API SDK client and CLI tool for creating fully-typed clients for remote OpenAPI or GraphQL APIs. Generate TypeScript/JavaScript clients with automatic type inference, authentication support, and seamless integration with popular frontend frameworks.
Why "Massimo"? The name is inspired by Massimo Troisi, the beloved Italian actor from the film "Il Postino" (The Postman). Just as the postman in the movie delivered messages and connected people, Massimo delivers API connections and bridges the gap between services, making communication between applications as effortless and poetic as Troisi's unforgettable performance.
- OpenAPI Client Generation: Create fully-typed clients from OpenAPI 3.x specifications
- GraphQL Client Generation: Generate clients from GraphQL schemas with type support
- TypeScript First: Full TypeScript support with automatic type generation
- Framework Agnostic: Works with any Node.js application or frontend framework
- Authentication Support: Built-in support for headers, tokens, and custom authentication
- Fastify Plugin: Ready-to-use Fastify plugin for seamless integration
npm install -g massimo-cli
npm install massimo
massimo http://api.example.com/openapi.json --name myclient
massimo http://api.example.com/graphql --name myclient --type graphql
JavaScript/TypeScript (Node.js, Undici-based):
The undici-based client is preferred for Node.js environments when you need:
- Maximum performance - Undici is the fastest HTTP/1.1 client for Node.js
- Advanced connection management with pooling, keep-alive, and pipelining
- HTTP/2 support with full capabilities
- Node.js optimized runtime (bundled with Node.js 18+)
- Advanced features like interceptors, custom dispatchers, and WebSocket support
- Efficient streaming with pipeline and stream methods for large payloads
- Comprehensive error types and network-level error handling
// Generate Node.js client
// massimo http://api.example.com/openapi.json --name myclient
import myClient from "./myclient/myclient.mjs";
const client = await myClient({
url: "https://api.example.com",
});
// OpenAPI
const users = await client.getUsers();
const newUser = await client.createUser({ name: "John Doe" });
// GraphQL
const result = await client.graphql({
query: "query { users { id name } }",
});
Frontend Client (Browser, Fetch-based):
The fetch-based client is preferred for browser environments and when you need:
- Browser compatibility with native Fetch API (Undici is Node.js-only)
- Zero dependencies for minimal bundle size
- Isomorphic code that runs in browsers and Node.js
- Maximum compatibility across all JavaScript runtimes
- Simple HTTP requests without advanced configuration
- Publishing to npm with broadest runtime support
- Independence from specific undici version features
// Generate frontend client
// massimo http://api.example.com/openapi.json --frontend --name myclient
// Option 1: Named operations
import { setBaseUrl, getUsers, createUser } from "./myclient/api.mjs";
setBaseUrl("https://api.example.com");
// Make type-safe API calls
const users = await getUsers({});
const newUser = await createUser({
name: "Jane Doe",
email: "[email protected]",
});
// Option 2: Factory method
import buildClient from "./myclient/api.mjs";
const client = buildClient("https://api.example.com");
// Set default headers for authentication
client.setDefaultHeaders({
Authorization: "Bearer token",
});
const users = await client.getUsers({});
const user = await client.getUserById({ id: "123" });
Fastify Plugin:
import fastify from "fastify";
import pltClient from "massimo/fastify-plugin.js";
const server = fastify();
server.register(pltClient, {
url: "http://example.com",
type: "openapi", // or "graphql"
});
// OpenAPI
server.post("/", async (request, reply) => {
const res = await request.movies.createMovie({ title: "foo" });
return res;
});
server.listen({ port: 3000 });
Note that you would need to install massimo
as a dependency.
TypeScript with Fastify Plugin:
Massimo generates full TypeScript support for Fastify. To add types information to your plugin, you can either extend the FastifyRequest interface globally or locally.
import { type MoviesClient } from "./movies/movies.ts";
import fastify, { type FastifyRequest } from "fastify";
import pltClient from "massimo/fastify-plugin.js";
const server = fastify();
server.register(pltClient, {
url: "http://example.com",
type: "openapi", // or "graphql"
});
// Method A: extend the interface globally
declare module "fastify" {
interface FastifyRequest {
movies: MoviesClient;
}
}
server.get("/movies", async (request: FastifyRequest, reply: FastifyReply) => {
return request.movies.getMovies();
});
// Method B: use a local request extension
interface MoviesRequest extends FastifyRequest {
movies: MoviesClient;
}
server.get("/movies", async (request: MoviesRequest, reply: FastifyReply) => {
return request.movies.getMovies();
});
# Generate client from URL
massimo <url> --name <client-name>
# Generate from local file
massimo ./openapi.json --name myclient
# Generate only TypeScript types
massimo <url> --name myclient --types-only
# Specify client type (auto-detected by default)
massimo <url> --name myclient --type openapi
massimo <url> --name myclient --type graphql
# Custom output folder
massimo <url> --name myclient --folder ./clients
# Specify module format (valid values: esm, cjs)
massimo <url> --name myclient --module esm
massimo <url> --name myclient --module cjs
# Force TypeScript declaration file extensions (.d.mts/.d.cts)
massimo <url> --name myclient --type-extension
Massimo automatically detects and generates the appropriate module format (ESM or CommonJS) for your clients:
When no --module
flag is specified, Massimo:
- Searches for the nearest
package.json
starting from the output directory and walking up the directory tree - If package.json is found, checks the
type
field:- If
"type": "module"
→ Generates ESM files (.mjs
,.d.mts
) - If
"type"
is missing or any other value → Generates CommonJS files (.cjs
,.d.ts
)
- If
- If no package.json is found → Defaults to ESM files (
.mjs
,.d.mts
) - Generated files:
- ESM:
client.mjs
+client.d.mts
+package.json
with"type": "module"
- CommonJS:
client.cjs
+client.d.ts
+package.json
without"type"
field
- ESM:
When using the --module
flag:
# Force ESM generation
massimo <url> --name myclient --module esm
# Force CommonJS generation
massimo <url> --name myclient --module cjs
This overrides any auto-detection and generates files in the specified format.
Module Format | Implementation | Types | Package.json |
---|---|---|---|
ESM | .mjs |
.d.mts |
"type": "module" |
CommonJS | .cjs |
.d.cts |
No "type" field |
Massimo uses intelligent logic to determine the appropriate TypeScript declaration file extension (.d.ts
, .d.mts
, or .d.cts
):
-
When
--type-extension
is specified:- Always generates module-specific extensions
- ESM format →
.d.mts
- CommonJS format →
.d.cts
-
When
--type-extension
is NOT specified:- If
--module
flag is provided:- Compares the specified module format with the parent package.json type
- If they match → generates
.d.ts
(universal compatibility) - If they differ → generates module-specific extension (
.d.mts
or.d.cts
)
- If no
--module
flag is provided:- Always generates
.d.ts
for maximum compatibility
- Always generates
- If
-
Parent Package.json Detection:
- Searches up the directory tree from the output location
- Stops at the first package.json found
- ESM parent:
"type": "module"
- CommonJS parent: no
type
field or"type": "commonjs"
# Always use module-specific extensions
massimo <url> --name myclient --type-extension
# Generate .d.ts when module format matches parent package.json
massimo <url> --name myclient --module esm # In ESM project → .d.ts
massimo <url> --name myclient --module cjs # In CommonJS project → .d.ts
# Generate module-specific when formats differ
massimo <url> --name myclient --module esm # In CommonJS project → .d.mts
massimo <url> --name myclient --module cjs # In ESM project → .d.cts
# Auto-detect everything (no module flag) → always .d.ts
massimo <url> --name myclient # → .d.ts (maximum compatibility)
# Explicit module generates module-specific when no parent package.json
massimo <url> --name myclient --module esm # No parent pkg → .d.mts
massimo <url> --name myclient --module cjs # No parent pkg → .d.cts
interface ClientOptions {
url: string; // Base URL for the API
headers?: Record<string, string>; // Default headers
timeout?: number; // Request timeout in ms
throwOnError?: boolean; // Throw on HTTP errors
}
const client = await generateMyClient({
url: "https://api.example.com",
headers: {
Authorization: "Bearer token",
},
timeout: 5000,
throwOnError: true,
});
Configure authentication headers dynamically:
// In a Fastify plugin
app.configureMyClient({
async getHeaders(req, reply) {
return {
Authorization: `Bearer ${req.user.token}`,
"X-User-ID": req.user.id,
};
},
});
Massimo generates full TypeScript definitions:
// Generated types for OpenAPI
interface GetUsersResponse {
id: string;
name: string;
email: string;
}
interface CreateUserRequest {
name: string;
email: string;
}
interface Client {
getUsers(): Promise<GetUsersResponse[]>;
createUser(req: CreateUserRequest): Promise<GetUsersResponse>;
}
// Generated types for GraphQL
interface User {
id?: string;
name?: string;
email?: string;
}
interface GraphQLClient {
graphql<T>(options: {
query: string;
variables?: Record<string, unknown>;
headers?: Record<string, string>;
}): Promise<T>;
}
Massimo consists of two main packages:
massimo
: Core client library for generating and using API clientsmassimo-cli
: Command-line tool for generating client code
- OpenAPI 3.x: Full support for OpenAPI specifications with automatic client generation
- GraphQL: Support for GraphQL schemas with type generation
- Any HTTP API: As long as it exposes OpenAPI or GraphQL schemas
- Type Safety: Full TypeScript support with request/response typing
- Error Handling: Built-in error handling and validation
- Request/Response Interceptors: Middleware support for modifying requests/responses
- Retry Logic: Configurable retry mechanisms
- Telemetry: Automatic telemetry and tracing propagation
We welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/platformatic/massimo.git
cd massimo
pnpm install
pnpm test
# Run all tests
pnpm test
# Run tests for specific package
cd packages/massimo
npm test
Licensed under Apache 2.0.
Made with ❤️ by the Platformatic team.