@smartsamurai/krapi-sdk
Version:
KRAPI TypeScript SDK - Easy-to-use client SDK for connecting to self-hosted KRAPI servers (like Appwrite SDK)
146 lines (129 loc) • 4.15 kB
text/typescript
import { AxiosInstance } from "axios";
import { KrapiError } from "../core/krapi-error";
import { Project, CreateProjectRequest, UpdateProjectRequest } from "../types";
import { normalizeError } from "../utils/error-handler";
/**
* Project API Manager
*
* Handles all project-related API operations for the KRAPI client SDK.
*/
export class ProjectApiManager {
constructor(private axiosInstance: AxiosInstance) {}
/**
* Get all projects
* @returns {Promise<Project[]>} Array of projects
*/
async getAll(): Promise<Project[]> {
try {
// Let interceptor handle all headers - no explicit headers needed
const response = await this.axiosInstance.get<Project[]>(
"/krapi/k1/projects"
);
// Return data directly - backend returns Project[] directly
return Array.isArray(response.data) ? response.data : [];
} catch (error) {
throw normalizeError(error, "INTERNAL_ERROR", {
operation: "getProjects",
});
}
}
/**
* Get project by ID
* @param {string} id - Project ID
* @returns {Promise<Project>} Project object
*/
async get(id: string): Promise<Project> {
if (!id || typeof id !== "string") {
throw KrapiError.validationError("Project ID is required", "id");
}
try {
// Let interceptor handle all headers - no explicit headers needed
const response = await this.axiosInstance.get<Project>(
`/krapi/k1/projects/${id}`
);
// Return data directly - backend returns Project directly
return response.data;
} catch (error) {
throw normalizeError(error, "INTERNAL_ERROR", {
operation: "getProject",
projectId: id,
});
}
}
/**
* Create a new project
* @param {CreateProjectRequest} data - Project data
* @returns {Promise<Project>} Created project
*/
async create(data: CreateProjectRequest): Promise<Project> {
if (
!data ||
!data.name ||
typeof data.name !== "string" ||
data.name.trim() === ""
) {
throw KrapiError.validationError("Project name is required", "name");
}
try {
// Let interceptor handle headers - Authorization is already set as default,
// and Content-Type is set in axios defaults
const response = await this.axiosInstance.post<Project>(
"/krapi/k1/projects",
data
);
// Return data directly - backend returns Project directly
return response.data;
} catch (error) {
throw normalizeError(error, "INTERNAL_ERROR", {
operation: "createProject",
});
}
}
/**
* Update a project
* @param {string} id - Project ID
* @param {UpdateProjectRequest} data - Updated project data
* @returns {Promise<Project>} Updated project
*/
async update(id: string, data: UpdateProjectRequest): Promise<Project> {
if (!id || typeof id !== "string") {
throw KrapiError.validationError("Project ID is required", "id");
}
if (!data || typeof data !== "object") {
throw KrapiError.validationError("Update data is required", "data");
}
try {
// Let interceptor handle all headers - Content-Type is already in defaults
const response = await this.axiosInstance.put<Project>(
`/krapi/k1/projects/${id}`,
data
);
// Return data directly - backend returns Project directly
return response.data;
} catch (error) {
throw normalizeError(error, "INTERNAL_ERROR", {
operation: "updateProject",
projectId: id,
});
}
}
/**
* Delete a project
* @param {string} id - Project ID
* @returns {Promise<void>}
*/
async delete(id: string): Promise<void> {
if (!id || typeof id !== "string") {
throw KrapiError.validationError("Project ID is required", "id");
}
try {
// Let interceptor handle all headers - no explicit headers needed
await this.axiosInstance.delete(`/krapi/k1/projects/${id}`);
} catch (error) {
throw normalizeError(error, "INTERNAL_ERROR", {
operation: "deleteProject",
projectId: id,
});
}
}
}