const fs = require('fs'); const path = require('path'); const { existingTopics } = require('./original_topics.cjs'); const getApisContent = fs.readFileSync(path.join(__dirname, "Get Api's.txt"), 'utf8'); const postApisContent = fs.readFileSync(path.join(__dirname, "Post, put and delete Api's.txt"), 'utf8'); const endpoints = []; // Parse GET APIs let currentGet = null; const getLines = getApisContent.split('\n'); for (let line of getLines) { const trimmed = line.trim(); if (trimmed.startsWith('# ')) { currentGet = { method: 'GET', description: trimmed.substring(2), name: trimmed.substring(2) }; } else if (trimmed.startsWith('https://')) { if (currentGet) { currentGet.url = trimmed; endpoints.push(currentGet); currentGet = null; } } } // Better Parse POST/PUT/DELETE APIs const postLines = postApisContent.split('\n'); let i = 0; while (i < postLines.length) { let line = postLines[i].trim(); if (line.startsWith('POST ') || line.startsWith('PUT ') || line.startsWith('DELETE ')) { const parts = line.split(' '); const method = parts[0]; const name = parts.slice(1).join(' '); let url = ''; let body = null; let description = name; i++; while (i < postLines.length) { let l = postLines[i].trim(); if (l.startsWith('POST ') || l.startsWith('PUT ') || l.startsWith('DELETE ') || l.startsWith('1. ') || l.startsWith('2. ') || l.startsWith('3. ') || l.startsWith('4. ') || l.startsWith('5. ') || l.startsWith('6. ') || l.startsWith('💻') || l.startsWith('📱')) { break; // Next block starts } if (l.startsWith('URL: ')) { url = l.substring(5).trim(); } else if (l.startsWith('Payload: (Uses the same schema')) { description += ' ' + l; } else if (l === 'json') { // start capturing json let jsonStr = ''; i++; while (i < postLines.length) { let jl = postLines[i].trim(); if (jl.startsWith('POST ') || jl.startsWith('PUT ') || jl.startsWith('DELETE ') || jl.startsWith('1. ') || jl.startsWith('2. ') || jl.startsWith('3. ') || jl.startsWith('4. ') || jl.startsWith('5. ') || jl.startsWith('6. ') || jl.startsWith('💻') || jl.startsWith('📱')) { break; } jsonStr += postLines[i] + '\n'; i++; } let rawBody = jsonStr.trim(); try { body = JSON.parse(rawBody); } catch (e) { body = rawBody; // fallback to string } continue; } i++; } if (url) { const ep = { method, name, description, url }; if (body) { ep.body = body; } endpoints.push(ep); } } else { i++; } } // Second pass: Resolve "Uses the same schema as" endpoints.forEach(ep => { if (!ep.body && ep.description.includes('Uses the same schema as')) { const match = ep.description.match(/Uses the same schema as(.*?)\)/); if (match) { let refText = match[1].trim().toLowerCase(); // Try to find the referenced endpoint let refEp = endpoints.find(e => { if (!e.body) return false; let eName = e.name.toLowerCase(); // Remove 'web ' or 'mobile ' for looser matching refText = refText.replace('web ', '').replace('mobile ', ''); eName = eName.replace('web ', '').replace('mobile ', ''); return refText.includes(eName) || eName.includes(refText); }); if (refEp) { ep.body = refEp.body; } } } }); // Map to topics const topicMapping = { 'utils': ['utils', 'config', 'category'], 'users': ['user'], 'partners': ['partner', 'rider'], 'tenants': ['tenant', 'location'], 'customers': ['customer'], 'deliveries': ['deliver'], 'orders': ['order'], 'products': ['product', 'catalog', 'stock'], 'invoice': ['invoice'], 'payments': ['payment'] }; const mapToTopic = (url) => { const urlLower = url.toLowerCase(); for (const [topicId, keywords] of Object.entries(topicMapping)) { if (urlLower.includes('/' + topicId + '/')) return topicId; for (const kw of keywords) { if (urlLower.includes('/' + kw)) return topicId; } } return 'utils'; }; const restTopicsMap = { utils: { id: 'utils', name: 'Utils', description: 'Shared lookup endpoints roles, locations, configs, app types, pricing.', endpoints: [] }, users: { id: 'users', name: 'Users', description: 'Manage users and roles across the Xpress platform.', endpoints: [] }, partners: { id: 'partners', name: 'Partners', description: 'Partners, riders, locations, shifts, and rider pricing.', endpoints: [] }, tenants: { id: 'tenants', name: 'Tenants', description: 'Tenant accounts info, locations, customers, orders, pricing, summary.', endpoints: [] }, customers: { id: 'customers', name: 'Customers', description: 'Customer accounts, lookups, and search.', endpoints: [] }, deliveries: { id: 'deliveries', name: 'Deliveries', description: 'Delivery records, queues, and rider-delivery joins.', endpoints: [] }, orders: { id: 'orders', name: 'Orders', description: 'Order records, details, and aggregate summaries.', endpoints: [] }, products: { id: 'products', name: 'Products', description: 'Product catalog, categories, and subcategories.', endpoints: [] }, invoice: { id: 'invoice', name: 'Invoice', description: 'Invoice insights and billing analytics.', endpoints: [] }, payments: { id: 'payments', name: 'Payments', description: 'Payment requests and settlements.', endpoints: [] } }; endpoints.forEach(ep => { let parsedUrl; try { parsedUrl = new URL(ep.url); } catch (e) { return; } const fullPath = parsedUrl.pathname + parsedUrl.search; const topicId = mapToTopic(fullPath); if (restTopicsMap[topicId]) { const newEp = { name: ep.name, method: ep.method, url: fullPath, description: ep.description }; if (ep.body) { newEp.body = ep.body; } restTopicsMap[topicId].endpoints.push(newEp); } }); const restTopics = Object.values(restTopicsMap); const out = `export const LEGACY_BASE_URL = 'https://api.workolik.com'; export const REST_BASE_URL = 'https://fiesta.nearle.app'; export const legacyTopics = ${JSON.stringify(existingTopics, null, 2)}; export const restTopics = ${JSON.stringify(restTopics, null, 2)}; `; fs.writeFileSync(path.join(__dirname, 'src', 'data', 'topics.js'), out, 'utf8'); console.log('Successfully updated topics.js with ' + endpoints.length + ' parsed endpoints (fixed payload parsing).');