UNPKG

@nicodoggie/node-kiwi-tcms-api

Version:

Vibe-coded Node.js wrapper for Kiwi TCMS XML-RPC API. Use at your own risk.

224 lines 7.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UrlAPI = exports.KiwiUtilsAPI = exports.MarkdownAPI = exports.AttachmentAPI = void 0; /** * Attachment API module */ class AttachmentAPI { client; constructor(client) { this.client = client; } /** * Remove an attachment */ async remove(attachmentId) { await this.client.authenticatedCall('Attachment.remove_attachment', [attachmentId]); } } exports.AttachmentAPI = AttachmentAPI; /** * Markdown API module */ class MarkdownAPI { client; constructor(client) { this.client = client; } /** * Render markdown to HTML */ async render(markdownText) { return await this.client.authenticatedCall('Markdown.render', [markdownText]); } } exports.MarkdownAPI = MarkdownAPI; /** * Kiwi TCMS system utilities */ class KiwiUtilsAPI { client; constructor(client) { this.client = client; } /** * Get Kiwi TCMS version */ async version() { return await this.client.call('Kiwi.version'); } /** * Extract tracker information from URL */ async trackerFromUrl(url) { return await this.client.authenticatedCall('Utils.tracker_from_url', [url]); } } exports.KiwiUtilsAPI = KiwiUtilsAPI; /** * URL generation utilities for creating permalinks and slugs */ class UrlAPI { client; constructor(client) { this.client = client; } /** * Generate a permalink URL for a test case * @param testCaseId - The ID of the test case * @returns The full URL to the test case */ generateTestCaseUrl(testCaseId) { const baseUrl = this.getBaseWebUrl(); return `${baseUrl}/case/${testCaseId}/`; } /** * Generate a permalink URL for a test plan * @param testPlanId - The ID of the test plan * @returns The full URL to the test plan */ generateTestPlanUrl(testPlanId) { const baseUrl = this.getBaseWebUrl(); return `${baseUrl}/plan/${testPlanId}/`; } /** * Generate a permalink URL for a test run * @param testRunId - The ID of the test run * @returns The full URL to the test run */ generateTestRunUrl(testRunId) { const baseUrl = this.getBaseWebUrl(); return `${baseUrl}/run/${testRunId}/`; } /** * Generate a permalink URL for a test execution * @param testRunId - The ID of the test run * @param testCaseId - The ID of the test case * @returns The full URL to the test execution */ generateTestExecutionUrl(testRunId, testCaseId) { const baseUrl = this.getBaseWebUrl(); return `${baseUrl}/run/${testRunId}/#testcase-${testCaseId}`; } /** * Generate a permalink URL for a bug report * @param bugId - The ID of the bug * @returns The full URL to the bug report */ generateBugUrl(bugId) { const baseUrl = this.getBaseWebUrl(); return `${baseUrl}/bugs/${bugId}/`; } /** * Create a URL-friendly slug from a string * @param text - The text to convert to a slug * @param maxLength - Maximum length of the slug (default: 50) * @returns A URL-friendly slug */ createSlug(text, maxLength = 50) { return text .toLowerCase() .trim() // Replace spaces and special characters with hyphens .replace(/[^\w\s-]/g, '') .replace(/[\s_-]+/g, '-') // Remove leading/trailing hyphens .replace(/^-+|-+$/g, '') // Limit length // .substring(0, maxLength) // Remove trailing hyphen if truncated .replace(/-+$/, ''); } /** * Generate a short link for sharing * @param entityType - Type of entity ('case', 'plan', 'run', 'bug') * @param entityId - ID of the entity * @param slug - Optional slug for readability * @returns A shareable short URL format */ generateShortLink(entityType, entityId, slug) { const baseUrl = this.getBaseWebUrl(); return `${baseUrl}/${entityType}/${entityId}/${slug}`; } /** * Parse a Kiwi TCMS URL to extract entity information * @param url - The Kiwi TCMS URL to parse * @returns Object with entity type and ID, or null if not a valid URL */ parseKiwiUrl(url) { try { const urlObj = new URL(url); const pathMatch = urlObj.pathname.match(/\/(case|plan|run|bugs?)\/(\d+)(?:\/([^\/]+))?/); if (pathMatch) { const [, type, idStr, slug] = pathMatch; const normalizedType = type === 'bugs' ? 'bug' : type; return { type: normalizedType, id: parseInt(idStr, 10), ...(slug && { slug }) }; } return null; } catch { return null; } } /** * Get the base web URL from the XML-RPC URL * @private */ getBaseWebUrl() { // Extract base URL from client config const xmlRpcUrl = this.client.getConfig().baseUrl; // Remove '/xml-rpc/' suffix to get base web URL return xmlRpcUrl.replace(/\/xml-rpc\/?$/, ''); } /** * Inject permalink properties into an entity object * @param entityType - Type of entity ('case', 'plan', 'run', 'bug') * @param entity - The entity object to enhance * @param nameField - Field name to use for slug generation (e.g., 'summary', 'name') * @returns The entity with permalink properties added */ injectPermalinks(entityType, entity, nameField) { const name = entity[nameField]; const slug = this.createSlug(name || `${entityType}/${entity.id}`); let permalink; switch (entityType) { case 'case': permalink = this.generateTestCaseUrl(entity.id); break; case 'plan': permalink = this.generateTestPlanUrl(entity.id); break; case 'run': permalink = this.generateTestRunUrl(entity.id); break; case 'bug': permalink = this.generateBugUrl(entity.id); break; default: permalink = `${this.getBaseWebUrl()}/${entityType}/${entity.id}/`; } const shortLink = this.generateShortLink(entityType, entity.id, slug); return { ...entity, permalink, shortLink, slug }; } /** * Inject permalinks into an array of entities * @param entityType - Type of entity ('case', 'plan', 'run', 'bug') * @param entities - Array of entities to enhance * @param nameField - Field name to use for slug generation * @returns Array of entities with permalink properties added */ injectPermalinksArray(entityType, entities, nameField) { return entities.map(entity => this.injectPermalinks(entityType, entity, nameField)); } } exports.UrlAPI = UrlAPI; //# sourceMappingURL=utilities.js.map