UNPKG

@bitecraft/yaak2postman

Version:

CLI tool to convert YAAK files to Postman

239 lines (238 loc) 8.31 kB
import path from 'node:path'; import { readJsonFile, saveJsonFile } from '../../utils/file.js'; export class PostmanConverter { constructor(yaakFilePath, exportType = 'collection') { this.yaakFilePath = yaakFilePath; this.exportType = exportType; this.yaakData = null; this.outputDir = null; } initialize() { try { const fileContent = readJsonFile(this.yaakFilePath); this.yaakData = fileContent; this.outputDir = path.dirname(this.yaakFilePath); if (!this.yaakData?.resources?.workspaces) { throw new Error('Invalid Yaak file: workspaces structure not found'); } return true; } catch (error) { console.error('Error initializing converter:', error instanceof Error ? error.message : 'Unknown error'); return false; } } convert() { if (!this.initialize()) { throw new Error('Failed to initialize converter'); } if (!this.yaakData) { throw new Error('Yaak data not initialized'); } try { const results = []; for (const workspace of this.yaakData.resources.workspaces) { const result = this.processWorkspace(workspace); if (Array.isArray(result)) { results.push(...result); } else { results.push(result); } } return results; } catch (error) { throw new Error(`Error during conversion: ${error instanceof Error ? error.message : 'Unknown error'}`); } } processWorkspace(workspace) { if (this.exportType === PostmanConverter.ExportType.COLLECTION) { return this.exportWorkspaceCollection(workspace); } return this.exportWorkspaceEnvironments(workspace); } exportWorkspaceCollection(workspace) { if (!this.yaakData || !this.outputDir) { throw new Error('Yaak data not initialized'); } const folderMap = this.createFolderMapForWorkspace(workspace.id); const collection = this.createBaseCollection(workspace); const rootFolders = this.organizeFolderHierarchy(folderMap); const workspaceRequests = this.yaakData.resources.httpRequests .filter(req => req.workspaceId === workspace.id); for (const request of workspaceRequests) { const postmanRequest = this.convertRequest(request); const folder = request.folderId ? folderMap.get(request.folderId) : null; if (folder) { folder.item.push(postmanRequest); } else { collection.item.push(postmanRequest); } } collection.item.push(...rootFolders); const outputPath = path.join(this.outputDir, `${workspace.name.toLowerCase()}_collection.json`); saveJsonFile(outputPath, collection); return { success: true, type: 'collection', workspaceName: workspace.name, outputPath }; } createFolderMapForWorkspace(workspaceId) { if (!this.yaakData) { throw new Error('Yaak data not initialized'); } const folderMap = new Map(); const workspaceFolders = this.yaakData.resources.folders .filter(folder => folder.workspaceId === workspaceId); for (const folder of workspaceFolders) { folderMap.set(folder.id, { name: folder.name, item: [], folderId: folder.folderId, id: folder.id }); } return folderMap; } exportWorkspaceEnvironments(workspace) { if (!this.yaakData || !this.outputDir) { throw new Error('Yaak data not initialized'); } const outputDir = this.outputDir; const workspaceEnvironments = this.yaakData.resources.environments .filter(env => env.workspaceId === workspace.id); return workspaceEnvironments.map(env => { const postmanEnv = this.convertEnvironment(env); const outputPath = path.join(outputDir, `${workspace.name.toLowerCase()}_environment_${env.name.toLowerCase()}.json`); saveJsonFile(outputPath, postmanEnv); return { success: true, type: 'environment', workspaceName: workspace.name, environmentName: env.name, outputPath }; }); } createBaseCollection(workspace) { return { info: { name: workspace.name, description: workspace.description || '', schema: "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, item: [], variable: [] }; } organizeFolderHierarchy(folderMap) { const rootFolders = []; for (const folder of folderMap.values()) { if (!folder.folderId) { rootFolders.push(folder); } else { const parentFolder = folderMap.get(folder.folderId); if (parentFolder) { parentFolder.item.push(folder); } } } return rootFolders; } convertRequest(request) { return { name: request.name, request: { method: request.method, header: this.convertHeaders(request.headers), url: this.convertUrl(request.url, request.urlParameters), description: '', ...(request.body?.text && { body: this.convertBody(request.body, request.bodyType) }) }, response: [] }; } convertHeaders(headers = []) { return headers.map(h => ({ key: h.name, value: h.value, type: "text", enabled: h.enabled })); } convertUrl(url, urlParameters) { const baseUrl = url.replace(/\$\{\[ base_url \]\}/g, '{{base_url}}'); return { raw: baseUrl, host: ["{{base_url}}"], path: this.convertUrlPath(baseUrl), variable: this.convertPathVariables(url, urlParameters), query: this.convertQueryParameters(urlParameters) }; } convertUrlPath(url) { return url .replace(/\$\{\[ base_url \]\}/g, '') .split('/') .filter(Boolean); } convertPathVariables(url, urlParameters) { const pathParamMatches = url.match(/:[a-zA-Z_][a-zA-Z0-9_]*/g) || []; return pathParamMatches.map(param => { const paramName = param.substring(1); const paramValue = urlParameters?.find(p => p.name === paramName)?.value || ''; return { id: paramName, key: paramName, value: paramValue, type: "string", description: '' }; }); } convertQueryParameters(urlParameters) { if (!urlParameters) return []; return urlParameters .filter(p => p.name && !p.name.startsWith(':')) .map(p => ({ key: p.name, value: p.value || '', disabled: !p.enabled })); } convertBody(body, bodyType) { return { mode: "raw", raw: body.text, options: { raw: { language: bodyType === 'application/json' ? 'json' : 'text' } } }; } convertEnvironment(env) { return { name: env.name, values: env.variables .filter(v => v.name && v.value) .map(v => ({ key: v.name, value: v.value, type: "default", enabled: v.enabled })), _postman_variable_scope: "environment" }; } } PostmanConverter.ExportType = { ENV: 'env', COLLECTION: 'collection' };