Installation
Copy
npm install @mesadev/sdk
# or
pnpm add @mesadev/sdk
# or
bun add @mesadev/sdk
Quick Start
Copy
import { Mesa } from "@mesadev/sdk";
const mesa = new Mesa({
apiKey: process.env.MESA_API_KEY,
});
// Create a repository
const repo = await mesa.repos.create({
org: "my-org",
body: { name: "my-repo" },
});
// List all repositories
const { result } = await mesa.repos.list({ org: "my-org" });
console.log(result.repos);
Configuration
The SDK accepts the following configuration options:Copy
const mesa = new Mesa({
// Required: Your API key for authentication
apiKey: "your-api-key",
// Optional: Override the default server URL
serverURL: "https://api.mesa.dev",
// Optional: Default timeout for requests (in milliseconds)
timeoutMs: 30000,
// Optional: Retry configuration
retryConfig: {
strategy: "backoff",
backoff: {
initialInterval: 500,
maxInterval: 60000,
exponent: 1.5,
maxElapsedTime: 300000,
},
},
});
Environment Variables
The SDK automatically reads from these environment variables if not explicitly configured:MESA_API_KEY- Your API key
Resources
The SDK organizes methods into resource namespaces that mirror the API structure.Repositories
Copy
// Create a repository
const repo = await mesa.repos.create({
org: "my-org",
body: {
name: "my-repo",
defaultBranch: "main", // optional, defaults to "main"
},
});
// List repositories (paginated)
const { result } = await mesa.repos.list({
org: "my-org",
limit: 50, // optional
cursor: "...", // optional, for pagination
});
// Get a specific repository
const repo = await mesa.repos.get({
org: "my-org",
repo: "my-repo",
});
// Update a repository
const updated = await mesa.repos.update({
org: "my-org",
repo: "my-repo",
body: { name: "new-name" },
});
// Delete a repository
await mesa.repos.delete({
org: "my-org",
repo: "my-repo",
});
Branches
Copy
// List branches (paginated)
const { result } = await mesa.branches.list({
org: "my-org",
repo: "my-repo",
});
// Create a branch
const branch = await mesa.branches.create({
org: "my-org",
repo: "my-repo",
body: {
name: "feature-branch",
headSha: "abc123...", // SHA to branch from
},
});
// Delete a branch
await mesa.branches.delete({
org: "my-org",
repo: "my-repo",
branch: "feature-branch",
});
Commits
Copy
// List commits (paginated)
const { result } = await mesa.commits.list({
org: "my-org",
repo: "my-repo",
ref: "main", // optional, branch or tag
});
// Get a specific commit
const commit = await mesa.commits.get({
org: "my-org",
repo: "my-repo",
sha: "abc123...",
});
// Create a commit programmatically
const commit = await mesa.commits.create({
org: "my-org",
repo: "my-repo",
body: {
branch: "main",
message: "Add new file",
author: {
name: "John Doe",
email: "john@example.com",
},
edits: [
{
path: "README.md",
action: "create",
content: "# Hello World",
},
],
},
});
Content
Copy
// Get file content (returns base64-encoded content)
const file = await mesa.content.get({
org: "my-org",
repo: "my-repo",
path: "src/index.ts",
ref: "main", // optional
});
// Get directory listing
const dir = await mesa.content.get({
org: "my-org",
repo: "my-repo",
path: "src",
ref: "main",
});
// The response type depends on whether the path is a file or directory
if (file.type === "file") {
console.log(atob(file.content)); // Decode base64 content
} else {
console.log(file.entries); // Array of directory entries
}
Diffs
Copy
// Get diff between two refs
const diff = await mesa.diffs.get({
org: "my-org",
repo: "my-repo",
base: "main",
head: "feature-branch",
});
// Response includes file changes
for (const file of diff.files) {
console.log(`${file.status}: ${file.path}`);
}
Merge
Copy
// Merge a branch into another (fast-forward when possible)
const result = await mesa.merge.perform({
org: "my-org",
repo: "my-repo",
base: "main",
body: {
head: "feature-branch",
author: {
name: "John Doe",
email: "john@example.com",
},
},
});
console.log(result.mergeType); // "fast_forward" or "merge_commit"
console.log(result.sha); // Resulting commit SHA
Copy
// Merge with a custom commit message
const result = await mesa.merge.perform({
org: "my-org",
repo: "my-repo",
base: "main",
body: {
head: "feature-branch",
message: "Ship feature X",
author: {
name: "John Doe",
email: "john@example.com",
},
},
});
Copy
// Merge and delete the head branch afterward
const result = await mesa.merge.perform({
org: "my-org",
repo: "my-repo",
base: "main",
body: {
head: "feature-branch",
author: {
name: "John Doe",
email: "john@example.com",
},
deleteBranch: true,
},
});
console.log(result.branchDeleted); // true
The merge endpoint returns
409 MERGE_CONFLICT when the branches have conflicting changes that cannot be auto-resolved. Catch this error to handle conflicts in your workflow.Admin (API Keys)
Copy
// Create an API key
const key = await mesa.admin.createApiKey({
org: "my-org",
body: {
name: "CI/CD Key",
scopes: ["git:read", "git:write"],
},
});
console.log(key.key); // Only shown once!
// List API keys
const keys = await mesa.admin.listApiKeys({
org: "my-org",
});
// Revoke an API key
await mesa.admin.revokeApiKey({
org: "my-org",
id: "key_123",
});
Pagination
List endpoints return aPageIterator that supports both direct access and async iteration.
Direct Access
Copy
// Get first page
const page = await mesa.repos.list({ org: "my-org" });
console.log(page.result.repos);
console.log(page.result.hasMore);
console.log(page.result.nextCursor);
// Get next page
if (page.result.hasMore) {
const nextPage = await page.next();
}
Async Iteration
Copy
// Iterate through all pages
for await (const page of await mesa.repos.list({ org: "my-org" })) {
for (const repo of page.result.repos) {
console.log(repo.name);
}
}
Manual Cursor Pagination
Copy
let cursor: string | undefined;
do {
const { result } = await mesa.repos.list({
org: "my-org",
cursor,
limit: 100,
});
for (const repo of result.repos) {
console.log(repo.name);
}
cursor = result.nextCursor ?? undefined;
} while (cursor);
Error Handling
The SDK throws typed errors that you can catch and handle:Copy
import { Mesa } from "@mesadev/sdk";
import * as errors from "mesa/models/errors";
try {
await mesa.repos.get({ org: "my-org", repo: "nonexistent" });
} catch (error) {
if (error instanceof errors.GetOrgRepoNotFoundError) {
console.log("Repository not found");
} else if (error instanceof errors.GetOrgRepoUnauthorizedError) {
console.log("Invalid API key");
} else if (error instanceof errors.GetOrgRepoForbiddenError) {
console.log("Access denied");
} else {
throw error;
}
}
Error Types
All API errors follow a consistent structure:Copy
{
code: string; // Error code (e.g., "NOT_FOUND")
message: string; // Human-readable message
details?: object; // Additional error details
}
Per-Request Options
You can override configuration on a per-request basis:Copy
const repo = await mesa.repos.get(
{ org: "my-org", repo: "my-repo" },
{
// Override timeout for this request
timeoutMs: 60000,
// Override retry configuration
retries: {
strategy: "backoff",
backoff: {
initialInterval: 1000,
maxInterval: 30000,
exponent: 2,
maxElapsedTime: 60000,
},
},
// Add custom headers
headers: {
"X-Custom-Header": "value",
},
}
);
TypeScript Support
The SDK is fully typed. Import types from the models:Copy
import type {
PostOrgReposRequest,
PostOrgReposResponse,
GetOrgReposRequest,
Repo,
} from "mesa/models/operations";
// Use types for better IDE support
const request: PostOrgReposRequest = {
org: "my-org",
body: { name: "my-repo" },
};
Complete Example
Copy
import { Mesa } from "@mesadev/sdk";
async function main() {
const mesa = new Mesa({
apiKey: process.env.MESA_API_KEY!,
});
// Create a repository
const repo = await mesa.repos.create({
org: "my-org",
body: { name: "example-repo" },
});
console.log(`Created repository: ${repo.name}`);
// Create initial commit
await mesa.commits.create({
org: "my-org",
repo: "example-repo",
body: {
branch: "main",
message: "Initial commit",
author: {
name: "Bot",
email: "bot@example.com",
},
edits: [
{
path: "README.md",
action: "create",
content: "# Example Repository\n\nThis is an example.",
},
],
},
});
// Create a feature branch
const mainCommits = await mesa.commits.list({
org: "my-org",
repo: "example-repo",
ref: "main",
});
await mesa.branches.create({
org: "my-org",
repo: "example-repo",
body: {
name: "feature",
headSha: mainCommits.result.commits[0].sha,
},
});
// Make changes on feature branch
await mesa.commits.create({
org: "my-org",
repo: "example-repo",
body: {
branch: "feature",
message: "Add feature",
author: {
name: "Bot",
email: "bot@example.com",
},
edits: [
{
path: "feature.ts",
action: "create",
content: "export const feature = true;",
},
],
},
});
// Get diff between branches
const diff = await mesa.diffs.get({
org: "my-org",
repo: "example-repo",
base: "main",
head: "feature",
});
console.log(`Changes: ${diff.files.length} files`);
// Merge feature branch into main and clean up
const merge = await mesa.merge.perform({
org: "my-org",
repo: "example-repo",
base: "main",
body: {
head: "feature",
author: {
name: "Bot",
email: "bot@example.com",
},
deleteBranch: true,
},
});
console.log(`Merged via ${merge.mergeType}: ${merge.sha}`);
}
main().catch(console.error);

