UNPKG

@redpanda-data/docs-extensions-and-macros

Version:

Antora extensions and macros developed for Redpanda documentation.

164 lines (147 loc) 6.34 kB
'use strict' const fs = require('fs'); const path = require('path'); const Papa = require('papaparse'); const CSV_PATH = 'internal/plugins/info.csv' const GITHUB_OWNER = 'redpanda-data' const GITHUB_REPO = 'connect' const GITHUB_REF = 'main' module.exports.register = function ({ config }) { const logger = this.getLogger('redpanda-connect-info-extension'); async function loadOctokit() { const { Octokit } = await import('@octokit/rest'); if (!process.env.REDPANDA_GITHUB_TOKEN) return new Octokit() return new Octokit({ auth: process.env.REDPANDA_GITHUB_TOKEN, }); } this.once('contentClassified', async ({ contentCatalog }) => { const redpandaConnect = contentCatalog.getComponents().find(component => component.name === 'redpanda-connect'); const redpandaCloud = contentCatalog.getComponents().find(component => component.name === 'redpanda-cloud'); const preview = contentCatalog.getComponents().find(component => component.name === 'preview'); if (!redpandaConnect) return; const pages = contentCatalog.getPages(); try { // Fetch CSV data (either from local file or GitHub) const csvData = await fetchCSV(config.csvpath); const parsedData = Papa.parse(csvData, { header: true, skipEmptyLines: true }); const enrichedData = translateCsvData(parsedData, pages, logger); parsedData.data = enrichedData; if (redpandaConnect) { redpandaConnect.latest.asciidoc.attributes.csvData = parsedData; } if (redpandaCloud) { redpandaCloud.latest.asciidoc.attributes.csvData = parsedData; } // For previewing the data on our extensions site if (preview) { preview.latest.asciidoc.attributes.csvData = parsedData; } } catch (error) { logger.error('Error fetching or parsing CSV data:', error.message); logger.error(error.stack); } }); // Check for local CSV file first. If not found, fetch from GitHub async function fetchCSV(localCsvPath) { if (localCsvPath && fs.existsSync(localCsvPath)) { if (path.extname(localCsvPath).toLowerCase() !== '.csv') { throw new Error(`Invalid file type: ${localCsvPath}. Expected a CSV file.`); } logger.info(`Loading CSV data from local file: ${localCsvPath}`); return fs.readFileSync(localCsvPath, 'utf8'); } else { logger.info('Local CSV file not found. Fetching from GitHub...'); return await fetchCsvFromGitHub(); } } // Fetch CSV data from GitHub async function fetchCsvFromGitHub() { const octokit = await loadOctokit(); try { const { data: fileContent } = await octokit.rest.repos.getContent({ owner: GITHUB_OWNER, repo: GITHUB_REPO, path: CSV_PATH, ref: GITHUB_REF, }); return Buffer.from(fileContent.content, 'base64').toString('utf8'); } catch (error) { console.error('Error fetching Redpanda Connect catalog from GitHub:', error); return ''; } } /** * Translates the parsed CSV data into our expected format. * If "enterprise" is found in the `support` column, it is replaced with "certified" in the output. * * @param {object} parsedData - The CSV data parsed into an object. * @param {array} pages - The list of pages to map the URLs (used for enrichment with URLs). * @param {object} logger - The logger used for error handling. * * @returns {array} - The translated and enriched data. */ function translateCsvData(parsedData, pages, logger) { return parsedData.data.map(row => { // Create a new object with trimmed keys and values const trimmedRow = Object.fromEntries( Object.entries(row).map(([key, value]) => [key.trim(), value.trim()]) ); // Map fields from the trimmed row to the desired output const connector = trimmedRow.name; const type = trimmedRow.type; const commercial_name = trimmedRow.commercial_name; const available_connect_version = trimmedRow.version; const deprecated = trimmedRow.deprecated.toLowerCase() === 'y' ? 'y' : 'n'; const is_cloud_supported = trimmedRow.cloud.toLowerCase() === 'y' ? 'y' : 'n'; const cloud_ai = trimmedRow.cloud_with_gpu.toLowerCase() === 'y' ? 'y' : 'n'; // Handle enterprise to certified conversion and set enterprise license flag const originalSupport = trimmedRow.support.toLowerCase(); const support_level = originalSupport === 'enterprise' ? 'certified' : originalSupport; const is_licensed = originalSupport === 'enterprise' ? 'Yes' : 'No'; // Redpanda Connect and Cloud enrichment URLs let redpandaConnectUrl = ''; let redpandaCloudUrl = ''; // Look for both Redpanda Connect and Cloud URLs for (const file of pages) { const component = file.src.component; const filePath = file.path; if ( component === 'redpanda-connect' && filePath.endsWith(`/${connector}.adoc`) && filePath.includes(`pages/${type}s/`) ) { redpandaConnectUrl = file.pub.url; } // Only check for Redpanda Cloud URLs if cloud is supported if ( is_cloud_supported === 'y' && component === 'redpanda-cloud' && filePath.endsWith(`/${connector}.adoc`) && filePath.includes(`${type}s/`) ) { redpandaCloudUrl = file.pub.url; } } // Log a warning if neither URL was found (only warn for missing cloud if it should support cloud) // Ignore sql_driver connectors because they are not real connectors and only used as a utility for grouping sql driver types. if (!connector.includes('sql_driver') && !redpandaConnectUrl && (!redpandaCloudUrl && is_cloud_supported === 'y')) { logger.warn(`Docs missing for: ${connector} of type: ${type}`); } // Return the translated and enriched row return { connector, type, commercial_name, available_connect_version, support_level, // "enterprise" is replaced with "certified" deprecated, is_cloud_supported, cloud_ai, is_licensed, // "Yes" if the original support level was "enterprise" redpandaConnectUrl, redpandaCloudUrl, }; }); } }