lokalise-mcp
Version:
The Lokalise MCP Server brings Lokalise's localization power to Claude and AI assistants—manage projects, keys, and translations by chat.
210 lines (209 loc) • 7.91 kB
JavaScript
/**
* Contributors Service
*
* Service layer for interacting with Lokalise Contributors API.
* Handles all API communication and data transformation.
*/
import { LokaliseApi } from "@lokalise/node-api";
import { config } from "../../shared/utils/config.util.js";
import { createApiError, createUnexpectedError, } from "../../shared/utils/error.util.js";
import { Logger } from "../../shared/utils/logger.util.js";
const logger = Logger.forContext("contributors.service.ts");
// ============================================================================
// Service Implementation
// ============================================================================
let lokaliseApi = null;
/**
* Gets or creates the Lokalise API instance
*/
function getLokaliseApi() {
if (!lokaliseApi) {
const apiKey = config.get("LOKALISE_API_KEY");
if (!apiKey) {
throw createApiError("LOKALISE_API_KEY is required but not found in configuration", 401);
}
const apiHost = config.get("LOKALISE_API_HOSTNAME") ||
"https://api.stage.lokalise.cloud/api2/";
lokaliseApi = new LokaliseApi({ apiKey, host: apiHost });
}
return lokaliseApi;
}
/**
* Contributors service for Lokalise API operations
*/
export const contributorsService = {
/**
* List contributors for a project
*/
async list(args) {
const methodLogger = logger.forMethod("list");
methodLogger.info("Listing contributors", {
projectId: args.projectId,
page: args.page,
limit: args.limit,
});
try {
const api = getLokaliseApi();
const result = await api.contributors().list({
project_id: args.projectId,
page: args.page,
limit: args.limit,
});
methodLogger.info("Listed contributors successfully", {
projectId: args.projectId,
count: result.items.length,
totalResults: result.totalResults,
});
return result;
}
catch (error) {
methodLogger.error("Failed to list contributors", { error, args });
throw createUnexpectedError(`Failed to list contributors for project ${args.projectId}`, error);
}
},
/**
* Add contributors to a project
*/
async create(args) {
const methodLogger = logger.forMethod("create");
methodLogger.info("Adding contributors", {
projectId: args.projectId,
count: args.contributors.length,
});
try {
const api = getLokaliseApi();
// Map our schema to SDK types
const contributorData = args.contributors.map((c) => ({
email: c.email,
fullname: c.fullname,
is_admin: c.is_admin,
is_reviewer: c.is_reviewer,
languages: c.languages,
admin_rights: c.admin_rights, // SDK typing issue with enum array
}));
const result = await api.contributors().create(contributorData, {
project_id: args.projectId,
});
methodLogger.info("Added contributors successfully", {
projectId: args.projectId,
added: result.length,
});
return result;
}
catch (error) {
methodLogger.error("Failed to add contributors", { error, args });
throw createUnexpectedError(`Failed to add contributors to project ${args.projectId}`, error);
}
},
/**
* Get a specific contributor
*/
async get(args) {
const methodLogger = logger.forMethod("get");
methodLogger.info("Getting contributor", {
projectId: args.projectId,
contributorId: args.contributorId,
});
try {
const api = getLokaliseApi();
const result = await api.contributors().get(args.contributorId, {
project_id: args.projectId,
});
methodLogger.info("Retrieved contributor successfully", {
projectId: args.projectId,
contributorId: args.contributorId,
email: result.email,
});
return result;
}
catch (error) {
methodLogger.error("Failed to get contributor", { error, args });
throw createUnexpectedError(`Failed to get contributor ${args.contributorId} from project ${args.projectId}`, error);
}
},
/**
* Get current user's contributor profile
*/
async me(args) {
const methodLogger = logger.forMethod("me");
methodLogger.info("Getting current user contributor profile", {
projectId: args.projectId,
});
try {
const api = getLokaliseApi();
const result = await api.contributors().me({
project_id: args.projectId,
});
methodLogger.info("Retrieved current user profile successfully", {
projectId: args.projectId,
userId: result.user_id,
email: result.email,
});
return result;
}
catch (error) {
methodLogger.error("Failed to get current user profile", { error, args });
throw createUnexpectedError(`Failed to get current user profile for project ${args.projectId}`, error);
}
},
/**
* Update a contributor
*/
async update(args) {
const methodLogger = logger.forMethod("update");
methodLogger.info("Updating contributor", {
projectId: args.projectId,
contributorId: args.contributorId,
});
try {
const api = getLokaliseApi();
// Build update data
const updateData = {};
if (args.is_admin !== undefined)
updateData.is_admin = args.is_admin;
if (args.is_reviewer !== undefined)
updateData.is_reviewer = args.is_reviewer;
if (args.languages)
updateData.languages = args.languages;
if (args.admin_rights)
updateData.admin_rights = args.admin_rights;
const result = await api
.contributors()
.update(args.contributorId, updateData, { project_id: args.projectId });
methodLogger.info("Updated contributor successfully", {
projectId: args.projectId,
contributorId: args.contributorId,
});
return result;
}
catch (error) {
methodLogger.error("Failed to update contributor", { error, args });
throw createUnexpectedError(`Failed to update contributor ${args.contributorId} in project ${args.projectId}`, error);
}
},
/**
* Remove a contributor from a project
*/
async delete(args) {
const methodLogger = logger.forMethod("delete");
methodLogger.info("Removing contributor", {
projectId: args.projectId,
contributorId: args.contributorId,
});
try {
const api = getLokaliseApi();
const result = await api.contributors().delete(args.contributorId, {
project_id: args.projectId,
});
methodLogger.info("Removed contributor successfully", {
projectId: args.projectId,
contributorId: args.contributorId,
});
return result;
}
catch (error) {
methodLogger.error("Failed to remove contributor", { error, args });
throw createUnexpectedError(`Failed to remove contributor ${args.contributorId} from project ${args.projectId}`, error);
}
},
};