From 2935475b1175cdf0ff07c3b75f432d837224f846 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Sat, 16 Nov 2024 14:44:34 +0530 Subject: [PATCH 1/2] format scripts --- scripts/adopters/index.js | 7 +- scripts/build-docs.js | 113 ++++--- scripts/build-meetings.js | 10 +- scripts/build-newsroom-videos.js | 79 ++--- scripts/build-pages.js | 2 +- scripts/build-post-list.js | 214 ++++++++------ scripts/build-rss.js | 93 +++--- scripts/build-tools.js | 25 +- scripts/casestudies/index.js | 29 +- scripts/compose.js | 57 ++-- scripts/dashboard/build-dashboard.js | 87 ++++-- scripts/finance/index.js | 57 ++-- scripts/index.js | 6 +- scripts/markdown/check-markdown.js | 200 +++++++------ scripts/tools/categorylist.js | 139 +++++---- scripts/tools/combine-tools.js | 258 ++++++++-------- scripts/tools/extract-tools-github.js | 6 +- scripts/tools/tags-color.js | 346 +++++++++++----------- scripts/tools/tools-object.js | 104 ++++--- scripts/tools/tools-schema.json | 411 +++++++++++++------------- scripts/utils.js | 36 +-- scripts/utils/readAndWriteJson.js | 48 +-- 22 files changed, 1277 insertions(+), 1050 deletions(-) diff --git a/scripts/adopters/index.js b/scripts/adopters/index.js index 6a11697ad68f..ef6643802d62 100644 --- a/scripts/adopters/index.js +++ b/scripts/adopters/index.js @@ -1,6 +1,9 @@ const { resolve } = require('path'); -const writeJSON = require('../utils/readAndWriteJson.js') +const writeJSON = require('../utils/readAndWriteJson.js'); module.exports = async function buildAdoptersList() { - writeJSON('config/adopters.yml',resolve(__dirname, '../../config', 'adopters.json')); + writeJSON( + 'config/adopters.yml', + resolve(__dirname, '../../config', 'adopters.json'), + ); }; diff --git a/scripts/build-docs.js b/scripts/build-docs.js index ac47b6751cee..e1aff2f99cd1 100644 --- a/scripts/build-docs.js +++ b/scripts/build-docs.js @@ -1,26 +1,40 @@ -const sortBy = require('lodash/sortBy') +const sortBy = require('lodash/sortBy'); function buildNavTree(navItems) { try { const tree = { - 'welcome': { - item: { title: 'Welcome', weight: 0, isRootSection: true, isSection: true, rootSectionId: 'welcome', sectionWeight: 0, slug: '/docs' }, - children: {} - } - } + welcome: { + item: { + title: 'Welcome', + weight: 0, + isRootSection: true, + isSection: true, + rootSectionId: 'welcome', + sectionWeight: 0, + slug: '/docs', + }, + children: {}, + }, + }; //first we make sure that list of items lists main section items and then sub sections, documents last - const sortedItems = sortBy(navItems, ['isRootSection', 'weight', 'isSection']); + const sortedItems = sortBy(navItems, [ + 'isRootSection', + 'weight', + 'isSection', + ]); - sortedItems.forEach(item => { + sortedItems.forEach((item) => { //identify main sections if (item.isRootSection) { - tree[item.rootSectionId] = { item, children: {} } + tree[item.rootSectionId] = { item, children: {} }; } //identify subsections if (item.parent) { if (!tree[item.parent]) { - throw new Error(`Parent section ${item.parent} not found for item ${item.title}`); + throw new Error( + `Parent section ${item.parent} not found for item ${item.title}`, + ); } tree[item.parent].children[item.sectionId] = { item, children: [] }; } @@ -29,7 +43,10 @@ function buildNavTree(navItems) { if (item.sectionId) { let section = tree[item.rootSectionId]?.children[item.sectionId]; if (!section) { - tree[item.rootSectionId].children[item.sectionId] = { item, children: [] }; + tree[item.rootSectionId].children[item.sectionId] = { + item, + children: [], + }; } tree[item.rootSectionId].children[item.sectionId].children.push(item); } else { @@ -62,40 +79,39 @@ function buildNavTree(navItems) { // point in slug for specification subgroup to the latest specification version if (rootKey === 'reference' && key === 'specification') { - allChildren[key].item.href = allChildren[key].children.find(c => c.isPrerelease === undefined).slug; + allChildren[key].item.href = allChildren[key].children.find( + (c) => c.isPrerelease === undefined, + ).slug; } } } } return tree; - } catch (err) { throw new Error(`Failed to build navigation tree: ${err.message}`); } } -// A recursion function, works on the logic of Depth First Search to traverse all the root and child posts of the +// A recursion function, works on the logic of Depth First Search to traverse all the root and child posts of the // DocTree to get sequential order of the Doc Posts const convertDocPosts = (docObject) => { try { - let docsArray = [] + let docsArray = []; // certain entries in the DocPosts are either a parent to many posts or itself a post. - docsArray.push(docObject?.item || docObject) + docsArray.push(docObject?.item || docObject); if (docObject.children) { - let children = docObject.children + let children = docObject.children; Object.keys(children).forEach((child) => { - let docChildArray = convertDocPosts(children[child]) - docsArray = [...docsArray, ...docChildArray] - }) + let docChildArray = convertDocPosts(children[child]); + docsArray = [...docsArray, ...docChildArray]; + }); } - return docsArray - } - catch (err) { + return docsArray; + } catch (err) { throw new Error('Error in convertDocPosts:', err); } -} - +}; function addDocButtons(docPosts, treePosts) { let structuredPosts = []; @@ -115,56 +131,62 @@ function addDocButtons(docPosts, treePosts) { }); // Appending the content of welcome page of Docs from the posts.json - structuredPosts[0] = docPosts.filter(p => p.slug === '/docs')[0]; + structuredPosts[0] = docPosts.filter((p) => p.slug === '/docs')[0]; // Traversing the structuredPosts in order to add `nextPage` and `prevPage` details for each page let countDocPages = structuredPosts.length; structuredPosts = structuredPosts.map((post, index) => { - // post item specifying the root Section or sub-section in the docs are excluded as - // they doesn't comprise any Doc Page or content to be shown in website. + // post item specifying the root Section or sub-section in the docs are excluded as + // they doesn't comprise any Doc Page or content to be shown in website. if (post?.isRootSection || post?.isSection || index == 0) { - if (post?.isRootSection || index == 0) - rootSections.push(post.title) - return post + if (post?.isRootSection || index == 0) rootSections.push(post.title); + return post; } - let nextPage = {}, prevPage = {} + let nextPage = {}, + prevPage = {}; let docPost = post; // checks whether the next page for the current docPost item exists or not if (index + 1 < countDocPages) { // checks whether the next item inside structuredPosts is a rootElement or a sectionElement // if yes, it goes again to a next to next item in structuredPosts to link the nextPage - if (!structuredPosts[index + 1].isRootElement && !structuredPosts[index + 1].isSection) { + if ( + !structuredPosts[index + 1].isRootElement && + !structuredPosts[index + 1].isSection + ) { nextPage = { title: structuredPosts[index + 1].title, - href: structuredPosts[index + 1].slug - } + href: structuredPosts[index + 1].slug, + }; } else { nextPage = { title: `${structuredPosts[index + 1].title} - ${structuredPosts[index + 2].title}`, - href: structuredPosts[index + 2].slug - } + href: structuredPosts[index + 2].slug, + }; } - docPost = { ...docPost, nextPage } + docPost = { ...docPost, nextPage }; } // checks whether the previous page for the current docPost item exists or not if (index > 0) { // checks whether the previous item inside structuredPosts is a rootElement or a sectionElement // if yes, it goes again to a next previous item in structuredPosts to link the prevPage - if (!structuredPosts[index - 1]?.isRootElement && !structuredPosts[index - 1]?.isSection) { + if ( + !structuredPosts[index - 1]?.isRootElement && + !structuredPosts[index - 1]?.isSection + ) { prevPage = { title: structuredPosts[index - 1].title, - href: structuredPosts[index - 1].slug - } - docPost = { ...docPost, prevPage } + href: structuredPosts[index - 1].slug, + }; + docPost = { ...docPost, prevPage }; } else { // additonal check for the first page of Docs so that it doesn't give any Segementation fault if (index - 2 >= 0) { prevPage = { title: `${structuredPosts[index - 1]?.isRootSection ? rootSections[rootSections.length - 2] : rootSections[rootSections.length - 1]} - ${structuredPosts[index - 2].title}`, - href: structuredPosts[index - 2].slug + href: structuredPosts[index - 2].slug, }; docPost = { ...docPost, prevPage }; } @@ -172,11 +194,10 @@ function addDocButtons(docPosts, treePosts) { } return docPost; }); - } catch (err) { - throw new Error("An error occurred while adding doc buttons:", err); + throw new Error('An error occurred while adding doc buttons:', err); } return structuredPosts; } -module.exports = { buildNavTree, addDocButtons, convertDocPosts } \ No newline at end of file +module.exports = { buildNavTree, addDocButtons, convertDocPosts }; diff --git a/scripts/build-meetings.js b/scripts/build-meetings.js index ee95803d9d44..cc56c0d026b8 100644 --- a/scripts/build-meetings.js +++ b/scripts/build-meetings.js @@ -9,11 +9,12 @@ async function buildMeetings(writePath) { try { auth = new google.auth.GoogleAuth({ scopes: ['https://www.googleapis.com/auth/calendar'], - credentials: process.env.CALENDAR_SERVICE_ACCOUNT ? JSON.parse(process.env.CALENDAR_SERVICE_ACCOUNT) : undefined, + credentials: process.env.CALENDAR_SERVICE_ACCOUNT + ? JSON.parse(process.env.CALENDAR_SERVICE_ACCOUNT) + : undefined, }); calendar = google.calendar({ version: 'v3', auth }); - } catch (err) { throw new Error(`Authentication failed: ${err.message}`); } @@ -24,10 +25,10 @@ async function buildMeetings(writePath) { //cron job runs this always on midnight const currentTime = new Date(Date.now()).toISOString(); const timeMin = new Date( - Date.parse(currentTime) - 100 * 24 * 60 * 60 * 1000 + Date.parse(currentTime) - 100 * 24 * 60 * 60 * 1000, ).toISOString(); const timeMax = new Date( - Date.parse(currentTime) + 30 * 24 * 60 * 60 * 1000 + Date.parse(currentTime) + 30 * 24 * 60 * 60 * 1000, ).toISOString(); const eventsList = await calendar.events.list({ @@ -53,7 +54,6 @@ async function buildMeetings(writePath) { console.log('The following events got fetched', eventsForHuman); writeFileSync(writePath, eventsForHuman); - } catch (err) { throw new Error(`Failed to fetch or process events: ${err.message}`); } diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index 383927765d36..496eba2de769 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -3,49 +3,52 @@ const { resolve } = require('path'); const fetch = require('node-fetch-2'); async function buildNewsroomVideos(writePath) { - try { - const response = await fetch('https://youtube.googleapis.com/youtube/v3/search?' + new URLSearchParams({ - key: process.env.YOUTUBE_TOKEN, - part: 'snippet', - channelId: 'UCIz9zGwDLbrYQcDKVXdOstQ', - eventType: 'completed', - type: 'video', - order: 'Date', - maxResults: 5, - })); - - if (!response.ok) { - throw new Error(`HTTP error! with status code: ${response.status}`); - } - - const data = await response.json(); - console.log(data); - - if (!data.items || !Array.isArray(data.items)) { - throw new Error('Invalid data structure received from YouTube API'); - } - - const videoDataItems = data.items.map((video) => ({ - image_url: video.snippet.thumbnails.high.url, - title: video.snippet.title, - description: video.snippet.description, - videoId: video.id.videoId, - })); - - const videoData = JSON.stringify(videoDataItems, null, ' '); - console.log('The following are the Newsroom Youtube videos: ', videoData); - - writeFileSync(writePath, videoData); - - return videoData; - } catch (err) { - throw new Error(`Failed to build newsroom videos: ${err.message}`); + try { + const response = await fetch( + 'https://youtube.googleapis.com/youtube/v3/search?' + + new URLSearchParams({ + key: process.env.YOUTUBE_TOKEN, + part: 'snippet', + channelId: 'UCIz9zGwDLbrYQcDKVXdOstQ', + eventType: 'completed', + type: 'video', + order: 'Date', + maxResults: 5, + }), + ); + + if (!response.ok) { + throw new Error(`HTTP error! with status code: ${response.status}`); } + + const data = await response.json(); + console.log(data); + + if (!data.items || !Array.isArray(data.items)) { + throw new Error('Invalid data structure received from YouTube API'); + } + + const videoDataItems = data.items.map((video) => ({ + image_url: video.snippet.thumbnails.high.url, + title: video.snippet.title, + description: video.snippet.description, + videoId: video.id.videoId, + })); + + const videoData = JSON.stringify(videoDataItems, null, ' '); + console.log('The following are the Newsroom Youtube videos: ', videoData); + + writeFileSync(writePath, videoData); + + return videoData; + } catch (err) { + throw new Error(`Failed to build newsroom videos: ${err.message}`); + } } /* istanbul ignore next */ if (require.main === module) { - buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')) + buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')); } module.exports = { buildNewsroomVideos }; diff --git a/scripts/build-pages.js b/scripts/build-pages.js index 48b3553e96b2..287d44f046b0 100644 --- a/scripts/build-pages.js +++ b/scripts/build-pages.js @@ -57,4 +57,4 @@ function copyAndRenameFiles(srcDir, targetDir) { copyAndRenameFiles(SRC_DIR, TARGET_DIR); -module.exports = {copyAndRenameFiles,capitalizeJsxTags} \ No newline at end of file +module.exports = { copyAndRenameFiles, capitalizeJsxTags }; diff --git a/scripts/build-post-list.js b/scripts/build-post-list.js index 288d7dc0c54e..dc249c6e2a43 100644 --- a/scripts/build-post-list.js +++ b/scripts/build-post-list.js @@ -1,161 +1,201 @@ -const { readdirSync, statSync, existsSync, readFileSync, writeFileSync } = require('fs') -const { resolve, basename } = require('path') -const frontMatter = require('gray-matter') -const toc = require('markdown-toc') -const { slugify } = require('markdown-toc/lib/utils') -const readingTime = require('reading-time') -const { markdownToTxt } = require('markdown-to-txt') -const { buildNavTree, addDocButtons } = require('./build-docs') +const { + readdirSync, + statSync, + existsSync, + readFileSync, + writeFileSync, +} = require('fs'); +const { resolve, basename } = require('path'); +const frontMatter = require('gray-matter'); +const toc = require('markdown-toc'); +const { slugify } = require('markdown-toc/lib/utils'); +const readingTime = require('reading-time'); +const { markdownToTxt } = require('markdown-to-txt'); +const { buildNavTree, addDocButtons } = require('./build-docs'); -let specWeight = 100 +let specWeight = 100; const result = { docs: [], blog: [], about: [], - docsTree: {} -} -const releaseNotes = [] -const basePath = 'pages' + docsTree: {}, +}; +const releaseNotes = []; +const basePath = 'pages'; const postDirectories = [ // order of these directories is important, as the blog should come before docs, to create a list of available release notes, which will later be used to release-note-link for spec docs [`${basePath}/blog`, '/blog'], [`${basePath}/docs`, '/docs'], - [`${basePath}/about`, '/about'] + [`${basePath}/about`, '/about'], ]; const addItem = (details) => { - if(details.slug.startsWith('/docs')) - result["docs"].push(details) - else if(details.slug.startsWith('/blog')) - result["blog"].push(details) - else if(details.slug.startsWith('/about')) - result["about"].push(details) - else {} -} + if (details.slug.startsWith('/docs')) result['docs'].push(details); + else if (details.slug.startsWith('/blog')) result['blog'].push(details); + else if (details.slug.startsWith('/about')) result['about'].push(details); + else { + } +}; module.exports = async function buildPostList() { - walkDirectories(postDirectories, result) - const treePosts = buildNavTree(result["docs"].filter((p) => p.slug.startsWith('/docs/'))) - result["docsTree"] = treePosts - result["docs"] = addDocButtons(result["docs"], treePosts) + walkDirectories(postDirectories, result); + const treePosts = buildNavTree( + result['docs'].filter((p) => p.slug.startsWith('/docs/')), + ); + result['docsTree'] = treePosts; + result['docs'] = addDocButtons(result['docs'], treePosts); if (process.env.NODE_ENV === 'production') { // console.log(inspect(result, { depth: null, colors: true })) } - writeFileSync(resolve(__dirname, '..', 'config', 'posts.json'), JSON.stringify(result, null, ' ')) -} + writeFileSync( + resolve(__dirname, '..', 'config', 'posts.json'), + JSON.stringify(result, null, ' '), + ); +}; -function walkDirectories(directories, result, sectionWeight = 0, sectionTitle, sectionId, rootSectionId) { +function walkDirectories( + directories, + result, + sectionWeight = 0, + sectionTitle, + sectionId, + rootSectionId, +) { for (let dir of directories) { - let directory = dir[0] - let sectionSlug = dir[1] || '' + let directory = dir[0]; + let sectionSlug = dir[1] || ''; let files = readdirSync(directory); for (let file of files) { - let details - const fileName = [directory, file].join('/') - const fileNameWithSection = [fileName, '_section.mdx'].join('/') - const slug = fileName.replace(new RegExp(`^${basePath}`), '') + let details; + const fileName = [directory, file].join('/'); + const fileNameWithSection = [fileName, '_section.mdx'].join('/'); + const slug = fileName.replace(new RegExp(`^${basePath}`), ''); const slugElements = slug.split('/'); if (isDirectory(fileName)) { if (existsSync(fileNameWithSection)) { // Passing a second argument to frontMatter disables cache. See https://github.com/asyncapi/website/issues/1057 - details = frontMatter(readFileSync(fileNameWithSection, 'utf-8'), {}).data - details.title = details.title || capitalize(basename(fileName)) + details = frontMatter( + readFileSync(fileNameWithSection, 'utf-8'), + {}, + ).data; + details.title = details.title || capitalize(basename(fileName)); } else { details = { title: capitalize(basename(fileName)), - } + }; } - details.isSection = true + details.isSection = true; if (slugElements.length > 3) { - details.parent = slugElements[slugElements.length - 2] - details.sectionId = slugElements[slugElements.length - 1] + details.parent = slugElements[slugElements.length - 2]; + details.sectionId = slugElements[slugElements.length - 1]; } if (!details.parent) { - details.isRootSection = true - details.rootSectionId = slugElements[slugElements.length - 1] + details.isRootSection = true; + details.rootSectionId = slugElements[slugElements.length - 1]; } - details.sectionWeight = sectionWeight - details.slug = slug - addItem(details) - const rootId = details.parent || details.rootSectionId - walkDirectories([[fileName, slug]], result, details.weight, details.title, details.sectionId, rootId) + details.sectionWeight = sectionWeight; + details.slug = slug; + addItem(details); + const rootId = details.parent || details.rootSectionId; + walkDirectories( + [[fileName, slug]], + result, + details.weight, + details.title, + details.sectionId, + rootId, + ); } else if (file.endsWith('.mdx') && !fileName.endsWith('/_section.mdx')) { - const fileContent = readFileSync(fileName, 'utf-8') + const fileContent = readFileSync(fileName, 'utf-8'); // Passing a second argument to frontMatter disables cache. See https://github.com/asyncapi/website/issues/1057 - const { data, content } = frontMatter(fileContent, {}) - details = data - details.toc = toc(content, { slugify: slugifyToC }).json - details.readingTime = Math.ceil(readingTime(content).minutes) - details.excerpt = details.excerpt || markdownToTxt(content).substr(0, 200) - details.sectionSlug = sectionSlug || slug.replace(/\.mdx$/, '') - details.sectionWeight = sectionWeight - details.sectionTitle = sectionTitle - details.sectionId = sectionId - details.rootSectionId = rootSectionId - details.id = fileName - details.isIndex = fileName.endsWith('/index.mdx') - details.slug = details.isIndex ? sectionSlug : slug.replace(/\.mdx$/, '') - if(details.slug.includes('/reference/specification/') && !details.title) { - const fileBaseName = basename(data.slug) // ex. v2.0.0 | v2.1.0-next-spec.1 - const fileName = fileBaseName.split('-')[0] // v2.0.0 | v2.1.0 - details.weight = specWeight-- + const { data, content } = frontMatter(fileContent, {}); + details = data; + details.toc = toc(content, { slugify: slugifyToC }).json; + details.readingTime = Math.ceil(readingTime(content).minutes); + details.excerpt = + details.excerpt || markdownToTxt(content).substr(0, 200); + details.sectionSlug = sectionSlug || slug.replace(/\.mdx$/, ''); + details.sectionWeight = sectionWeight; + details.sectionTitle = sectionTitle; + details.sectionId = sectionId; + details.rootSectionId = rootSectionId; + details.id = fileName; + details.isIndex = fileName.endsWith('/index.mdx'); + details.slug = details.isIndex + ? sectionSlug + : slug.replace(/\.mdx$/, ''); + if ( + details.slug.includes('/reference/specification/') && + !details.title + ) { + const fileBaseName = basename(data.slug); // ex. v2.0.0 | v2.1.0-next-spec.1 + const fileName = fileBaseName.split('-')[0]; // v2.0.0 | v2.1.0 + details.weight = specWeight--; if (fileName.startsWith('v')) { - details.title = capitalize(fileName.slice(1)) + details.title = capitalize(fileName.slice(1)); } else { - details.title = capitalize(fileName) + details.title = capitalize(fileName); } - if(releaseNotes.includes(details.title)){ - details.releaseNoteLink = `/blog/release-notes-${details.title}` + if (releaseNotes.includes(details.title)) { + details.releaseNoteLink = `/blog/release-notes-${details.title}`; } - if (fileBaseName.includes('next-spec') || fileBaseName.includes('next-major-spec')) { - details.isPrerelease = true + if ( + fileBaseName.includes('next-spec') || + fileBaseName.includes('next-major-spec') + ) { + details.isPrerelease = true; // this need to be separate because the `-` in "Pre-release" will get removed by `capitalize()` function - details.title += " (Pre-release)" + details.title += ' (Pre-release)'; } if (fileBaseName.includes('explorer')) { - details.title += " - Explorer" + details.title += ' - Explorer'; } } // To create a list of available ReleaseNotes list, which will be used to add details.releaseNoteLink attribute. - if(file.startsWith("release-notes") && dir[1] === "/blog"){ - const fileName_without_extension = file.slice(0,-4) + if (file.startsWith('release-notes') && dir[1] === '/blog') { + const fileName_without_extension = file.slice(0, -4); // removes the file extension. For example, release-notes-2.1.0.md -> release-notes-2.1.0 - const version = fileName_without_extension.slice(fileName_without_extension.lastIndexOf("-")+1) + const version = fileName_without_extension.slice( + fileName_without_extension.lastIndexOf('-') + 1, + ); // gets the version from the name of the releaseNote .md file (from /blog). For example, version = 2.1.0 if fileName_without_extension = release-notes-2.1.0 - releaseNotes.push(version) + releaseNotes.push(version); // releaseNotes is the list of all available releaseNotes } - addItem(details) + addItem(details); } } } } function slugifyToC(str) { - let slug + let slug; // Try to match heading ids like {# myHeadingId} - const headingIdMatch = str.match(/[\s]?\{\#([\w\d\-_]+)\}/) + const headingIdMatch = str.match(/[\s]?\{\#([\w\d\-_]+)\}/); if (headingIdMatch && headingIdMatch.length >= 2) { - slug = headingIdMatch[1] + slug = headingIdMatch[1]; } else { // Try to match heading ids like {} - const anchorTagMatch = str.match(/[\s]*= 2) slug = anchorTagMatch[1] + const anchorTagMatch = str.match(/[\s]*= 2) slug = anchorTagMatch[1]; } - return slug || slugify(str, { firsth1: true, maxdepth: 6 }) + return slug || slugify(str, { firsth1: true, maxdepth: 6 }); } function isDirectory(dir) { - return statSync(dir).isDirectory() + return statSync(dir).isDirectory(); } function capitalize(text) { - return text.split(/[\s\-]/g).map(word => `${word[0].toUpperCase()}${word.substr(1)}`).join(' ') + return text + .split(/[\s\-]/g) + .map((word) => `${word[0].toUpperCase()}${word.substr(1)}`) + .join(' '); } diff --git a/scripts/build-rss.js b/scripts/build-rss.js index 673da1398fe0..46c668119c6a 100644 --- a/scripts/build-rss.js +++ b/scripts/build-rss.js @@ -1,26 +1,25 @@ -const fs = require('fs').promises -const json2xml = require('jgexml/json2xml') +const fs = require('fs').promises; +const json2xml = require('jgexml/json2xml'); function getAllPosts() { return require('../config/posts.json'); } function clean(s) { - s = s.split('<span>').join('') - s = s.split('&').join('&') - s = s.split(''').join("'") - s = s.split('<').join('<') - s = s.split('>').join('>') - s = s.split('"').join('"') - return s + s = s.split('<span>').join(''); + s = s.split('&').join('&'); + s = s.split(''').join("'"); + s = s.split('<').join('<'); + s = s.split('>').join('>'); + s = s.split('"').join('"'); + return s; } module.exports = async function rssFeed(type, title, desc, outputPath) { try { - - let posts = getAllPosts()[`${type}`] - const missingDatePosts = posts.filter(post => !post.date); - posts = posts.filter(post => post.date); + let posts = getAllPosts()[`${type}`]; + const missingDatePosts = posts.filter((post) => !post.date); + posts = posts.filter((post) => post.date); posts.sort((i1, i2) => { const i1Date = new Date(i1.date); const i2Date = new Date(i2.date); @@ -30,37 +29,41 @@ module.exports = async function rssFeed(type, title, desc, outputPath) { }); if (missingDatePosts.length > 0) { - throw new Error(`Missing date in posts: ${missingDatePosts.map(p => p.title || p.slug).join(', ')}`); + throw new Error( + `Missing date in posts: ${missingDatePosts.map((p) => p.title || p.slug).join(', ')}`, + ); } - const base = 'https://www.asyncapi.com' + const base = 'https://www.asyncapi.com'; const tracking = '?utm_source=rss'; - const feed = {} - const rss = {} - rss['@version'] = '2.0' - rss["@xmlns:atom"] = 'http://www.w3.org/2005/Atom' - rss.channel = {} - rss.channel.title = title - rss.channel.link = `${base}/${outputPath}` - rss.channel["atom:link"] = {} - rss.channel["atom:link"]["@rel"] = 'self' - rss.channel["atom:link"]["@href"] = rss.channel.link - rss.channel["atom:link"]["@type"] = 'application/rss+xml' - rss.channel.description = desc + const feed = {}; + const rss = {}; + rss['@version'] = '2.0'; + rss['@xmlns:atom'] = 'http://www.w3.org/2005/Atom'; + rss.channel = {}; + rss.channel.title = title; + rss.channel.link = `${base}/${outputPath}`; + rss.channel['atom:link'] = {}; + rss.channel['atom:link']['@rel'] = 'self'; + rss.channel['atom:link']['@href'] = rss.channel.link; + rss.channel['atom:link']['@type'] = 'application/rss+xml'; + rss.channel.description = desc; rss.channel.language = 'en-gb'; rss.channel.copyright = 'Made with :love: by the AsyncAPI Initiative.'; - rss.channel.webMaster = 'info@asyncapi.io (AsyncAPI Initiative)' - rss.channel.pubDate = new Date().toUTCString() - rss.channel.generator = 'next.js' - rss.channel.item = [] + rss.channel.webMaster = 'info@asyncapi.io (AsyncAPI Initiative)'; + rss.channel.pubDate = new Date().toUTCString(); + rss.channel.generator = 'next.js'; + rss.channel.item = []; - const invalidPosts = posts.filter(post => - !post.title || !post.slug || !post.excerpt || !post.date + const invalidPosts = posts.filter( + (post) => !post.title || !post.slug || !post.excerpt || !post.date, ); if (invalidPosts.length > 0) { - throw new Error(`Missing required fields in posts: ${invalidPosts.map(p => p.title || p.slug).join(', ')}`); + throw new Error( + `Missing required fields in posts: ${invalidPosts.map((p) => p.title || p.slug).join(', ')}`, + ); } for (let post of posts) { @@ -75,25 +78,25 @@ module.exports = async function rssFeed(type, title, desc, outputPath) { link, category: type, guid, - pubDate + pubDate, }; if (post.cover) { const enclosure = {}; - enclosure["@url"] = base + post.cover; - enclosure["@length"] = 15026; // dummy value, anything works - enclosure["@type"] = 'image/jpeg'; - if (typeof enclosure["@url"] === 'string') { - let tmp = enclosure["@url"].toLowerCase(); - if (tmp.indexOf('.png') >= 0) enclosure["@type"] = 'image/png'; - if (tmp.indexOf('.svg') >= 0) enclosure["@type"] = 'image/svg+xml'; - if (tmp.indexOf('.webp') >= 0) enclosure["@type"] = 'image/webp'; + enclosure['@url'] = base + post.cover; + enclosure['@length'] = 15026; // dummy value, anything works + enclosure['@type'] = 'image/jpeg'; + if (typeof enclosure['@url'] === 'string') { + let tmp = enclosure['@url'].toLowerCase(); + if (tmp.indexOf('.png') >= 0) enclosure['@type'] = 'image/png'; + if (tmp.indexOf('.svg') >= 0) enclosure['@type'] = 'image/svg+xml'; + if (tmp.indexOf('.webp') >= 0) enclosure['@type'] = 'image/webp'; } item.enclosure = enclosure; } - rss.channel.item.push(item) + rss.channel.item.push(item); } - feed.rss = rss + feed.rss = rss; const xml = json2xml.getXml(feed, '@', '', 2); await fs.writeFile(`./public/${outputPath}`, xml, 'utf8'); diff --git a/scripts/build-tools.js b/scripts/build-tools.js index c5cce74a7cb1..30404a2d015f 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -4,14 +4,27 @@ const { combineTools } = require('./tools/combine-tools'); const fs = require('fs-extra'); const { resolve } = require('path'); -const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { +const buildTools = async ( + automatedToolsPath, + manualToolsPath, + toolsPath, + tagsPath, +) => { try { let githubExtractData = await getData(); let automatedTools = await convertTools(githubExtractData); - await fs.writeFile(automatedToolsPath, JSON.stringify(automatedTools, null, ' ')); + await fs.writeFile( + automatedToolsPath, + JSON.stringify(automatedTools, null, ' '), + ); - await combineTools(automatedTools, require(manualToolsPath), toolsPath, tagsPath); + await combineTools( + automatedTools, + require(manualToolsPath), + toolsPath, + tagsPath, + ); } catch (err) { throw new Error(`An error occurred while building tools: ${err.message}`); } @@ -19,7 +32,11 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa /* istanbul ignore next */ if (require.main === module) { - const automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json'); + const automatedToolsPath = resolve( + __dirname, + '../config', + 'tools-automated.json', + ); const manualToolsPath = resolve(__dirname, '../config', 'tools-manual.json'); const toolsPath = resolve(__dirname, '../config', 'tools.json'); const tagsPath = resolve(__dirname, '../config', 'all-tags.json'); diff --git a/scripts/casestudies/index.js b/scripts/casestudies/index.js index 77695e06fd38..3ff9e415f525 100644 --- a/scripts/casestudies/index.js +++ b/scripts/casestudies/index.js @@ -1,19 +1,22 @@ const { readdir, writeFile, readFile } = require('fs').promises; const { convertToJson } = require('../../scripts/utils'); -module.exports = async function buildCaseStudiesList(dirWithCaseStudy, writeFilePath) { - try { - let files = await readdir(dirWithCaseStudy); - let caseStudiesList = []; - for (let file of files) { - const caseStudyFileName = [dirWithCaseStudy, file].join('/'); - const caseStudyContent = await readFile(caseStudyFileName, 'utf-8'); - const jsonContent = convertToJson(caseStudyContent); +module.exports = async function buildCaseStudiesList( + dirWithCaseStudy, + writeFilePath, +) { + try { + let files = await readdir(dirWithCaseStudy); + let caseStudiesList = []; + for (let file of files) { + const caseStudyFileName = [dirWithCaseStudy, file].join('/'); + const caseStudyContent = await readFile(caseStudyFileName, 'utf-8'); + const jsonContent = convertToJson(caseStudyContent); - caseStudiesList.push(jsonContent); - await writeFile(writeFilePath, JSON.stringify(caseStudiesList)) - } - } catch (err) { - throw new Error(err); + caseStudiesList.push(jsonContent); + await writeFile(writeFilePath, JSON.stringify(caseStudiesList)); } + } catch (err) { + throw new Error(err); + } }; diff --git a/scripts/compose.js b/scripts/compose.js index 8c4f0e3a4a36..00d262019428 100644 --- a/scripts/compose.js +++ b/scripts/compose.js @@ -2,25 +2,25 @@ * Script based on https://github.com/timlrx/tailwind-nextjs-starter-blog/blob/master/scripts/compose.js */ -const fs = require('fs') -const inquirer = require('inquirer') -const dedent = require('dedent') -const moment = require('moment') +const fs = require('fs'); +const inquirer = require('inquirer'); +const dedent = require('dedent'); +const moment = require('moment'); const genFrontMatter = (answers) => { - let d = new Date() + let d = new Date(); const date = [ d.getFullYear(), ('0' + (d.getMonth() + 1)).slice(-2), ('0' + d.getDate()).slice(-2), - ].join('-') - const tagArray = answers.tags.split(',') - tagArray.forEach((tag, index) => (tagArray[index] = tag.trim())) - const tags = "'" + tagArray.join("','") + "'" + ].join('-'); + const tagArray = answers.tags.split(','); + tagArray.forEach((tag, index) => (tagArray[index] = tag.trim())); + const tags = "'" + tagArray.join("','") + "'"; let frontMatter = dedent`--- title: ${answers.title ? answers.title : 'Untitled'} - date: ${moment().format("YYYY-MM-DDTh:mm:ssZ")} + date: ${moment().format('YYYY-MM-DDTh:mm:ssZ')} type: ${answers.type} canonical: ${answers.canonical ? answers.canonical : ''} tags: [${answers.tags ? tags : ''}] @@ -90,12 +90,12 @@ const genFrontMatter = (answers) => {
- ` + `; - frontMatter = frontMatter + '\n---' + frontMatter = frontMatter + '\n---'; - return frontMatter -} + return frontMatter; +}; inquirer .prompt([ @@ -118,7 +118,14 @@ inquirer name: 'type', message: 'Enter the post type:', type: 'list', - choices: ['Communication', 'Community', 'Engineering', 'Marketing', 'Strategy', 'Video'], + choices: [ + 'Communication', + 'Community', + 'Engineering', + 'Marketing', + 'Strategy', + 'Video', + ], }, { name: 'canonical', @@ -132,22 +139,22 @@ inquirer .toLowerCase() .replace(/[^a-zA-Z0-9 ]/g, '') .replace(/ /g, '-') - .replace(/-+/g, '-') - const frontMatter = genFrontMatter(answers) - const filePath = `pages/blog/${fileName ? fileName : 'untitled'}.md` + .replace(/-+/g, '-'); + const frontMatter = genFrontMatter(answers); + const filePath = `pages/blog/${fileName ? fileName : 'untitled'}.md`; fs.writeFile(filePath, frontMatter, { flag: 'wx' }, (err) => { if (err) { - throw err + throw err; } else { - console.log(`Blog post generated successfully at ${filePath}`) + console.log(`Blog post generated successfully at ${filePath}`); } - }) + }); }) .catch((error) => { - console.error(error) + console.error(error); if (error.isTtyError) { - console.log("Prompt couldn't be rendered in the current environment") + console.log("Prompt couldn't be rendered in the current environment"); } else { - console.log('Something went wrong, sorry!') + console.log('Something went wrong, sorry!'); } - }) + }); diff --git a/scripts/dashboard/build-dashboard.js b/scripts/dashboard/build-dashboard.js index c20be204e87b..cb07d85c2f5f 100644 --- a/scripts/dashboard/build-dashboard.js +++ b/scripts/dashboard/build-dashboard.js @@ -20,8 +20,8 @@ async function getDiscussions(query, pageSize, endCursor = null) { first: pageSize, after: endCursor, headers: { - authorization: `token ${process.env.GITHUB_TOKEN}` - } + authorization: `token ${process.env.GITHUB_TOKEN}`, + }, }); if (result.rateLimit.remaining <= 100) { @@ -30,7 +30,7 @@ async function getDiscussions(query, pageSize, endCursor = null) { `cost = ${result.rateLimit.cost}`, `limit = ${result.rateLimit.limit}`, `remaining = ${result.rateLimit.remaining}`, - `resetAt = ${result.rateLimit.resetAt}` + `resetAt = ${result.rateLimit.resetAt}`, ); } @@ -41,7 +41,9 @@ async function getDiscussions(query, pageSize, endCursor = null) { if (!hasNextPage) { return result.search.nodes; } - return result.search.nodes.concat(await getDiscussions(query, pageSize, result.search.pageInfo.endCursor)); + return result.search.nodes.concat( + await getDiscussions(query, pageSize, result.search.pageInfo.endCursor), + ); } catch (e) { console.error(e); return Promise.reject(e); @@ -50,12 +52,15 @@ async function getDiscussions(query, pageSize, endCursor = null) { async function getDiscussionByID(isPR, id) { try { - const result = await graphql(isPR ? Queries.pullRequestById : Queries.issueById, { - id, - headers: { - authorization: `token ${process.env.GITHUB_TOKEN}` - } - }); + const result = await graphql( + isPR ? Queries.pullRequestById : Queries.issueById, + { + id, + headers: { + authorization: `token ${process.env.GITHUB_TOKEN}`, + }, + }, + ); return result; } catch (e) { @@ -70,19 +75,28 @@ async function processHotDiscussions(batch) { try { const isPR = discussion.__typename === 'PullRequest'; if (discussion.comments.pageInfo.hasNextPage) { - const fetchedDiscussion = await getDiscussionByID(isPR, discussion.id); + const fetchedDiscussion = await getDiscussionByID( + isPR, + discussion.id, + ); discussion = fetchedDiscussion.node; } const interactionsCount = discussion.reactions.totalCount + discussion.comments.totalCount + - discussion.comments.nodes.reduce((acc, curr) => acc + curr.reactions.totalCount, 0); + discussion.comments.nodes.reduce( + (acc, curr) => acc + curr.reactions.totalCount, + 0, + ); const finalInteractionsCount = isPR ? interactionsCount + - discussion.reviews.totalCount + - discussion.reviews.nodes.reduce((acc, curr) => acc + curr.comments.totalCount, 0) + discussion.reviews.totalCount + + discussion.reviews.nodes.reduce( + (acc, curr) => acc + curr.comments.totalCount, + 0, + ) : interactionsCount; return { @@ -94,13 +108,17 @@ async function processHotDiscussions(batch) { resourcePath: discussion.resourcePath, repo: `asyncapi/${discussion.repository.name}`, labels: discussion.labels ? discussion.labels.nodes : [], - score: finalInteractionsCount / (monthsSince(discussion.timelineItems.updatedAt) + 2) ** 1.8 + score: + finalInteractionsCount / + (monthsSince(discussion.timelineItems.updatedAt) + 2) ** 1.8, }; } catch (e) { - console.error(`there were some issues while parsing this item: ${JSON.stringify(discussion)}`); + console.error( + `there were some issues while parsing this item: ${JSON.stringify(discussion)}`, + ); throw e; } - }) + }), ); } @@ -116,7 +134,9 @@ async function getHotDiscussions(discussions) { } result.sort((ElemA, ElemB) => ElemB.score - ElemA.score); - const filteredResult = result.filter((issue) => issue.author !== 'asyncapi-bot'); + const filteredResult = result.filter( + (issue) => issue.author !== 'asyncapi-bot', + ); return filteredResult.slice(0, 12); } @@ -126,7 +146,7 @@ async function writeToFile(content, writePath) { } catch (error) { console.error('Failed to write dashboard data:', { error: error.message, - writePath + writePath, }); throw error; } @@ -142,13 +162,17 @@ async function mapGoodFirstIssues(issues) { author: issue.author.login, area: getLabel(issue, 'area/') || 'Unknown', labels: issue.labels.nodes.filter( - (label) => !label.name.startsWith('area/') && !label.name.startsWith('good first issue') - ) + (label) => + !label.name.startsWith('area/') && + !label.name.startsWith('good first issue'), + ), })); } function getLabel(issue, filter) { - const result = issue.labels.nodes.find((label) => label.name.startsWith(filter)); + const result = issue.labels.nodes.find((label) => + label.name.startsWith(filter), + ); return result?.name.split('/')[1]; } @@ -163,11 +187,14 @@ async function start(writePath) { try { const issues = await getDiscussions(Queries.hotDiscussionsIssues, 20); const PRs = await getDiscussions(Queries.hotDiscussionsPullRequests, 20); - const rawGoodFirstIssues = await getDiscussions(Queries.goodFirstIssues, 20); + const rawGoodFirstIssues = await getDiscussions( + Queries.goodFirstIssues, + 20, + ); const discussions = issues.concat(PRs); const [hotDiscussions, goodFirstIssues] = await Promise.all([ getHotDiscussions(discussions), - mapGoodFirstIssues(rawGoodFirstIssues) + mapGoodFirstIssues(rawGoodFirstIssues), ]); return await writeToFile({ hotDiscussions, goodFirstIssues }, writePath); } catch (e) { @@ -181,4 +208,14 @@ if (require.main === module) { start(resolve(__dirname, '..', '..', 'dashboard.json')); } -module.exports = { getLabel, monthsSince, mapGoodFirstIssues, getHotDiscussions, getDiscussionByID, getDiscussions, writeToFile, start, processHotDiscussions }; +module.exports = { + getLabel, + monthsSince, + mapGoodFirstIssues, + getHotDiscussions, + getDiscussionByID, + getDiscussions, + writeToFile, + start, + processHotDiscussions, +}; diff --git a/scripts/finance/index.js b/scripts/finance/index.js index 3f4a5edcfb6e..af3cf0a80f60 100644 --- a/scripts/finance/index.js +++ b/scripts/finance/index.js @@ -1,25 +1,48 @@ const { - promises: { mkdir } + promises: { mkdir }, } = require('fs'); const { resolve } = require('path'); const writeJSON = require('../utils/readAndWriteJson.js'); -module.exports = async function buildFinanceInfoList({ currentDir, configDir, financeDir, year, jsonDataDir }) { - try { - const expensesPath = resolve(currentDir, configDir, financeDir, year, 'Expenses.yml'); - const expensesLinkPath = resolve(currentDir, configDir, financeDir, year, 'ExpensesLink.yml'); +module.exports = async function buildFinanceInfoList({ + currentDir, + configDir, + financeDir, + year, + jsonDataDir, +}) { + try { + const expensesPath = resolve( + currentDir, + configDir, + financeDir, + year, + 'Expenses.yml', + ); + const expensesLinkPath = resolve( + currentDir, + configDir, + financeDir, + year, + 'ExpensesLink.yml', + ); - // Ensure the directory exists before writing the files - const jsonDirectory = resolve(currentDir, configDir, financeDir, jsonDataDir); - await mkdir(jsonDirectory, { recursive: true }); + // Ensure the directory exists before writing the files + const jsonDirectory = resolve( + currentDir, + configDir, + financeDir, + jsonDataDir, + ); + await mkdir(jsonDirectory, { recursive: true }); - // Write Expenses and ExpensesLink to JSON files - const expensesJsonPath = resolve(jsonDirectory, 'Expenses.json'); - await writeJSON(expensesPath, expensesJsonPath); + // Write Expenses and ExpensesLink to JSON files + const expensesJsonPath = resolve(jsonDirectory, 'Expenses.json'); + await writeJSON(expensesPath, expensesJsonPath); - const expensesLinkJsonPath = resolve(jsonDirectory, 'ExpensesLink.json'); - await writeJSON(expensesLinkPath, expensesLinkJsonPath); - } catch (err) { - throw new Error(err); - } -}; \ No newline at end of file + const expensesLinkJsonPath = resolve(jsonDirectory, 'ExpensesLink.json'); + await writeJSON(expensesLinkPath, expensesLinkJsonPath); + } catch (err) { + throw new Error(err); + } +}; diff --git a/scripts/index.js b/scripts/index.js index 33125fe7533b..0ae68666ce24 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -12,11 +12,11 @@ async function start() { 'blog', 'AsyncAPI Initiative Blog RSS Feed', 'AsyncAPI Initiative Blog', - 'rss.xml' + 'rss.xml', ); await buildCaseStudiesList( 'config/casestudies', - resolve(__dirname, '../config', 'case-studies.json') + resolve(__dirname, '../config', 'case-studies.json'), ); await buildAdoptersList(); const financeDir = resolve('.', 'config', 'finance'); @@ -44,7 +44,7 @@ async function start() { configDir: 'config', financeDir: 'finance', year: latestYear, - jsonDataDir: 'json-data' + jsonDataDir: 'json-data', }); } diff --git a/scripts/markdown/check-markdown.js b/scripts/markdown/check-markdown.js index 8979f7e0b4ab..001a210a2a77 100644 --- a/scripts/markdown/check-markdown.js +++ b/scripts/markdown/check-markdown.js @@ -8,12 +8,12 @@ const path = require('path'); * @returns {boolean} True if the string is a valid URL, false otherwise. */ function isValidURL(str) { - try { - new URL(str); - return true; - } catch (err) { - return false; - } + try { + new URL(str); + return true; + } catch (err) { + return false; + } } /** @@ -23,51 +23,60 @@ function isValidURL(str) { * @returns {string[]|null} An array of validation error messages, or null if no errors. */ function validateBlogs(frontmatter) { - const requiredAttributes = ['title', 'date', 'type', 'tags', 'cover', 'authors']; - const errors = []; - - // Check for required attributes - requiredAttributes.forEach(attr => { - if (!frontmatter.hasOwnProperty(attr)) { - errors.push(`${attr} is missing`); - } - }); - - // Validate date format - if (frontmatter.date && Number.isNaN(Date.parse(frontmatter.date))) { - errors.push(`Invalid date format: ${frontmatter.date}`); + const requiredAttributes = [ + 'title', + 'date', + 'type', + 'tags', + 'cover', + 'authors', + ]; + const errors = []; + + // Check for required attributes + requiredAttributes.forEach((attr) => { + if (!frontmatter.hasOwnProperty(attr)) { + errors.push(`${attr} is missing`); } - - // Validate tags format (must be an array) - if (frontmatter.tags && !Array.isArray(frontmatter.tags)) { - errors.push(`Tags should be an array`); - } - - // Validate cover is a string - if (frontmatter.cover && typeof frontmatter.cover !== 'string') { - errors.push(`Cover must be a string`); - } - - // Validate authors (must be an array with valid attributes) - if (frontmatter.authors) { - if (!Array.isArray(frontmatter.authors)) { - errors.push('Authors should be an array'); - } else { - frontmatter.authors.forEach((author, index) => { - if (!author.name) { - errors.push(`Author at index ${index} is missing a name`); - } - if (author.link && !isValidURL(author.link)) { - errors.push(`Invalid URL for author at index ${index}: ${author.link}`); - } - if (!author.photo) { - errors.push(`Author at index ${index} is missing a photo`); - } - }); + }); + + // Validate date format + if (frontmatter.date && Number.isNaN(Date.parse(frontmatter.date))) { + errors.push(`Invalid date format: ${frontmatter.date}`); + } + + // Validate tags format (must be an array) + if (frontmatter.tags && !Array.isArray(frontmatter.tags)) { + errors.push(`Tags should be an array`); + } + + // Validate cover is a string + if (frontmatter.cover && typeof frontmatter.cover !== 'string') { + errors.push(`Cover must be a string`); + } + + // Validate authors (must be an array with valid attributes) + if (frontmatter.authors) { + if (!Array.isArray(frontmatter.authors)) { + errors.push('Authors should be an array'); + } else { + frontmatter.authors.forEach((author, index) => { + if (!author.name) { + errors.push(`Author at index ${index} is missing a name`); + } + if (author.link && !isValidURL(author.link)) { + errors.push( + `Invalid URL for author at index ${index}: ${author.link}`, + ); } + if (!author.photo) { + errors.push(`Author at index ${index} is missing a photo`); + } + }); } + } - return errors.length ? errors : null; + return errors.length ? errors : null; } /** @@ -77,19 +86,22 @@ function validateBlogs(frontmatter) { * @returns {string[]|null} An array of validation error messages, or null if no errors. */ function validateDocs(frontmatter) { - const errors = []; - - // Check if title exists and is a string - if (!frontmatter.title || typeof frontmatter.title !== 'string') { - errors.push('Title is missing or not a string'); - } - - // Check if weight exists and is a number - if (frontmatter.weight === undefined || typeof frontmatter.weight !== 'number') { - errors.push('Weight is missing or not a number'); - } - - return errors.length ? errors : null; + const errors = []; + + // Check if title exists and is a string + if (!frontmatter.title || typeof frontmatter.title !== 'string') { + errors.push('Title is missing or not a string'); + } + + // Check if weight exists and is a number + if ( + frontmatter.weight === undefined || + typeof frontmatter.weight !== 'number' + ) { + errors.push('Weight is missing or not a number'); + } + + return errors.length ? errors : null; } /** @@ -99,44 +111,44 @@ function validateDocs(frontmatter) { * @param {string} [relativePath=''] - The relative path of the folder for logging purposes. */ function checkMarkdownFiles(folderPath, validateFunction, relativePath = '') { - fs.readdir(folderPath, (err, files) => { + fs.readdir(folderPath, (err, files) => { + if (err) { + console.error('Error reading directory:', err); + return; + } + + files.forEach((file) => { + const filePath = path.join(folderPath, file); + const relativeFilePath = path.join(relativePath, file); + + // Skip the folder 'docs/reference/specification' + if (relativeFilePath.includes('reference/specification')) { + return; + } + + fs.stat(filePath, (err, stats) => { if (err) { - console.error('Error reading directory:', err); - return; + console.error('Error reading file stats:', err); + return; } - files.forEach(file => { - const filePath = path.join(folderPath, file); - const relativeFilePath = path.join(relativePath, file); - - // Skip the folder 'docs/reference/specification' - if (relativeFilePath.includes('reference/specification')) { - return; - } - - fs.stat(filePath, (err, stats) => { - if (err) { - console.error('Error reading file stats:', err); - return; - } - - // Recurse if directory, otherwise validate markdown file - if (stats.isDirectory()) { - checkMarkdownFiles(filePath, validateFunction, relativeFilePath); - } else if (path.extname(file) === '.md') { - const fileContent = fs.readFileSync(filePath, 'utf-8'); - const { data: frontmatter } = matter(fileContent); - - const errors = validateFunction(frontmatter); - if (errors) { - console.log(`Errors in file ${relativeFilePath}:`); - errors.forEach(error => console.log(` - ${error}`)); - process.exitCode = 1; - } - } - }); - }); + // Recurse if directory, otherwise validate markdown file + if (stats.isDirectory()) { + checkMarkdownFiles(filePath, validateFunction, relativeFilePath); + } else if (path.extname(file) === '.md') { + const fileContent = fs.readFileSync(filePath, 'utf-8'); + const { data: frontmatter } = matter(fileContent); + + const errors = validateFunction(frontmatter); + if (errors) { + console.log(`Errors in file ${relativeFilePath}:`); + errors.forEach((error) => console.log(` - ${error}`)); + process.exitCode = 1; + } + } + }); }); + }); } const docsFolderPath = path.resolve(__dirname, '../../markdown/docs'); diff --git a/scripts/tools/categorylist.js b/scripts/tools/categorylist.js index 11fcc3790e9e..15323b1606aa 100644 --- a/scripts/tools/categorylist.js +++ b/scripts/tools/categorylist.js @@ -1,100 +1,119 @@ // Various categories to define the category in which a tool has to be listed const categoryList = [ { - name: "APIs", - tag: "api", - description: "The following is a list of APIs that expose functionality related to AsyncAPI." + name: 'APIs', + tag: 'api', + description: + 'The following is a list of APIs that expose functionality related to AsyncAPI.', }, { - name: "Code-first tools", - tag: "code-first", - description: "The following is a list of tools that generate AsyncAPI documents from your code." + name: 'Code-first tools', + tag: 'code-first', + description: + 'The following is a list of tools that generate AsyncAPI documents from your code.', }, { - name: "Code Generators", - tag: "code-generator", - description: "The following is a list of tools that generate code from an AsyncAPI document; not the other way around." + name: 'Code Generators', + tag: 'code-generator', + description: + 'The following is a list of tools that generate code from an AsyncAPI document; not the other way around.', }, { - name: "Converters", - tag: "converter", - description: "The following is a list of tools that do not yet belong to any specific category but are also useful for the community." + name: 'Converters', + tag: 'converter', + description: + 'The following is a list of tools that do not yet belong to any specific category but are also useful for the community.', }, { - name: "Directories", - tag: "directory", - description: "The following is a list of directories that index public AsyncAPI documents." + name: 'Directories', + tag: 'directory', + description: + 'The following is a list of directories that index public AsyncAPI documents.', }, { - name: "Documentation Generators", - tag: "documentation-generator", - description: "The following is a list of tools that generate human-readable documentation from an AsyncAPI document." + name: 'Documentation Generators', + tag: 'documentation-generator', + description: + 'The following is a list of tools that generate human-readable documentation from an AsyncAPI document.', }, { - name: "Editors", - tag: "editor", - description: "The following is a list of editors or related tools that allow editing of AsyncAPI document." + name: 'Editors', + tag: 'editor', + description: + 'The following is a list of editors or related tools that allow editing of AsyncAPI document.', }, { - name: "UI components", - tag: "ui-component", - description: "The following is a list of UI components to view AsyncAPI documents." + name: 'UI components', + tag: 'ui-component', + description: + 'The following is a list of UI components to view AsyncAPI documents.', }, { - name: "DSL", - tag: "dsl", - description: "Writing YAML by hand is no fun, and maybe you don't want a GUI, so use a Domain Specific Language to write AsyncAPI in your language of choice." + name: 'DSL', + tag: 'dsl', + description: + "Writing YAML by hand is no fun, and maybe you don't want a GUI, so use a Domain Specific Language to write AsyncAPI in your language of choice.", }, { - name: "Frameworks", - tag: "framework", - description: "The following is a list of API/application frameworks that make use of AsyncAPI." + name: 'Frameworks', + tag: 'framework', + description: + 'The following is a list of API/application frameworks that make use of AsyncAPI.', }, { - name: "GitHub Actions", - tag: "github-action", - description: "The following is a list of GitHub Actions that you can use in your workflows" + name: 'GitHub Actions', + tag: 'github-action', + description: + 'The following is a list of GitHub Actions that you can use in your workflows', }, { - name: "Mocking and Testing", - tag: "mocking-and-testing", - description: "The tools below take specification documents as input, then publish fake messages to broker destinations for simulation purposes. They may also check that publisher messages are compliant with schemas." + name: 'Mocking and Testing', + tag: 'mocking-and-testing', + description: + 'The tools below take specification documents as input, then publish fake messages to broker destinations for simulation purposes. They may also check that publisher messages are compliant with schemas.', }, { - name: "Validators", - tag: "validator", - description: "The following is a list of tools that validate AsyncAPI documents." + name: 'Validators', + tag: 'validator', + description: + 'The following is a list of tools that validate AsyncAPI documents.', }, { - name: "Compare tools", - tag: "compare-tool", - description: "The following is a list of tools that compare AsyncAPI documents." + name: 'Compare tools', + tag: 'compare-tool', + description: + 'The following is a list of tools that compare AsyncAPI documents.', }, { - name: "CLIs", - tag: "cli", - description: "The following is a list of tools that you can work with in terminal or do some CI/CD automation." + name: 'CLIs', + tag: 'cli', + description: + 'The following is a list of tools that you can work with in terminal or do some CI/CD automation.', }, { - name: "Bundlers", - tag: "bundler", - description: "The following is a list of tools that you can work with to bundle AsyncAPI documents." + name: 'Bundlers', + tag: 'bundler', + description: + 'The following is a list of tools that you can work with to bundle AsyncAPI documents.', }, { - name: "IDE Extensions", - tag: "ide-extension", - description: "The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others" + name: 'IDE Extensions', + tag: 'ide-extension', + description: + 'The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others', }, { - name: "AsyncAPI Generator Templates", - tag: "generator-template", - description: "The following is a list of templates compatible with AsyncAPI Generator. You can use them to generate apps, clients or documentation from your AsyncAPI documents." + name: 'AsyncAPI Generator Templates', + tag: 'generator-template', + description: + 'The following is a list of templates compatible with AsyncAPI Generator. You can use them to generate apps, clients or documentation from your AsyncAPI documents.', }, { - name: "Others", - tag: "other", - description: "The following is a list of tools that comes under Other category." - } -] + name: 'Others', + tag: 'other', + description: + 'The following is a list of tools that comes under Other category.', + }, +]; -module.exports = {categoryList} +module.exports = { categoryList }; diff --git a/scripts/tools/combine-tools.js b/scripts/tools/combine-tools.js index 602262428fa1..34980f1abd61 100644 --- a/scripts/tools/combine-tools.js +++ b/scripts/tools/combine-tools.js @@ -1,142 +1,160 @@ -const { languagesColor, technologiesColor } = require("./tags-color") -const { categoryList } = require("./categorylist.js") -const { createToolObject } = require("./tools-object") -const fs = require('fs') -const schema = require("./tools-schema.json"); -const Ajv = require("ajv") -const addFormats = require("ajv-formats") -const Fuse = require("fuse.js"); -const ajv = new Ajv() -addFormats(ajv, ["uri"]) -const validate = ajv.compile(schema) +const { languagesColor, technologiesColor } = require('./tags-color'); +const { categoryList } = require('./categorylist.js'); +const { createToolObject } = require('./tools-object'); +const fs = require('fs'); +const schema = require('./tools-schema.json'); +const Ajv = require('ajv'); +const addFormats = require('ajv-formats'); +const Fuse = require('fuse.js'); +const ajv = new Ajv(); +addFormats(ajv, ['uri']); +const validate = ajv.compile(schema); let finalTools = {}; for (var category of categoryList) { - finalTools[category.name] = { - description: category.description, - toolsList: [] - }; + finalTools[category.name] = { + description: category.description, + toolsList: [], + }; } // Config options set for the Fuse object const options = { - includeScore: true, - shouldSort: true, - threshold: 0.39, - keys: ['name', 'color', 'borderColor'] -} + includeScore: true, + shouldSort: true, + threshold: 0.39, + keys: ['name', 'color', 'borderColor'], +}; -// Two seperate lists and Fuse objects initialised to search languages and technologies tags +// Two seperate lists and Fuse objects initialised to search languages and technologies tags // from specified list of same. -let languageList = [...languagesColor], technologyList = [...technologiesColor]; -let languageFuse = new Fuse(languageList, options), technologyFuse = new Fuse(technologyList, options) +let languageList = [...languagesColor], + technologyList = [...technologiesColor]; +let languageFuse = new Fuse(languageList, options), + technologyFuse = new Fuse(technologyList, options); -// takes individual tool object and inserts borderColor and backgroundColor of the tags of +// takes individual tool object and inserts borderColor and backgroundColor of the tags of // languages and technologies, for Tool Card in website. const getFinalTool = async (toolObject) => { - let finalObject = toolObject; + let finalObject = toolObject; - //there might be a tool without language - if (toolObject.filters.language) { - let languageArray = [] - if (typeof toolObject.filters.language === 'string') { - const languageSearch = await languageFuse.search(toolObject.filters.language) - if (languageSearch.length) { - languageArray.push(languageSearch[0].item); - } else { - // adds a new language object in the Fuse list as well as in tool object - // so that it isn't missed out in the UI. - let languageObject = { - name: toolObject.filters.language, - color: 'bg-[#57f281]', - borderColor: 'border-[#37f069]' - } - languageList.push(languageObject); - languageArray.push(languageObject) - languageFuse = new Fuse(languageList, options) - } + //there might be a tool without language + if (toolObject.filters.language) { + let languageArray = []; + if (typeof toolObject.filters.language === 'string') { + const languageSearch = await languageFuse.search( + toolObject.filters.language, + ); + if (languageSearch.length) { + languageArray.push(languageSearch[0].item); + } else { + // adds a new language object in the Fuse list as well as in tool object + // so that it isn't missed out in the UI. + let languageObject = { + name: toolObject.filters.language, + color: 'bg-[#57f281]', + borderColor: 'border-[#37f069]', + }; + languageList.push(languageObject); + languageArray.push(languageObject); + languageFuse = new Fuse(languageList, options); + } + } else { + for (const language of toolObject?.filters?.language) { + const languageSearch = await languageFuse.search(language); + if (languageSearch.length > 0) { + languageArray.push(languageSearch[0].item); } else { - for (const language of toolObject?.filters?.language) { - const languageSearch = await languageFuse.search(language) - if (languageSearch.length > 0) { - languageArray.push(languageSearch[0].item); - } - else { - // adds a new language object in the Fuse list as well as in tool object - // so that it isn't missed out in the UI. - let languageObject = { - name: language, - color: 'bg-[#57f281]', - borderColor: 'border-[#37f069]' - } - languageList.push(languageObject); - languageArray.push(languageObject) - languageFuse = new Fuse(languageList, options) - } - } + // adds a new language object in the Fuse list as well as in tool object + // so that it isn't missed out in the UI. + let languageObject = { + name: language, + color: 'bg-[#57f281]', + borderColor: 'border-[#37f069]', + }; + languageList.push(languageObject); + languageArray.push(languageObject); + languageFuse = new Fuse(languageList, options); } - finalObject.filters.language = languageArray + } } - let technologyArray = []; - if (toolObject.filters.technology) { - for (const technology of toolObject?.filters?.technology) { - const technologySearch = await technologyFuse.search(technology) - if (technologySearch.length > 0) { - technologyArray.push(technologySearch[0].item); - } - else { - // adds a new technology object in the Fuse list as well as in tool object - // so that it isn't missed out in the UI. - let technologyObject = { - name: technology, - color: 'bg-[#61d0f2]', - borderColor: 'border-[#40ccf7]' - } - technologyList.push(technologyObject); - technologyArray.push(technologyObject); - technologyFuse = new Fuse(technologyList, options) - } - } + finalObject.filters.language = languageArray; + } + let technologyArray = []; + if (toolObject.filters.technology) { + for (const technology of toolObject?.filters?.technology) { + const technologySearch = await technologyFuse.search(technology); + if (technologySearch.length > 0) { + technologyArray.push(technologySearch[0].item); + } else { + // adds a new technology object in the Fuse list as well as in tool object + // so that it isn't missed out in the UI. + let technologyObject = { + name: technology, + color: 'bg-[#61d0f2]', + borderColor: 'border-[#40ccf7]', + }; + technologyList.push(technologyObject); + technologyArray.push(technologyObject); + technologyFuse = new Fuse(technologyList, options); + } } - finalObject.filters.technology = technologyArray; - return finalObject; -} - + } + finalObject.filters.technology = technologyArray; + return finalObject; +}; -// Combine the automated tools and manual tools list into single JSON object file, and +// Combine the automated tools and manual tools list into single JSON object file, and // lists down all the language and technology tags in one JSON file. -const combineTools = async (automatedTools, manualTools, toolsPath, tagsPath) => { - for (const key in automatedTools) { - let finalToolsList = []; - if (automatedTools[key].toolsList.length) { - for (const tool of automatedTools[key].toolsList) { - finalToolsList.push(await getFinalTool(tool)) - } - } - if (manualTools[key] && manualTools[key].toolsList.length) { - for (const tool of manualTools[key].toolsList) { - let isAsyncAPIrepo; - const isValid = await validate(tool) - if (isValid) { - if (tool?.links?.repoUrl) { - const url = new URL(tool.links.repoUrl) - isAsyncAPIrepo = url.href.startsWith("https://github.com/asyncapi/") - } else isAsyncAPIrepo = false - let toolObject = await createToolObject(tool, "", "", isAsyncAPIrepo) - finalToolsList.push(await getFinalTool(toolObject)) - } else { - console.error('Script is not failing, it is just dropping errors for further investigation'); - console.error(`Invalid ${tool.title} .asyncapi-tool file.`); - console.error(`Located in manual-tools.json file`); - console.error('Validation errors:', JSON.stringify(validate.errors, null, 2)); - } - } +const combineTools = async ( + automatedTools, + manualTools, + toolsPath, + tagsPath, +) => { + for (const key in automatedTools) { + let finalToolsList = []; + if (automatedTools[key].toolsList.length) { + for (const tool of automatedTools[key].toolsList) { + finalToolsList.push(await getFinalTool(tool)); + } + } + if (manualTools[key] && manualTools[key].toolsList.length) { + for (const tool of manualTools[key].toolsList) { + let isAsyncAPIrepo; + const isValid = await validate(tool); + if (isValid) { + if (tool?.links?.repoUrl) { + const url = new URL(tool.links.repoUrl); + isAsyncAPIrepo = url.href.startsWith( + 'https://github.com/asyncapi/', + ); + } else isAsyncAPIrepo = false; + let toolObject = await createToolObject(tool, '', '', isAsyncAPIrepo); + finalToolsList.push(await getFinalTool(toolObject)); + } else { + console.error( + 'Script is not failing, it is just dropping errors for further investigation', + ); + console.error(`Invalid ${tool.title} .asyncapi-tool file.`); + console.error(`Located in manual-tools.json file`); + console.error( + 'Validation errors:', + JSON.stringify(validate.errors, null, 2), + ); } - finalToolsList.sort((tool, anotherTool) => tool.title.localeCompare(anotherTool.title)); - finalTools[key].toolsList = finalToolsList + } } - fs.writeFileSync(toolsPath,JSON.stringify(finalTools)); - fs.writeFileSync(tagsPath,JSON.stringify({ languages: languageList, technologies: technologyList }),) -} + finalToolsList.sort((tool, anotherTool) => + tool.title.localeCompare(anotherTool.title), + ); + finalTools[key].toolsList = finalToolsList; + } + fs.writeFileSync(toolsPath, JSON.stringify(finalTools)); + fs.writeFileSync( + tagsPath, + JSON.stringify({ languages: languageList, technologies: technologyList }), + ); +}; -module.exports = { combineTools } \ No newline at end of file +module.exports = { combineTools }; diff --git a/scripts/tools/extract-tools-github.js b/scripts/tools/extract-tools-github.js index 55e96124b752..567a8077be4b 100644 --- a/scripts/tools/extract-tools-github.js +++ b/scripts/tools/extract-tools-github.js @@ -1,5 +1,5 @@ const axios = require('axios'); -require('dotenv').config() +require('dotenv').config(); const getData = async () => { try { @@ -10,7 +10,7 @@ const getData = async () => { accept: 'application/vnd.github.text-match+json', authorization: `token ${process.env.GITHUB_TOKEN}`, }, - } + }, ); return result.data; @@ -19,4 +19,4 @@ const getData = async () => { } }; -module.exports = { getData }; \ No newline at end of file +module.exports = { getData }; diff --git a/scripts/tools/tags-color.js b/scripts/tools/tags-color.js index 9a18ca2058d5..5897fcab5837 100644 --- a/scripts/tools/tags-color.js +++ b/scripts/tools/tags-color.js @@ -1,178 +1,178 @@ // Language and Technology tags along with their colors in UI are defined here. const languagesColor = [ - { - name: "Go/Golang", - color: "bg-[#8ECFDF]", - borderColor: "border-[#00AFD9]" - }, - { - name: "Java", - color: "bg-[#ECA2A4]", - borderColor: "border-[#EC2125]" - }, - { - name: "JavaScript", - color: "bg-[#F2F1C7]", - borderColor: "border-[#BFBE86]" - }, - { - name: "HTML", - color: "bg-[#E2A291]", - borderColor: "border-[#E44D26]" - }, - { - name: "C/C++", - color: "bg-[#93CDEF]", - borderColor: "border-[#0080CC]" - }, - { - name: "C#", - color: "bg-[#E3AFE0]", - borderColor: "border-[#9B4F96]" - }, - { - name: "Python", - color: "bg-[#A8D0EF]", - borderColor: "border-[#3878AB]" - }, - { - name: "TypeScript", - color: "bg-[#7DBCFE]", - borderColor: "border-[#2C78C7]" - }, - { - name: "Kotlin", - color: "bg-[#B1ACDF]", - borderColor: "border-[#756BD9]" - }, - { - name: "Scala", - color: "bg-[#FFA299]", - borderColor: "border-[#DF301F]" - }, - { - name: "Markdown", - color: "bg-[#BABEBF]", - borderColor: "border-[#445B64]" - }, - { - name: "YAML", - color: "bg-[#FFB764]", - borderColor: "border-[#F1901F]" - }, - { - name: "R", - color: "bg-[#84B5ED]", - borderColor: "border-[#246BBE]" - }, - { - name: "Ruby", - color: "bg-[#FF8289]", - borderColor: "border-[#FF000F]" - }, - { - name: "Rust", - color: "bg-[#FFB8AA]", - borderColor: "border-[#E43716]" - }, - { - name: "Shell", - color: "bg-[#87D4FF]", - borderColor: "border-[#389ED7]" - }, - { - name: "Groovy", - color: "bg-[#B6D5E5]", - borderColor: "border-[#609DBC]" - } -] + { + name: 'Go/Golang', + color: 'bg-[#8ECFDF]', + borderColor: 'border-[#00AFD9]', + }, + { + name: 'Java', + color: 'bg-[#ECA2A4]', + borderColor: 'border-[#EC2125]', + }, + { + name: 'JavaScript', + color: 'bg-[#F2F1C7]', + borderColor: 'border-[#BFBE86]', + }, + { + name: 'HTML', + color: 'bg-[#E2A291]', + borderColor: 'border-[#E44D26]', + }, + { + name: 'C/C++', + color: 'bg-[#93CDEF]', + borderColor: 'border-[#0080CC]', + }, + { + name: 'C#', + color: 'bg-[#E3AFE0]', + borderColor: 'border-[#9B4F96]', + }, + { + name: 'Python', + color: 'bg-[#A8D0EF]', + borderColor: 'border-[#3878AB]', + }, + { + name: 'TypeScript', + color: 'bg-[#7DBCFE]', + borderColor: 'border-[#2C78C7]', + }, + { + name: 'Kotlin', + color: 'bg-[#B1ACDF]', + borderColor: 'border-[#756BD9]', + }, + { + name: 'Scala', + color: 'bg-[#FFA299]', + borderColor: 'border-[#DF301F]', + }, + { + name: 'Markdown', + color: 'bg-[#BABEBF]', + borderColor: 'border-[#445B64]', + }, + { + name: 'YAML', + color: 'bg-[#FFB764]', + borderColor: 'border-[#F1901F]', + }, + { + name: 'R', + color: 'bg-[#84B5ED]', + borderColor: 'border-[#246BBE]', + }, + { + name: 'Ruby', + color: 'bg-[#FF8289]', + borderColor: 'border-[#FF000F]', + }, + { + name: 'Rust', + color: 'bg-[#FFB8AA]', + borderColor: 'border-[#E43716]', + }, + { + name: 'Shell', + color: 'bg-[#87D4FF]', + borderColor: 'border-[#389ED7]', + }, + { + name: 'Groovy', + color: 'bg-[#B6D5E5]', + borderColor: 'border-[#609DBC]', + }, +]; const technologiesColor = [ - { - name: "Node.js", - color: "bg-[#BDFF67]", - borderColor: "border-[#84CE24]" - }, - { - name: "Hermes", - color: "bg-[#8AEEBD]", - borderColor: "border-[#2AB672]" - }, - { - name: "React JS", - color: "bg-[#9FECFA]", - borderColor: "border-[#08D8FE]" - }, - { - name: ".NET", - color: "bg-[#A184FF]", - borderColor: "border-[#5026D4]" - }, - { - name: "ASP.NET", - color: "bg-[#71C2FB]", - borderColor: "border-[#1577BC]" - }, - { - name: "Springboot", - color: "bg-[#98E279]", - borderColor: "border-[#68BC44]" - }, - { - name: "AWS", - color: "bg-[#FF9F59]", - borderColor: "border-[#EF6703]" - }, - { - name: "Docker", - color: "bg-[#B8E0FF]", - borderColor: "border-[#2596ED]" - }, - { - name: "Node-RED", - color: "bg-[#FF7474]", - borderColor: "border-[#8F0101]" - }, - { - name: "Maven", - color: "bg-[#FF6B80]", - borderColor: "border-[#CA1A33]" - }, - { - name: "Saas", - color: "bg-[#6AB8EC]", - borderColor: "border-[#2275AD]" - }, - { - name: "Kubernetes-native", - color: "bg-[#D7C7F2]", - borderColor: "border-[#A387D2]" - }, - { - name: "Scala", - color: "bg-[#D7C7F2]", - borderColor: "border-[#A387D2]" - }, - { - name: "Azure", - color: "bg-[#4B93FF]", - borderColor: "border-[#015ADF]" - }, - { - name: "Jenkins", - color: "bg-[#D7C7F2]", - borderColor: "border-[#A387D2]" - }, - { - name: "Flask", - color: "bg-[#D7C7F2]", - borderColor: "border-[#A387D2]" - }, - { - name: "Nest Js", - color: "bg-[#E1224E]", - borderColor: "border-[#B9012b]" - } -] + { + name: 'Node.js', + color: 'bg-[#BDFF67]', + borderColor: 'border-[#84CE24]', + }, + { + name: 'Hermes', + color: 'bg-[#8AEEBD]', + borderColor: 'border-[#2AB672]', + }, + { + name: 'React JS', + color: 'bg-[#9FECFA]', + borderColor: 'border-[#08D8FE]', + }, + { + name: '.NET', + color: 'bg-[#A184FF]', + borderColor: 'border-[#5026D4]', + }, + { + name: 'ASP.NET', + color: 'bg-[#71C2FB]', + borderColor: 'border-[#1577BC]', + }, + { + name: 'Springboot', + color: 'bg-[#98E279]', + borderColor: 'border-[#68BC44]', + }, + { + name: 'AWS', + color: 'bg-[#FF9F59]', + borderColor: 'border-[#EF6703]', + }, + { + name: 'Docker', + color: 'bg-[#B8E0FF]', + borderColor: 'border-[#2596ED]', + }, + { + name: 'Node-RED', + color: 'bg-[#FF7474]', + borderColor: 'border-[#8F0101]', + }, + { + name: 'Maven', + color: 'bg-[#FF6B80]', + borderColor: 'border-[#CA1A33]', + }, + { + name: 'Saas', + color: 'bg-[#6AB8EC]', + borderColor: 'border-[#2275AD]', + }, + { + name: 'Kubernetes-native', + color: 'bg-[#D7C7F2]', + borderColor: 'border-[#A387D2]', + }, + { + name: 'Scala', + color: 'bg-[#D7C7F2]', + borderColor: 'border-[#A387D2]', + }, + { + name: 'Azure', + color: 'bg-[#4B93FF]', + borderColor: 'border-[#015ADF]', + }, + { + name: 'Jenkins', + color: 'bg-[#D7C7F2]', + borderColor: 'border-[#A387D2]', + }, + { + name: 'Flask', + color: 'bg-[#D7C7F2]', + borderColor: 'border-[#A387D2]', + }, + { + name: 'Nest Js', + color: 'bg-[#E1224E]', + borderColor: 'border-[#B9012b]', + }, +]; -module.exports = {languagesColor, technologiesColor} \ No newline at end of file +module.exports = { languagesColor, technologiesColor }; diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index e5a30334f7d3..9ef57e5cab31 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -1,50 +1,58 @@ -const schema = require("./tools-schema.json"); -const axios = require('axios') -const Ajv = require("ajv") -const addFormats = require("ajv-formats") -const Fuse = require("fuse.js") -const { categoryList } = require("./categorylist") -const ajv = new Ajv() -addFormats(ajv, ["uri"]) -const validate = ajv.compile(schema) +const schema = require('./tools-schema.json'); +const axios = require('axios'); +const Ajv = require('ajv'); +const addFormats = require('ajv-formats'); +const Fuse = require('fuse.js'); +const { categoryList } = require('./categorylist'); +const ajv = new Ajv(); +addFormats(ajv, ['uri']); +const validate = ajv.compile(schema); const { convertToJson } = require('../utils'); - // Config options set for the Fuse object const options = { includeScore: true, shouldSort: true, threshold: 0.4, - keys: ["tag"] -} + keys: ['tag'], +}; -const fuse = new Fuse(categoryList, options) +const fuse = new Fuse(categoryList, options); -// using the contents of each toolFile (extracted from Github), along with Github URL -// (repositoryUrl) of the tool, it's repository description (repoDescription) and -// isAsyncAPIrepo boolean variable to define whether the tool repository is under -// AsyncAPI organization or not, to create a JSON tool object as required in the frontend +// using the contents of each toolFile (extracted from Github), along with Github URL +// (repositoryUrl) of the tool, it's repository description (repoDescription) and +// isAsyncAPIrepo boolean variable to define whether the tool repository is under +// AsyncAPI organization or not, to create a JSON tool object as required in the frontend // side to show ToolCard. -const createToolObject = async (toolFile, repositoryUrl='', repoDescription='', isAsyncAPIrepo='') => { +const createToolObject = async ( + toolFile, + repositoryUrl = '', + repoDescription = '', + isAsyncAPIrepo = '', +) => { let resultantObject = { title: toolFile.title, description: toolFile?.description ? toolFile.description : repoDescription, links: { ...toolFile.links, - repoUrl: toolFile?.links?.repoUrl ? toolFile.links.repoUrl : repositoryUrl + repoUrl: toolFile?.links?.repoUrl + ? toolFile.links.repoUrl + : repositoryUrl, }, filters: { ...toolFile.filters, - hasCommercial: toolFile?.filters?.hasCommercial ? toolFile.filters.hasCommercial : false, - isAsyncAPIOwner: isAsyncAPIrepo - } + hasCommercial: toolFile?.filters?.hasCommercial + ? toolFile.filters.hasCommercial + : false, + isAsyncAPIOwner: isAsyncAPIrepo, + }, }; return resultantObject; }; -// Each result obtained from the Github API call will be tested and verified +// Each result obtained from the Github API call will be tested and verified // using the defined JSON schema, categorising each tool inside their defined categories -// and creating a JSON tool object in which all the tools are listed in defined +// and creating a JSON tool object in which all the tools are listed in defined // categories order, which is then updated in `automated-tools.json` file. async function convertTools(data) { let finalToolsObject = {}; @@ -54,7 +62,7 @@ async function convertTools(data) { for (var index in categoryList) { finalToolsObject[categoryList[index].name] = { description: categoryList[index].description, - toolsList: [] + toolsList: [], }; } @@ -64,50 +72,70 @@ async function convertTools(data) { // extracting the reference id of the repository which will be used to extract the path of the .asyncapi-tool file in the Tools repository // ex: for a url = "https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873" // the text (id) present after '=' gives us a reference id for the repo - let reference_id = tool.url.split("=")[1]; + let reference_id = tool.url.split('=')[1]; let download_url = `https://raw.githubusercontent.com/${tool.repository.full_name}/${reference_id}/${tool.path}`; const { data: toolFileContent } = await axios.get(download_url); //some stuff can be YAML - const jsonToolFileContent = await convertToJson(toolFileContent) + const jsonToolFileContent = await convertToJson(toolFileContent); //validating against JSON Schema for tools file - const isValid = await validate(jsonToolFileContent) + const isValid = await validate(jsonToolFileContent); if (isValid) { let repositoryUrl = tool.repository.html_url; let repoDescription = tool.repository.description; - let isAsyncAPIrepo = tool.repository.owner.login === "asyncapi"; - let toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); + let isAsyncAPIrepo = tool.repository.owner.login === 'asyncapi'; + let toolObject = await createToolObject( + jsonToolFileContent, + repositoryUrl, + repoDescription, + isAsyncAPIrepo, + ); // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object jsonToolFileContent.filters.categories.forEach(async (category) => { const categorySearch = await fuse.search(category); if (categorySearch.length) { - let searchedCategoryName = categorySearch[0].item.name - if (!finalToolsObject[searchedCategoryName].toolsList.find((element => element === toolObject))) - finalToolsObject[searchedCategoryName].toolsList.push(toolObject); + let searchedCategoryName = categorySearch[0].item.name; + if ( + !finalToolsObject[searchedCategoryName].toolsList.find( + (element) => element === toolObject, + ) + ) + finalToolsObject[searchedCategoryName].toolsList.push( + toolObject, + ); } else { // if Tool object has a category, not defined in our categorylist, then this provides a `other` category to the tool. - if (!finalToolsObject['Others'].toolsList.find((element => element === toolObject))) + if ( + !finalToolsObject['Others'].toolsList.find( + (element) => element === toolObject, + ) + ) finalToolsObject['Others'].toolsList.push(toolObject); } }); } else { - console.error('Script is not failing, it is just dropping errors for further investigation'); + console.error( + 'Script is not failing, it is just dropping errors for further investigation', + ); console.error('Invalid .asyncapi-tool file.'); console.error(`Located in: ${tool.html_url}`); - console.error('Validation errors:', JSON.stringify(validate.errors, null, 2)); + console.error( + 'Validation errors:', + JSON.stringify(validate.errors, null, 2), + ); } } } catch (err) { - console.error(err) + console.error(err); throw err; } } return finalToolsObject; } -module.exports = {convertTools, createToolObject} \ No newline at end of file +module.exports = { convertTools, createToolObject }; diff --git a/scripts/tools/tools-schema.json b/scripts/tools/tools-schema.json index e11968a1b2e1..74bcb3d783b4 100644 --- a/scripts/tools/tools-schema.json +++ b/scripts/tools/tools-schema.json @@ -1,220 +1,209 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "JSON Schema for AsyncAPI tool discovery file.", - "type": "object", - "additionalProperties": false, - "required": [ - "title", - "filters" - ], - "properties": { - "title": { - "type": "string", - "description": "Human-readable name of the tool that will be visible to people in the list of tools.", - "examples": [ - "AsyncAPI Generator", - "Cupid" - ] + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema for AsyncAPI tool discovery file.", + "type": "object", + "additionalProperties": false, + "required": ["title", "filters"], + "properties": { + "title": { + "type": "string", + "description": "Human-readable name of the tool that will be visible to people in the list of tools.", + "examples": ["AsyncAPI Generator", "Cupid"] + }, + "description": { + "type": "string", + "description": "By default scripts read description of repository there project is stored. You can override this behaviour by providing custom description." + }, + "links": { + "type": "object", + "additionalProperties": false, + "properties": { + "websiteUrl": { + "type": "string", + "description": "You can provide URL to the website where your project hosts some demo or project landing page.", + "format": "uri" }, - "description": { - "type": "string", - "description": "By default scripts read description of repository there project is stored. You can override this behaviour by providing custom description." + "docsUrl": { + "type": "string", + "description": "You can provide URL to project documentation in case you have more than just a readme file.", + "format": "uri" }, - "links": { - "type": "object", - "additionalProperties": false, - "properties": { - "websiteUrl": { - "type": "string", - "description": "You can provide URL to the website where your project hosts some demo or project landing page.", - "format": "uri" - }, - "docsUrl": { - "type": "string", - "description": "You can provide URL to project documentation in case you have more than just a readme file.", - "format": "uri" + "repoUrl": { + "type": "string", + "description": "You can provide URL to project codebase in case you have more than one tool present inside single repository.", + "format": "uri" + } + } + }, + "filters": { + "type": "object", + "additionalProperties": false, + "required": ["categories"], + "properties": { + "language": { + "description": "The language referred to is the runtime language selected by the user, not the generator or library language. For example, the Generator written in JavaScript generates Python code from the JavaScript template and the result of generation is a Python app, so the language for Generator is specified as Python. But for the Bundler library, users need to know if it can be integrated into their TypeScript codebase, so its language is specified as TypeScript. If some language in the schema's enum is omitted, it can be added through a pull request to the AsyncAPI website repository.", + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "type": "string", + "enum": [ + "Go", + "Java", + "JavaScript", + "HTML", + "C/C++", + "C#", + "Python", + "TypeScript", + "Kotlin", + "Scala", + "Markdown", + "YAML", + "R", + "Ruby", + "Rust", + "Shell", + "Groovy" + ] }, - "repoUrl": { - "type": "string", - "description": "You can provide URL to project codebase in case you have more than one tool present inside single repository.", - "format": "uri" + { + "type": "string" } - } - }, - "filters": { - "type": "object", - "additionalProperties": false, - "required": [ - "categories" - ], - "properties": { - "language": { - "description": "The language referred to is the runtime language selected by the user, not the generator or library language. For example, the Generator written in JavaScript generates Python code from the JavaScript template and the result of generation is a Python app, so the language for Generator is specified as Python. But for the Bundler library, users need to know if it can be integrated into their TypeScript codebase, so its language is specified as TypeScript. If some language in the schema's enum is omitted, it can be added through a pull request to the AsyncAPI website repository.", - "anyOf": [ - { - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": [ - "Go", - "Java", - "JavaScript", - "HTML", - "C/C++", - "C#", - "Python", - "TypeScript", - "Kotlin", - "Scala", - "Markdown", - "YAML", - "R", - "Ruby", - "Rust", - "Shell", - "Groovy" - ] - }, - { - "type": "string" - } - ] - }, - { - "type": "array", - "items": { - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": [ - "Go", - "Java", - "JavaScript", - "HTML", - "C/C++", - "C#", - "Python", - "TypeScript", - "Kotlin", - "Scala", - "Markdown", - "YAML", - "R", - "Ruby", - "Rust", - "Shell", - "Groovy" - ] - }, - { - "type": "string" - } - ] - } - } - ] - }, - "technology": { - "type": "array", - "description": "Provide a list of different technologies used in the tool. Put details useful for tool user and tool contributor.", - "items": { - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": [ - "Node js", - "Hermes", - "React JS", - ".NET", - "ASP.NET", - "Springboot", - "AWS", - "Docker", - "Node-red", - "Maven", - "Saas", - "Kubernetes-native", - "Scala", - "Azure", - "Jenkins", - "Flask" - ] - }, - { - "type": "string" - } - ] - }, - "examples": [ - "Express.js", - "Kafka" - ] - }, - "categories": { - "type": "array", - "description": "Categories are used to group tools by different use case, like documentation or code generation. If have a list of fixed categories. If you use different one that your tool lands under \"other\" category. Feel free to add your category through a pull request to AsyncAPI website repository.", - "items": { - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": [ - "api", - "code-first", - "code-generator", - "converter", - "directory", - "documentation-generator", - "editor", - "ui-component", - "dsl", - "framework", - "github-action", - "mocking-and-testing", - "validator", - "compare-tool", - "other", - "cli", - "bundler", - "ide-extension" - ] - }, - { - "type": "string" - } - ] - }, - "minItems": 1, - "examples": [ - "api", - "code-first", - "code-generator", - "converter", - "directory", - "documentation-generator", - "editor", - "ui-component", - "dsl", - "framework", - "github-action", - "mocking-and-testing", - "validator", - "compare-tool", - "other", - "cli", - "bundler", - "ide-extension" + ] + }, + { + "type": "array", + "items": { + "type": "string", + "anyOf": [ + { + "type": "string", + "enum": [ + "Go", + "Java", + "JavaScript", + "HTML", + "C/C++", + "C#", + "Python", + "TypeScript", + "Kotlin", + "Scala", + "Markdown", + "YAML", + "R", + "Ruby", + "Rust", + "Shell", + "Groovy" ] - }, - "hasCommercial": { - "type": "boolean", - "description": "Indicate if your tool is open source or commercial offering, like SAAS for example", - "default": false - } + }, + { + "type": "string" + } + ] + } } + ] + }, + "technology": { + "type": "array", + "description": "Provide a list of different technologies used in the tool. Put details useful for tool user and tool contributor.", + "items": { + "type": "string", + "anyOf": [ + { + "type": "string", + "enum": [ + "Node js", + "Hermes", + "React JS", + ".NET", + "ASP.NET", + "Springboot", + "AWS", + "Docker", + "Node-red", + "Maven", + "Saas", + "Kubernetes-native", + "Scala", + "Azure", + "Jenkins", + "Flask" + ] + }, + { + "type": "string" + } + ] + }, + "examples": ["Express.js", "Kafka"] + }, + "categories": { + "type": "array", + "description": "Categories are used to group tools by different use case, like documentation or code generation. If have a list of fixed categories. If you use different one that your tool lands under \"other\" category. Feel free to add your category through a pull request to AsyncAPI website repository.", + "items": { + "type": "string", + "anyOf": [ + { + "type": "string", + "enum": [ + "api", + "code-first", + "code-generator", + "converter", + "directory", + "documentation-generator", + "editor", + "ui-component", + "dsl", + "framework", + "github-action", + "mocking-and-testing", + "validator", + "compare-tool", + "other", + "cli", + "bundler", + "ide-extension" + ] + }, + { + "type": "string" + } + ] + }, + "minItems": 1, + "examples": [ + "api", + "code-first", + "code-generator", + "converter", + "directory", + "documentation-generator", + "editor", + "ui-component", + "dsl", + "framework", + "github-action", + "mocking-and-testing", + "validator", + "compare-tool", + "other", + "cli", + "bundler", + "ide-extension" + ] + }, + "hasCommercial": { + "type": "boolean", + "description": "Indicate if your tool is open source or commercial offering, like SAAS for example", + "default": false } + } } -} \ No newline at end of file + } +} diff --git a/scripts/utils.js b/scripts/utils.js index c740ae91eaef..66d01b75afc7 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -1,26 +1,28 @@ const yaml = require('yaml'); function convertToJson(contentYAMLorJSON) { - // Axios handles conversion to JSON by default, if data returned from the server allows it - // So if returned content is not a string (not YAML), we just return JSON back - if (typeof contentYAMLorJSON !== "string") { - return contentYAMLorJSON; - } + // Axios handles conversion to JSON by default, if data returned from the server allows it + // So if returned content is not a string (not YAML), we just return JSON back + if (typeof contentYAMLorJSON !== 'string') { + return contentYAMLorJSON; + } - // Check if the content is valid JSON before attempting to parse as YAML + // Check if the content is valid JSON before attempting to parse as YAML + try { + const jsonContent = JSON.parse(contentYAMLorJSON); + return jsonContent; + } catch (jsonError) { + // If it's not valid JSON, try parsing it as YAML try { - const jsonContent = JSON.parse(contentYAMLorJSON); - return jsonContent; - } catch (jsonError) { - // If it's not valid JSON, try parsing it as YAML - try { - const yamlContent = yaml.parse(contentYAMLorJSON); - return yamlContent; - } catch (yamlError) { - // If parsing as YAML also fails, throw an error - throw new Error(`Invalid content format:\nJSON Parse Error: ${jsonError}\nYAML Parse Error: ${yamlError}`); - } + const yamlContent = yaml.parse(contentYAMLorJSON); + return yamlContent; + } catch (yamlError) { + // If parsing as YAML also fails, throw an error + throw new Error( + `Invalid content format:\nJSON Parse Error: ${jsonError}\nYAML Parse Error: ${yamlError}`, + ); } + } } module.exports = { convertToJson }; diff --git a/scripts/utils/readAndWriteJson.js b/scripts/utils/readAndWriteJson.js index 3c7f05d2308b..d1ed2dd43a12 100644 --- a/scripts/utils/readAndWriteJson.js +++ b/scripts/utils/readAndWriteJson.js @@ -1,28 +1,30 @@ -const { promises: { readFile, writeFile } } = require('fs'); -const { convertToJson } = require("../utils"); +const { + promises: { readFile, writeFile }, +} = require('fs'); +const { convertToJson } = require('../utils'); module.exports = async function writeJSON(readPath, writePath) { - let readContent; - let jsonContent; + let readContent; + let jsonContent; - // Attempt to read the file - try { - readContent = await readFile(readPath, 'utf-8'); - } catch (err) { - throw new Error(`Error while reading file\nError: ${err}`); - } + // Attempt to read the file + try { + readContent = await readFile(readPath, 'utf-8'); + } catch (err) { + throw new Error(`Error while reading file\nError: ${err}`); + } - // Attempt to convert content to JSON - try { - jsonContent = convertToJson(readContent); - } catch (err) { - throw new Error(`Error while conversion\nError: ${err}`); - } + // Attempt to convert content to JSON + try { + jsonContent = convertToJson(readContent); + } catch (err) { + throw new Error(`Error while conversion\nError: ${err}`); + } - // Attempt to write the JSON content to file - try { - await writeFile(writePath, JSON.stringify(jsonContent)); - } catch (err) { - throw new Error(`Error while writing file\nError: ${err}`); - } -}; \ No newline at end of file + // Attempt to write the JSON content to file + try { + await writeFile(writePath, JSON.stringify(jsonContent)); + } catch (err) { + throw new Error(`Error while writing file\nError: ${err}`); + } +}; From 2badba708c2dc63498e9ea71bae30e84b748ae7a Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Sat, 16 Nov 2024 15:04:44 +0530 Subject: [PATCH 2/2] format using prettier --- scripts/adopters/index.js | 5 +- scripts/build-docs.js | 67 +++++++++------------ scripts/build-meetings.js | 23 +++---- scripts/build-newsroom-videos.js | 21 +++---- scripts/build-post-list.js | 87 ++++++++------------------- scripts/build-rss.js | 18 ++---- scripts/build-tools.js | 33 +++------- scripts/casestudies/index.js | 13 ++-- scripts/compose.js | 33 ++++------ scripts/dashboard/build-dashboard.js | 75 ++++++++--------------- scripts/dashboard/issue-queries.js | 2 +- scripts/finance/index.js | 33 ++-------- scripts/index.js | 14 +---- scripts/markdown/check-markdown.js | 18 +----- scripts/tools/categorylist.js | 53 ++++++---------- scripts/tools/combine-tools.js | 82 ++++++++++--------------- scripts/tools/extract-tools-github.js | 15 ++--- scripts/tools/tags-color.js | 72 +++++++++++----------- scripts/tools/tools-object.js | 81 +++++++++---------------- scripts/utils.js | 4 +- scripts/utils/readAndWriteJson.js | 2 +- 21 files changed, 261 insertions(+), 490 deletions(-) diff --git a/scripts/adopters/index.js b/scripts/adopters/index.js index ef6643802d62..a8c8363d25ab 100644 --- a/scripts/adopters/index.js +++ b/scripts/adopters/index.js @@ -2,8 +2,5 @@ const { resolve } = require('path'); const writeJSON = require('../utils/readAndWriteJson.js'); module.exports = async function buildAdoptersList() { - writeJSON( - 'config/adopters.yml', - resolve(__dirname, '../../config', 'adopters.json'), - ); + writeJSON('config/adopters.yml', resolve(__dirname, '../../config', 'adopters.json')); }; diff --git a/scripts/build-docs.js b/scripts/build-docs.js index e1aff2f99cd1..48693f176ba8 100644 --- a/scripts/build-docs.js +++ b/scripts/build-docs.js @@ -1,4 +1,5 @@ const sortBy = require('lodash/sortBy'); + function buildNavTree(navItems) { try { const tree = { @@ -10,42 +11,36 @@ function buildNavTree(navItems) { isSection: true, rootSectionId: 'welcome', sectionWeight: 0, - slug: '/docs', + slug: '/docs' }, - children: {}, - }, + children: {} + } }; - //first we make sure that list of items lists main section items and then sub sections, documents last - const sortedItems = sortBy(navItems, [ - 'isRootSection', - 'weight', - 'isSection', - ]); + // first we make sure that list of items lists main section items and then sub sections, documents last + const sortedItems = sortBy(navItems, ['isRootSection', 'weight', 'isSection']); sortedItems.forEach((item) => { - //identify main sections + // identify main sections if (item.isRootSection) { tree[item.rootSectionId] = { item, children: {} }; } - //identify subsections + // identify subsections if (item.parent) { if (!tree[item.parent]) { - throw new Error( - `Parent section ${item.parent} not found for item ${item.title}`, - ); + throw new Error(`Parent section ${item.parent} not found for item ${item.title}`); } tree[item.parent].children[item.sectionId] = { item, children: [] }; } if (!item.isSection) { if (item.sectionId) { - let section = tree[item.rootSectionId]?.children[item.sectionId]; + const section = tree[item.rootSectionId]?.children[item.sectionId]; if (!section) { tree[item.rootSectionId].children[item.sectionId] = { item, - children: [], + children: [] }; } tree[item.rootSectionId].children[item.sectionId].children.push(item); @@ -68,7 +63,7 @@ function buildNavTree(navItems) { return obj; }, {}); - //handling subsections + // handling subsections if (allChildrenKeys.length > 1) { for (const key of allChildrenKeys) { if (allChildren[key].children) { @@ -79,9 +74,7 @@ function buildNavTree(navItems) { // point in slug for specification subgroup to the latest specification version if (rootKey === 'reference' && key === 'specification') { - allChildren[key].item.href = allChildren[key].children.find( - (c) => c.isPrerelease === undefined, - ).slug; + allChildren[key].item.href = allChildren[key].children.find((c) => c.isPrerelease === undefined).slug; } } } @@ -101,9 +94,9 @@ const convertDocPosts = (docObject) => { // certain entries in the DocPosts are either a parent to many posts or itself a post. docsArray.push(docObject?.item || docObject); if (docObject.children) { - let children = docObject.children; + const { children } = docObject; Object.keys(children).forEach((child) => { - let docChildArray = convertDocPosts(children[child]); + const docChildArray = convertDocPosts(children[child]); docsArray = [...docsArray, ...docChildArray]; }); } @@ -115,16 +108,16 @@ const convertDocPosts = (docObject) => { function addDocButtons(docPosts, treePosts) { let structuredPosts = []; - let rootSections = []; + const rootSections = []; try { // Traversing the whole DocTree and storing each post inside them in sequential order Object.keys(treePosts).forEach((rootElement) => { structuredPosts.push(treePosts[rootElement].item); if (treePosts[rootElement].children) { - let children = treePosts[rootElement].children; + const { children } = treePosts[rootElement]; Object.keys(children).forEach((child) => { - let docChildArray = convertDocPosts(children[child]); + const docChildArray = convertDocPosts(children[child]); structuredPosts = [...structuredPosts, ...docChildArray]; }); } @@ -134,7 +127,7 @@ function addDocButtons(docPosts, treePosts) { structuredPosts[0] = docPosts.filter((p) => p.slug === '/docs')[0]; // Traversing the structuredPosts in order to add `nextPage` and `prevPage` details for each page - let countDocPages = structuredPosts.length; + const countDocPages = structuredPosts.length; structuredPosts = structuredPosts.map((post, index) => { // post item specifying the root Section or sub-section in the docs are excluded as // they doesn't comprise any Doc Page or content to be shown in website. @@ -143,26 +136,23 @@ function addDocButtons(docPosts, treePosts) { return post; } - let nextPage = {}, - prevPage = {}; + let nextPage = {}; + let prevPage = {}; let docPost = post; // checks whether the next page for the current docPost item exists or not if (index + 1 < countDocPages) { // checks whether the next item inside structuredPosts is a rootElement or a sectionElement // if yes, it goes again to a next to next item in structuredPosts to link the nextPage - if ( - !structuredPosts[index + 1].isRootElement && - !structuredPosts[index + 1].isSection - ) { + if (!structuredPosts[index + 1].isRootElement && !structuredPosts[index + 1].isSection) { nextPage = { title: structuredPosts[index + 1].title, - href: structuredPosts[index + 1].slug, + href: structuredPosts[index + 1].slug }; } else { nextPage = { title: `${structuredPosts[index + 1].title} - ${structuredPosts[index + 2].title}`, - href: structuredPosts[index + 2].slug, + href: structuredPosts[index + 2].slug }; } docPost = { ...docPost, nextPage }; @@ -172,13 +162,10 @@ function addDocButtons(docPosts, treePosts) { if (index > 0) { // checks whether the previous item inside structuredPosts is a rootElement or a sectionElement // if yes, it goes again to a next previous item in structuredPosts to link the prevPage - if ( - !structuredPosts[index - 1]?.isRootElement && - !structuredPosts[index - 1]?.isSection - ) { + if (!structuredPosts[index - 1]?.isRootElement && !structuredPosts[index - 1]?.isSection) { prevPage = { title: structuredPosts[index - 1].title, - href: structuredPosts[index - 1].slug, + href: structuredPosts[index - 1].slug }; docPost = { ...docPost, prevPage }; } else { @@ -186,7 +173,7 @@ function addDocButtons(docPosts, treePosts) { if (index - 2 >= 0) { prevPage = { title: `${structuredPosts[index - 1]?.isRootSection ? rootSections[rootSections.length - 2] : rootSections[rootSections.length - 1]} - ${structuredPosts[index - 2].title}`, - href: structuredPosts[index - 2].slug, + href: structuredPosts[index - 2].slug }; docPost = { ...docPost, prevPage }; } diff --git a/scripts/build-meetings.js b/scripts/build-meetings.js index cc56c0d026b8..ac556b7578d4 100644 --- a/scripts/build-meetings.js +++ b/scripts/build-meetings.js @@ -9,9 +9,7 @@ async function buildMeetings(writePath) { try { auth = new google.auth.GoogleAuth({ scopes: ['https://www.googleapis.com/auth/calendar'], - credentials: process.env.CALENDAR_SERVICE_ACCOUNT - ? JSON.parse(process.env.CALENDAR_SERVICE_ACCOUNT) - : undefined, + credentials: process.env.CALENDAR_SERVICE_ACCOUNT ? JSON.parse(process.env.CALENDAR_SERVICE_ACCOUNT) : undefined }); calendar = google.calendar({ version: 'v3', auth }); @@ -22,19 +20,15 @@ async function buildMeetings(writePath) { let eventsItems; try { - //cron job runs this always on midnight + // cron job runs this always on midnight const currentTime = new Date(Date.now()).toISOString(); - const timeMin = new Date( - Date.parse(currentTime) - 100 * 24 * 60 * 60 * 1000, - ).toISOString(); - const timeMax = new Date( - Date.parse(currentTime) + 30 * 24 * 60 * 60 * 1000, - ).toISOString(); + const timeMin = new Date(Date.parse(currentTime) - 100 * 24 * 60 * 60 * 1000).toISOString(); + const timeMax = new Date(Date.parse(currentTime) + 30 * 24 * 60 * 60 * 1000).toISOString(); const eventsList = await calendar.events.list({ calendarId: process.env.CALENDAR_ID, - timeMax: timeMax, - timeMin: timeMin, + timeMax, + timeMin }); eventsItems = eventsList.data.items.map((e) => { @@ -44,9 +38,8 @@ async function buildMeetings(writePath) { url: e.extendedProperties?.private && `https://github.com/asyncapi/community/issues/${e.extendedProperties.private.ISSUE_ID}`, - banner: - e.extendedProperties?.private && e.extendedProperties.private.BANNER, - date: new Date(e.start.dateTime), + banner: e.extendedProperties?.private && e.extendedProperties.private.BANNER, + date: new Date(e.start.dateTime) }; }); diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index 496eba2de769..40ad1617362e 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -5,16 +5,15 @@ const fetch = require('node-fetch-2'); async function buildNewsroomVideos(writePath) { try { const response = await fetch( - 'https://youtube.googleapis.com/youtube/v3/search?' + - new URLSearchParams({ - key: process.env.YOUTUBE_TOKEN, - part: 'snippet', - channelId: 'UCIz9zGwDLbrYQcDKVXdOstQ', - eventType: 'completed', - type: 'video', - order: 'Date', - maxResults: 5, - }), + `https://youtube.googleapis.com/youtube/v3/search?${new URLSearchParams({ + key: process.env.YOUTUBE_TOKEN, + part: 'snippet', + channelId: 'UCIz9zGwDLbrYQcDKVXdOstQ', + eventType: 'completed', + type: 'video', + order: 'Date', + maxResults: 5 + })}` ); if (!response.ok) { @@ -32,7 +31,7 @@ async function buildNewsroomVideos(writePath) { image_url: video.snippet.thumbnails.high.url, title: video.snippet.title, description: video.snippet.description, - videoId: video.id.videoId, + videoId: video.id.videoId })); const videoData = JSON.stringify(videoDataItems, null, ' '); diff --git a/scripts/build-post-list.js b/scripts/build-post-list.js index dc249c6e2a43..3cfee35032ec 100644 --- a/scripts/build-post-list.js +++ b/scripts/build-post-list.js @@ -1,10 +1,4 @@ -const { - readdirSync, - statSync, - existsSync, - readFileSync, - writeFileSync, -} = require('fs'); +const { readdirSync, statSync, existsSync, readFileSync, writeFileSync } = require('fs'); const { resolve, basename } = require('path'); const frontMatter = require('gray-matter'); const toc = require('markdown-toc'); @@ -18,7 +12,7 @@ const result = { docs: [], blog: [], about: [], - docsTree: {}, + docsTree: {} }; const releaseNotes = []; const basePath = 'pages'; @@ -26,47 +20,35 @@ const postDirectories = [ // order of these directories is important, as the blog should come before docs, to create a list of available release notes, which will later be used to release-note-link for spec docs [`${basePath}/blog`, '/blog'], [`${basePath}/docs`, '/docs'], - [`${basePath}/about`, '/about'], + [`${basePath}/about`, '/about'] ]; const addItem = (details) => { - if (details.slug.startsWith('/docs')) result['docs'].push(details); - else if (details.slug.startsWith('/blog')) result['blog'].push(details); - else if (details.slug.startsWith('/about')) result['about'].push(details); + if (details.slug.startsWith('/docs')) result.docs.push(details); + else if (details.slug.startsWith('/blog')) result.blog.push(details); + else if (details.slug.startsWith('/about')) result.about.push(details); else { } }; module.exports = async function buildPostList() { walkDirectories(postDirectories, result); - const treePosts = buildNavTree( - result['docs'].filter((p) => p.slug.startsWith('/docs/')), - ); - result['docsTree'] = treePosts; - result['docs'] = addDocButtons(result['docs'], treePosts); + const treePosts = buildNavTree(result.docs.filter((p) => p.slug.startsWith('/docs/'))); + result.docsTree = treePosts; + result.docs = addDocButtons(result.docs, treePosts); if (process.env.NODE_ENV === 'production') { // console.log(inspect(result, { depth: null, colors: true })) } - writeFileSync( - resolve(__dirname, '..', 'config', 'posts.json'), - JSON.stringify(result, null, ' '), - ); + writeFileSync(resolve(__dirname, '..', 'config', 'posts.json'), JSON.stringify(result, null, ' ')); }; -function walkDirectories( - directories, - result, - sectionWeight = 0, - sectionTitle, - sectionId, - rootSectionId, -) { - for (let dir of directories) { - let directory = dir[0]; - let sectionSlug = dir[1] || ''; - let files = readdirSync(directory); +function walkDirectories(directories, result, sectionWeight = 0, sectionTitle, sectionId, rootSectionId) { + for (const dir of directories) { + const directory = dir[0]; + const sectionSlug = dir[1] || ''; + const files = readdirSync(directory); - for (let file of files) { + for (const file of files) { let details; const fileName = [directory, file].join('/'); const fileNameWithSection = [fileName, '_section.mdx'].join('/'); @@ -75,14 +57,11 @@ function walkDirectories( if (isDirectory(fileName)) { if (existsSync(fileNameWithSection)) { // Passing a second argument to frontMatter disables cache. See https://github.com/asyncapi/website/issues/1057 - details = frontMatter( - readFileSync(fileNameWithSection, 'utf-8'), - {}, - ).data; + details = frontMatter(readFileSync(fileNameWithSection, 'utf-8'), {}).data; details.title = details.title || capitalize(basename(fileName)); } else { details = { - title: capitalize(basename(fileName)), + title: capitalize(basename(fileName)) }; } details.isSection = true; @@ -98,14 +77,7 @@ function walkDirectories( details.slug = slug; addItem(details); const rootId = details.parent || details.rootSectionId; - walkDirectories( - [[fileName, slug]], - result, - details.weight, - details.title, - details.sectionId, - rootId, - ); + walkDirectories([[fileName, slug]], result, details.weight, details.title, details.sectionId, rootId); } else if (file.endsWith('.mdx') && !fileName.endsWith('/_section.mdx')) { const fileContent = readFileSync(fileName, 'utf-8'); // Passing a second argument to frontMatter disables cache. See https://github.com/asyncapi/website/issues/1057 @@ -113,8 +85,7 @@ function walkDirectories( details = data; details.toc = toc(content, { slugify: slugifyToC }).json; details.readingTime = Math.ceil(readingTime(content).minutes); - details.excerpt = - details.excerpt || markdownToTxt(content).substr(0, 200); + details.excerpt = details.excerpt || markdownToTxt(content).substr(0, 200); details.sectionSlug = sectionSlug || slug.replace(/\.mdx$/, ''); details.sectionWeight = sectionWeight; details.sectionTitle = sectionTitle; @@ -122,13 +93,8 @@ function walkDirectories( details.rootSectionId = rootSectionId; details.id = fileName; details.isIndex = fileName.endsWith('/index.mdx'); - details.slug = details.isIndex - ? sectionSlug - : slug.replace(/\.mdx$/, ''); - if ( - details.slug.includes('/reference/specification/') && - !details.title - ) { + details.slug = details.isIndex ? sectionSlug : slug.replace(/\.mdx$/, ''); + if (details.slug.includes('/reference/specification/') && !details.title) { const fileBaseName = basename(data.slug); // ex. v2.0.0 | v2.1.0-next-spec.1 const fileName = fileBaseName.split('-')[0]; // v2.0.0 | v2.1.0 details.weight = specWeight--; @@ -143,10 +109,7 @@ function walkDirectories( details.releaseNoteLink = `/blog/release-notes-${details.title}`; } - if ( - fileBaseName.includes('next-spec') || - fileBaseName.includes('next-major-spec') - ) { + if (fileBaseName.includes('next-spec') || fileBaseName.includes('next-major-spec')) { details.isPrerelease = true; // this need to be separate because the `-` in "Pre-release" will get removed by `capitalize()` function details.title += ' (Pre-release)'; @@ -160,9 +123,7 @@ function walkDirectories( if (file.startsWith('release-notes') && dir[1] === '/blog') { const fileName_without_extension = file.slice(0, -4); // removes the file extension. For example, release-notes-2.1.0.md -> release-notes-2.1.0 - const version = fileName_without_extension.slice( - fileName_without_extension.lastIndexOf('-') + 1, - ); + const version = fileName_without_extension.slice(fileName_without_extension.lastIndexOf('-') + 1); // gets the version from the name of the releaseNote .md file (from /blog). For example, version = 2.1.0 if fileName_without_extension = release-notes-2.1.0 releaseNotes.push(version); diff --git a/scripts/build-rss.js b/scripts/build-rss.js index 46c668119c6a..75195ea53ccf 100644 --- a/scripts/build-rss.js +++ b/scripts/build-rss.js @@ -29,9 +29,7 @@ module.exports = async function rssFeed(type, title, desc, outputPath) { }); if (missingDatePosts.length > 0) { - throw new Error( - `Missing date in posts: ${missingDatePosts.map((p) => p.title || p.slug).join(', ')}`, - ); + throw new Error(`Missing date in posts: ${missingDatePosts.map((p) => p.title || p.slug).join(', ')}`); } const base = 'https://www.asyncapi.com'; @@ -56,17 +54,13 @@ module.exports = async function rssFeed(type, title, desc, outputPath) { rss.channel.generator = 'next.js'; rss.channel.item = []; - const invalidPosts = posts.filter( - (post) => !post.title || !post.slug || !post.excerpt || !post.date, - ); + const invalidPosts = posts.filter((post) => !post.title || !post.slug || !post.excerpt || !post.date); if (invalidPosts.length > 0) { - throw new Error( - `Missing required fields in posts: ${invalidPosts.map((p) => p.title || p.slug).join(', ')}`, - ); + throw new Error(`Missing required fields in posts: ${invalidPosts.map((p) => p.title || p.slug).join(', ')}`); } - for (let post of posts) { + for (const post of posts) { const link = `${base}${post.slug}${tracking}`; const { title, excerpt, date } = post; const pubDate = new Date(date).toUTCString(); @@ -78,7 +72,7 @@ module.exports = async function rssFeed(type, title, desc, outputPath) { link, category: type, guid, - pubDate, + pubDate }; if (post.cover) { const enclosure = {}; @@ -86,7 +80,7 @@ module.exports = async function rssFeed(type, title, desc, outputPath) { enclosure['@length'] = 15026; // dummy value, anything works enclosure['@type'] = 'image/jpeg'; if (typeof enclosure['@url'] === 'string') { - let tmp = enclosure['@url'].toLowerCase(); + const tmp = enclosure['@url'].toLowerCase(); if (tmp.indexOf('.png') >= 0) enclosure['@type'] = 'image/png'; if (tmp.indexOf('.svg') >= 0) enclosure['@type'] = 'image/svg+xml'; if (tmp.indexOf('.webp') >= 0) enclosure['@type'] = 'image/webp'; diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 30404a2d015f..83db76534f11 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -1,30 +1,17 @@ +const fs = require('fs-extra'); +const { resolve } = require('path'); const { getData } = require('./tools/extract-tools-github'); const { convertTools } = require('./tools/tools-object'); const { combineTools } = require('./tools/combine-tools'); -const fs = require('fs-extra'); -const { resolve } = require('path'); -const buildTools = async ( - automatedToolsPath, - manualToolsPath, - toolsPath, - tagsPath, -) => { +const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { try { - let githubExtractData = await getData(); - let automatedTools = await convertTools(githubExtractData); + const githubExtractData = await getData(); + const automatedTools = await convertTools(githubExtractData); - await fs.writeFile( - automatedToolsPath, - JSON.stringify(automatedTools, null, ' '), - ); + await fs.writeFile(automatedToolsPath, JSON.stringify(automatedTools, null, ' ')); - await combineTools( - automatedTools, - require(manualToolsPath), - toolsPath, - tagsPath, - ); + await combineTools(automatedTools, require(manualToolsPath), toolsPath, tagsPath); } catch (err) { throw new Error(`An error occurred while building tools: ${err.message}`); } @@ -32,11 +19,7 @@ const buildTools = async ( /* istanbul ignore next */ if (require.main === module) { - const automatedToolsPath = resolve( - __dirname, - '../config', - 'tools-automated.json', - ); + const automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json'); const manualToolsPath = resolve(__dirname, '../config', 'tools-manual.json'); const toolsPath = resolve(__dirname, '../config', 'tools.json'); const tagsPath = resolve(__dirname, '../config', 'all-tags.json'); diff --git a/scripts/casestudies/index.js b/scripts/casestudies/index.js index 3ff9e415f525..22011781f1be 100644 --- a/scripts/casestudies/index.js +++ b/scripts/casestudies/index.js @@ -1,14 +1,11 @@ const { readdir, writeFile, readFile } = require('fs').promises; -const { convertToJson } = require('../../scripts/utils'); +const { convertToJson } = require('../utils'); -module.exports = async function buildCaseStudiesList( - dirWithCaseStudy, - writeFilePath, -) { +module.exports = async function buildCaseStudiesList(dirWithCaseStudy, writeFilePath) { try { - let files = await readdir(dirWithCaseStudy); - let caseStudiesList = []; - for (let file of files) { + const files = await readdir(dirWithCaseStudy); + const caseStudiesList = []; + for (const file of files) { const caseStudyFileName = [dirWithCaseStudy, file].join('/'); const caseStudyContent = await readFile(caseStudyFileName, 'utf-8'); const jsonContent = convertToJson(caseStudyContent); diff --git a/scripts/compose.js b/scripts/compose.js index 00d262019428..18d8d724420d 100644 --- a/scripts/compose.js +++ b/scripts/compose.js @@ -8,15 +8,11 @@ const dedent = require('dedent'); const moment = require('moment'); const genFrontMatter = (answers) => { - let d = new Date(); - const date = [ - d.getFullYear(), - ('0' + (d.getMonth() + 1)).slice(-2), - ('0' + d.getDate()).slice(-2), - ].join('-'); + const d = new Date(); + const date = [d.getFullYear(), `0${d.getMonth() + 1}`.slice(-2), `0${d.getDate()}`.slice(-2)].join('-'); const tagArray = answers.tags.split(','); tagArray.forEach((tag, index) => (tagArray[index] = tag.trim())); - const tags = "'" + tagArray.join("','") + "'"; + const tags = `'${tagArray.join("','")}'`; let frontMatter = dedent`--- title: ${answers.title ? answers.title : 'Untitled'} @@ -92,7 +88,7 @@ const genFrontMatter = (answers) => { `; - frontMatter = frontMatter + '\n---'; + frontMatter += '\n---'; return frontMatter; }; @@ -102,36 +98,29 @@ inquirer { name: 'title', message: 'Enter post title:', - type: 'input', + type: 'input' }, { name: 'excerpt', message: 'Enter post excerpt:', - type: 'input', + type: 'input' }, { name: 'tags', message: 'Any Tags? Separate them with , or leave empty if no tags.', - type: 'input', + type: 'input' }, { name: 'type', message: 'Enter the post type:', type: 'list', - choices: [ - 'Communication', - 'Community', - 'Engineering', - 'Marketing', - 'Strategy', - 'Video', - ], + choices: ['Communication', 'Community', 'Engineering', 'Marketing', 'Strategy', 'Video'] }, { name: 'canonical', message: 'Enter the canonical URL if any:', - type: 'input', - }, + type: 'input' + } ]) .then((answers) => { // Remove special characters and replace space with - @@ -141,7 +130,7 @@ inquirer .replace(/ /g, '-') .replace(/-+/g, '-'); const frontMatter = genFrontMatter(answers); - const filePath = `pages/blog/${fileName ? fileName : 'untitled'}.md`; + const filePath = `pages/blog/${fileName || 'untitled'}.md`; fs.writeFile(filePath, frontMatter, { flag: 'wx' }, (err) => { if (err) { throw err; diff --git a/scripts/dashboard/build-dashboard.js b/scripts/dashboard/build-dashboard.js index cb07d85c2f5f..00e2049a6338 100644 --- a/scripts/dashboard/build-dashboard.js +++ b/scripts/dashboard/build-dashboard.js @@ -20,8 +20,8 @@ async function getDiscussions(query, pageSize, endCursor = null) { first: pageSize, after: endCursor, headers: { - authorization: `token ${process.env.GITHUB_TOKEN}`, - }, + authorization: `token ${process.env.GITHUB_TOKEN}` + } }); if (result.rateLimit.remaining <= 100) { @@ -30,7 +30,7 @@ async function getDiscussions(query, pageSize, endCursor = null) { `cost = ${result.rateLimit.cost}`, `limit = ${result.rateLimit.limit}`, `remaining = ${result.rateLimit.remaining}`, - `resetAt = ${result.rateLimit.resetAt}`, + `resetAt = ${result.rateLimit.resetAt}` ); } @@ -41,9 +41,7 @@ async function getDiscussions(query, pageSize, endCursor = null) { if (!hasNextPage) { return result.search.nodes; } - return result.search.nodes.concat( - await getDiscussions(query, pageSize, result.search.pageInfo.endCursor), - ); + return result.search.nodes.concat(await getDiscussions(query, pageSize, result.search.pageInfo.endCursor)); } catch (e) { console.error(e); return Promise.reject(e); @@ -52,15 +50,12 @@ async function getDiscussions(query, pageSize, endCursor = null) { async function getDiscussionByID(isPR, id) { try { - const result = await graphql( - isPR ? Queries.pullRequestById : Queries.issueById, - { - id, - headers: { - authorization: `token ${process.env.GITHUB_TOKEN}`, - }, - }, - ); + const result = await graphql(isPR ? Queries.pullRequestById : Queries.issueById, { + id, + headers: { + authorization: `token ${process.env.GITHUB_TOKEN}` + } + }); return result; } catch (e) { @@ -75,28 +70,19 @@ async function processHotDiscussions(batch) { try { const isPR = discussion.__typename === 'PullRequest'; if (discussion.comments.pageInfo.hasNextPage) { - const fetchedDiscussion = await getDiscussionByID( - isPR, - discussion.id, - ); + const fetchedDiscussion = await getDiscussionByID(isPR, discussion.id); discussion = fetchedDiscussion.node; } const interactionsCount = discussion.reactions.totalCount + discussion.comments.totalCount + - discussion.comments.nodes.reduce( - (acc, curr) => acc + curr.reactions.totalCount, - 0, - ); + discussion.comments.nodes.reduce((acc, curr) => acc + curr.reactions.totalCount, 0); const finalInteractionsCount = isPR ? interactionsCount + discussion.reviews.totalCount + - discussion.reviews.nodes.reduce( - (acc, curr) => acc + curr.comments.totalCount, - 0, - ) + discussion.reviews.nodes.reduce((acc, curr) => acc + curr.comments.totalCount, 0) : interactionsCount; return { @@ -108,17 +94,13 @@ async function processHotDiscussions(batch) { resourcePath: discussion.resourcePath, repo: `asyncapi/${discussion.repository.name}`, labels: discussion.labels ? discussion.labels.nodes : [], - score: - finalInteractionsCount / - (monthsSince(discussion.timelineItems.updatedAt) + 2) ** 1.8, + score: finalInteractionsCount / (monthsSince(discussion.timelineItems.updatedAt) + 2) ** 1.8 }; } catch (e) { - console.error( - `there were some issues while parsing this item: ${JSON.stringify(discussion)}`, - ); + console.error(`there were some issues while parsing this item: ${JSON.stringify(discussion)}`); throw e; } - }), + }) ); } @@ -134,9 +116,7 @@ async function getHotDiscussions(discussions) { } result.sort((ElemA, ElemB) => ElemB.score - ElemA.score); - const filteredResult = result.filter( - (issue) => issue.author !== 'asyncapi-bot', - ); + const filteredResult = result.filter((issue) => issue.author !== 'asyncapi-bot'); return filteredResult.slice(0, 12); } @@ -146,7 +126,7 @@ async function writeToFile(content, writePath) { } catch (error) { console.error('Failed to write dashboard data:', { error: error.message, - writePath, + writePath }); throw error; } @@ -162,17 +142,13 @@ async function mapGoodFirstIssues(issues) { author: issue.author.login, area: getLabel(issue, 'area/') || 'Unknown', labels: issue.labels.nodes.filter( - (label) => - !label.name.startsWith('area/') && - !label.name.startsWith('good first issue'), - ), + (label) => !label.name.startsWith('area/') && !label.name.startsWith('good first issue') + ) })); } function getLabel(issue, filter) { - const result = issue.labels.nodes.find((label) => - label.name.startsWith(filter), - ); + const result = issue.labels.nodes.find((label) => label.name.startsWith(filter)); return result?.name.split('/')[1]; } @@ -187,14 +163,11 @@ async function start(writePath) { try { const issues = await getDiscussions(Queries.hotDiscussionsIssues, 20); const PRs = await getDiscussions(Queries.hotDiscussionsPullRequests, 20); - const rawGoodFirstIssues = await getDiscussions( - Queries.goodFirstIssues, - 20, - ); + const rawGoodFirstIssues = await getDiscussions(Queries.goodFirstIssues, 20); const discussions = issues.concat(PRs); const [hotDiscussions, goodFirstIssues] = await Promise.all([ getHotDiscussions(discussions), - mapGoodFirstIssues(rawGoodFirstIssues), + mapGoodFirstIssues(rawGoodFirstIssues) ]); return await writeToFile({ hotDiscussions, goodFirstIssues }, writePath); } catch (e) { @@ -217,5 +190,5 @@ module.exports = { getDiscussions, writeToFile, start, - processHotDiscussions, + processHotDiscussions }; diff --git a/scripts/dashboard/issue-queries.js b/scripts/dashboard/issue-queries.js index 629214a9ea90..4b2e5a87853c 100644 --- a/scripts/dashboard/issue-queries.js +++ b/scripts/dashboard/issue-queries.js @@ -274,5 +274,5 @@ query($first: Int!, $after: String) { resetAt } } -`, +` }); diff --git a/scripts/finance/index.js b/scripts/finance/index.js index af3cf0a80f60..c5ab35346c0d 100644 --- a/scripts/finance/index.js +++ b/scripts/finance/index.js @@ -1,39 +1,16 @@ const { - promises: { mkdir }, + promises: { mkdir } } = require('fs'); const { resolve } = require('path'); const writeJSON = require('../utils/readAndWriteJson.js'); -module.exports = async function buildFinanceInfoList({ - currentDir, - configDir, - financeDir, - year, - jsonDataDir, -}) { +module.exports = async function buildFinanceInfoList({ currentDir, configDir, financeDir, year, jsonDataDir }) { try { - const expensesPath = resolve( - currentDir, - configDir, - financeDir, - year, - 'Expenses.yml', - ); - const expensesLinkPath = resolve( - currentDir, - configDir, - financeDir, - year, - 'ExpensesLink.yml', - ); + const expensesPath = resolve(currentDir, configDir, financeDir, year, 'Expenses.yml'); + const expensesLinkPath = resolve(currentDir, configDir, financeDir, year, 'ExpensesLink.yml'); // Ensure the directory exists before writing the files - const jsonDirectory = resolve( - currentDir, - configDir, - financeDir, - jsonDataDir, - ); + const jsonDirectory = resolve(currentDir, configDir, financeDir, jsonDataDir); await mkdir(jsonDirectory, { recursive: true }); // Write Expenses and ExpensesLink to JSON files diff --git a/scripts/index.js b/scripts/index.js index 0ae68666ce24..afe99ff7ca11 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -8,16 +8,8 @@ const buildFinanceInfoList = require('./finance'); async function start() { await buildPostList(); - rssFeed( - 'blog', - 'AsyncAPI Initiative Blog RSS Feed', - 'AsyncAPI Initiative Blog', - 'rss.xml', - ); - await buildCaseStudiesList( - 'config/casestudies', - resolve(__dirname, '../config', 'case-studies.json'), - ); + rssFeed('blog', 'AsyncAPI Initiative Blog RSS Feed', 'AsyncAPI Initiative Blog', 'rss.xml'); + await buildCaseStudiesList('config/casestudies', resolve(__dirname, '../config', 'case-studies.json')); await buildAdoptersList(); const financeDir = resolve('.', 'config', 'finance'); @@ -44,7 +36,7 @@ async function start() { configDir: 'config', financeDir: 'finance', year: latestYear, - jsonDataDir: 'json-data', + jsonDataDir: 'json-data' }); } diff --git a/scripts/markdown/check-markdown.js b/scripts/markdown/check-markdown.js index 001a210a2a77..7088a1c4d0fc 100644 --- a/scripts/markdown/check-markdown.js +++ b/scripts/markdown/check-markdown.js @@ -23,14 +23,7 @@ function isValidURL(str) { * @returns {string[]|null} An array of validation error messages, or null if no errors. */ function validateBlogs(frontmatter) { - const requiredAttributes = [ - 'title', - 'date', - 'type', - 'tags', - 'cover', - 'authors', - ]; + const requiredAttributes = ['title', 'date', 'type', 'tags', 'cover', 'authors']; const errors = []; // Check for required attributes @@ -65,9 +58,7 @@ function validateBlogs(frontmatter) { errors.push(`Author at index ${index} is missing a name`); } if (author.link && !isValidURL(author.link)) { - errors.push( - `Invalid URL for author at index ${index}: ${author.link}`, - ); + errors.push(`Invalid URL for author at index ${index}: ${author.link}`); } if (!author.photo) { errors.push(`Author at index ${index} is missing a photo`); @@ -94,10 +85,7 @@ function validateDocs(frontmatter) { } // Check if weight exists and is a number - if ( - frontmatter.weight === undefined || - typeof frontmatter.weight !== 'number' - ) { + if (frontmatter.weight === undefined || typeof frontmatter.weight !== 'number') { errors.push('Weight is missing or not a number'); } diff --git a/scripts/tools/categorylist.js b/scripts/tools/categorylist.js index 15323b1606aa..dc81be15a320 100644 --- a/scripts/tools/categorylist.js +++ b/scripts/tools/categorylist.js @@ -3,117 +3,104 @@ const categoryList = [ { name: 'APIs', tag: 'api', - description: - 'The following is a list of APIs that expose functionality related to AsyncAPI.', + description: 'The following is a list of APIs that expose functionality related to AsyncAPI.' }, { name: 'Code-first tools', tag: 'code-first', - description: - 'The following is a list of tools that generate AsyncAPI documents from your code.', + description: 'The following is a list of tools that generate AsyncAPI documents from your code.' }, { name: 'Code Generators', tag: 'code-generator', description: - 'The following is a list of tools that generate code from an AsyncAPI document; not the other way around.', + 'The following is a list of tools that generate code from an AsyncAPI document; not the other way around.' }, { name: 'Converters', tag: 'converter', description: - 'The following is a list of tools that do not yet belong to any specific category but are also useful for the community.', + 'The following is a list of tools that do not yet belong to any specific category but are also useful for the community.' }, { name: 'Directories', tag: 'directory', - description: - 'The following is a list of directories that index public AsyncAPI documents.', + description: 'The following is a list of directories that index public AsyncAPI documents.' }, { name: 'Documentation Generators', tag: 'documentation-generator', description: - 'The following is a list of tools that generate human-readable documentation from an AsyncAPI document.', + 'The following is a list of tools that generate human-readable documentation from an AsyncAPI document.' }, { name: 'Editors', tag: 'editor', - description: - 'The following is a list of editors or related tools that allow editing of AsyncAPI document.', + description: 'The following is a list of editors or related tools that allow editing of AsyncAPI document.' }, { name: 'UI components', tag: 'ui-component', - description: - 'The following is a list of UI components to view AsyncAPI documents.', + description: 'The following is a list of UI components to view AsyncAPI documents.' }, { name: 'DSL', tag: 'dsl', description: - "Writing YAML by hand is no fun, and maybe you don't want a GUI, so use a Domain Specific Language to write AsyncAPI in your language of choice.", + "Writing YAML by hand is no fun, and maybe you don't want a GUI, so use a Domain Specific Language to write AsyncAPI in your language of choice." }, { name: 'Frameworks', tag: 'framework', - description: - 'The following is a list of API/application frameworks that make use of AsyncAPI.', + description: 'The following is a list of API/application frameworks that make use of AsyncAPI.' }, { name: 'GitHub Actions', tag: 'github-action', - description: - 'The following is a list of GitHub Actions that you can use in your workflows', + description: 'The following is a list of GitHub Actions that you can use in your workflows' }, { name: 'Mocking and Testing', tag: 'mocking-and-testing', description: - 'The tools below take specification documents as input, then publish fake messages to broker destinations for simulation purposes. They may also check that publisher messages are compliant with schemas.', + 'The tools below take specification documents as input, then publish fake messages to broker destinations for simulation purposes. They may also check that publisher messages are compliant with schemas.' }, { name: 'Validators', tag: 'validator', - description: - 'The following is a list of tools that validate AsyncAPI documents.', + description: 'The following is a list of tools that validate AsyncAPI documents.' }, { name: 'Compare tools', tag: 'compare-tool', - description: - 'The following is a list of tools that compare AsyncAPI documents.', + description: 'The following is a list of tools that compare AsyncAPI documents.' }, { name: 'CLIs', tag: 'cli', - description: - 'The following is a list of tools that you can work with in terminal or do some CI/CD automation.', + description: 'The following is a list of tools that you can work with in terminal or do some CI/CD automation.' }, { name: 'Bundlers', tag: 'bundler', - description: - 'The following is a list of tools that you can work with to bundle AsyncAPI documents.', + description: 'The following is a list of tools that you can work with to bundle AsyncAPI documents.' }, { name: 'IDE Extensions', tag: 'ide-extension', - description: - 'The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others', + description: 'The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others' }, { name: 'AsyncAPI Generator Templates', tag: 'generator-template', description: - 'The following is a list of templates compatible with AsyncAPI Generator. You can use them to generate apps, clients or documentation from your AsyncAPI documents.', + 'The following is a list of templates compatible with AsyncAPI Generator. You can use them to generate apps, clients or documentation from your AsyncAPI documents.' }, { name: 'Others', tag: 'other', - description: - 'The following is a list of tools that comes under Other category.', - }, + description: 'The following is a list of tools that comes under Other category.' + } ]; module.exports = { categoryList }; diff --git a/scripts/tools/combine-tools.js b/scripts/tools/combine-tools.js index 34980f1abd61..01be1ec876dc 100644 --- a/scripts/tools/combine-tools.js +++ b/scripts/tools/combine-tools.js @@ -1,20 +1,21 @@ -const { languagesColor, technologiesColor } = require('./tags-color'); -const { categoryList } = require('./categorylist.js'); -const { createToolObject } = require('./tools-object'); const fs = require('fs'); -const schema = require('./tools-schema.json'); const Ajv = require('ajv'); const addFormats = require('ajv-formats'); const Fuse = require('fuse.js'); +const { languagesColor, technologiesColor } = require('./tags-color'); +const { categoryList } = require('./categorylist.js'); +const { createToolObject } = require('./tools-object'); +const schema = require('./tools-schema.json'); + const ajv = new Ajv(); addFormats(ajv, ['uri']); const validate = ajv.compile(schema); -let finalTools = {}; -for (var category of categoryList) { +const finalTools = {}; +for (const category of categoryList) { finalTools[category.name] = { description: category.description, - toolsList: [], + toolsList: [] }; } @@ -23,37 +24,35 @@ const options = { includeScore: true, shouldSort: true, threshold: 0.39, - keys: ['name', 'color', 'borderColor'], + keys: ['name', 'color', 'borderColor'] }; // Two seperate lists and Fuse objects initialised to search languages and technologies tags // from specified list of same. -let languageList = [...languagesColor], - technologyList = [...technologiesColor]; -let languageFuse = new Fuse(languageList, options), - technologyFuse = new Fuse(technologyList, options); +const languageList = [...languagesColor]; +const technologyList = [...technologiesColor]; +let languageFuse = new Fuse(languageList, options); +let technologyFuse = new Fuse(technologyList, options); // takes individual tool object and inserts borderColor and backgroundColor of the tags of // languages and technologies, for Tool Card in website. const getFinalTool = async (toolObject) => { - let finalObject = toolObject; + const finalObject = toolObject; - //there might be a tool without language + // there might be a tool without language if (toolObject.filters.language) { - let languageArray = []; + const languageArray = []; if (typeof toolObject.filters.language === 'string') { - const languageSearch = await languageFuse.search( - toolObject.filters.language, - ); + const languageSearch = await languageFuse.search(toolObject.filters.language); if (languageSearch.length) { languageArray.push(languageSearch[0].item); } else { // adds a new language object in the Fuse list as well as in tool object // so that it isn't missed out in the UI. - let languageObject = { + const languageObject = { name: toolObject.filters.language, color: 'bg-[#57f281]', - borderColor: 'border-[#37f069]', + borderColor: 'border-[#37f069]' }; languageList.push(languageObject); languageArray.push(languageObject); @@ -67,10 +66,10 @@ const getFinalTool = async (toolObject) => { } else { // adds a new language object in the Fuse list as well as in tool object // so that it isn't missed out in the UI. - let languageObject = { + const languageObject = { name: language, color: 'bg-[#57f281]', - borderColor: 'border-[#37f069]', + borderColor: 'border-[#37f069]' }; languageList.push(languageObject); languageArray.push(languageObject); @@ -80,7 +79,7 @@ const getFinalTool = async (toolObject) => { } finalObject.filters.language = languageArray; } - let technologyArray = []; + const technologyArray = []; if (toolObject.filters.technology) { for (const technology of toolObject?.filters?.technology) { const technologySearch = await technologyFuse.search(technology); @@ -89,10 +88,10 @@ const getFinalTool = async (toolObject) => { } else { // adds a new technology object in the Fuse list as well as in tool object // so that it isn't missed out in the UI. - let technologyObject = { + const technologyObject = { name: technology, color: 'bg-[#61d0f2]', - borderColor: 'border-[#40ccf7]', + borderColor: 'border-[#40ccf7]' }; technologyList.push(technologyObject); technologyArray.push(technologyObject); @@ -106,14 +105,9 @@ const getFinalTool = async (toolObject) => { // Combine the automated tools and manual tools list into single JSON object file, and // lists down all the language and technology tags in one JSON file. -const combineTools = async ( - automatedTools, - manualTools, - toolsPath, - tagsPath, -) => { +const combineTools = async (automatedTools, manualTools, toolsPath, tagsPath) => { for (const key in automatedTools) { - let finalToolsList = []; + const finalToolsList = []; if (automatedTools[key].toolsList.length) { for (const tool of automatedTools[key].toolsList) { finalToolsList.push(await getFinalTool(tool)); @@ -126,35 +120,23 @@ const combineTools = async ( if (isValid) { if (tool?.links?.repoUrl) { const url = new URL(tool.links.repoUrl); - isAsyncAPIrepo = url.href.startsWith( - 'https://github.com/asyncapi/', - ); + isAsyncAPIrepo = url.href.startsWith('https://github.com/asyncapi/'); } else isAsyncAPIrepo = false; - let toolObject = await createToolObject(tool, '', '', isAsyncAPIrepo); + const toolObject = await createToolObject(tool, '', '', isAsyncAPIrepo); finalToolsList.push(await getFinalTool(toolObject)); } else { - console.error( - 'Script is not failing, it is just dropping errors for further investigation', - ); + console.error('Script is not failing, it is just dropping errors for further investigation'); console.error(`Invalid ${tool.title} .asyncapi-tool file.`); console.error(`Located in manual-tools.json file`); - console.error( - 'Validation errors:', - JSON.stringify(validate.errors, null, 2), - ); + console.error('Validation errors:', JSON.stringify(validate.errors, null, 2)); } } } - finalToolsList.sort((tool, anotherTool) => - tool.title.localeCompare(anotherTool.title), - ); + finalToolsList.sort((tool, anotherTool) => tool.title.localeCompare(anotherTool.title)); finalTools[key].toolsList = finalToolsList; } fs.writeFileSync(toolsPath, JSON.stringify(finalTools)); - fs.writeFileSync( - tagsPath, - JSON.stringify({ languages: languageList, technologies: technologyList }), - ); + fs.writeFileSync(tagsPath, JSON.stringify({ languages: languageList, technologies: technologyList })); }; module.exports = { combineTools }; diff --git a/scripts/tools/extract-tools-github.js b/scripts/tools/extract-tools-github.js index 567a8077be4b..1db138a95add 100644 --- a/scripts/tools/extract-tools-github.js +++ b/scripts/tools/extract-tools-github.js @@ -3,15 +3,12 @@ require('dotenv').config(); const getData = async () => { try { - const result = await axios.get( - 'https://api.github.com/search/code?q=filename:.asyncapi-tool', - { - headers: { - accept: 'application/vnd.github.text-match+json', - authorization: `token ${process.env.GITHUB_TOKEN}`, - }, - }, - ); + const result = await axios.get('https://api.github.com/search/code?q=filename:.asyncapi-tool', { + headers: { + accept: 'application/vnd.github.text-match+json', + authorization: `token ${process.env.GITHUB_TOKEN}` + } + }); return result.data; } catch (err) { diff --git a/scripts/tools/tags-color.js b/scripts/tools/tags-color.js index 5897fcab5837..3483de2b0b08 100644 --- a/scripts/tools/tags-color.js +++ b/scripts/tools/tags-color.js @@ -3,176 +3,176 @@ const languagesColor = [ { name: 'Go/Golang', color: 'bg-[#8ECFDF]', - borderColor: 'border-[#00AFD9]', + borderColor: 'border-[#00AFD9]' }, { name: 'Java', color: 'bg-[#ECA2A4]', - borderColor: 'border-[#EC2125]', + borderColor: 'border-[#EC2125]' }, { name: 'JavaScript', color: 'bg-[#F2F1C7]', - borderColor: 'border-[#BFBE86]', + borderColor: 'border-[#BFBE86]' }, { name: 'HTML', color: 'bg-[#E2A291]', - borderColor: 'border-[#E44D26]', + borderColor: 'border-[#E44D26]' }, { name: 'C/C++', color: 'bg-[#93CDEF]', - borderColor: 'border-[#0080CC]', + borderColor: 'border-[#0080CC]' }, { name: 'C#', color: 'bg-[#E3AFE0]', - borderColor: 'border-[#9B4F96]', + borderColor: 'border-[#9B4F96]' }, { name: 'Python', color: 'bg-[#A8D0EF]', - borderColor: 'border-[#3878AB]', + borderColor: 'border-[#3878AB]' }, { name: 'TypeScript', color: 'bg-[#7DBCFE]', - borderColor: 'border-[#2C78C7]', + borderColor: 'border-[#2C78C7]' }, { name: 'Kotlin', color: 'bg-[#B1ACDF]', - borderColor: 'border-[#756BD9]', + borderColor: 'border-[#756BD9]' }, { name: 'Scala', color: 'bg-[#FFA299]', - borderColor: 'border-[#DF301F]', + borderColor: 'border-[#DF301F]' }, { name: 'Markdown', color: 'bg-[#BABEBF]', - borderColor: 'border-[#445B64]', + borderColor: 'border-[#445B64]' }, { name: 'YAML', color: 'bg-[#FFB764]', - borderColor: 'border-[#F1901F]', + borderColor: 'border-[#F1901F]' }, { name: 'R', color: 'bg-[#84B5ED]', - borderColor: 'border-[#246BBE]', + borderColor: 'border-[#246BBE]' }, { name: 'Ruby', color: 'bg-[#FF8289]', - borderColor: 'border-[#FF000F]', + borderColor: 'border-[#FF000F]' }, { name: 'Rust', color: 'bg-[#FFB8AA]', - borderColor: 'border-[#E43716]', + borderColor: 'border-[#E43716]' }, { name: 'Shell', color: 'bg-[#87D4FF]', - borderColor: 'border-[#389ED7]', + borderColor: 'border-[#389ED7]' }, { name: 'Groovy', color: 'bg-[#B6D5E5]', - borderColor: 'border-[#609DBC]', - }, + borderColor: 'border-[#609DBC]' + } ]; const technologiesColor = [ { name: 'Node.js', color: 'bg-[#BDFF67]', - borderColor: 'border-[#84CE24]', + borderColor: 'border-[#84CE24]' }, { name: 'Hermes', color: 'bg-[#8AEEBD]', - borderColor: 'border-[#2AB672]', + borderColor: 'border-[#2AB672]' }, { name: 'React JS', color: 'bg-[#9FECFA]', - borderColor: 'border-[#08D8FE]', + borderColor: 'border-[#08D8FE]' }, { name: '.NET', color: 'bg-[#A184FF]', - borderColor: 'border-[#5026D4]', + borderColor: 'border-[#5026D4]' }, { name: 'ASP.NET', color: 'bg-[#71C2FB]', - borderColor: 'border-[#1577BC]', + borderColor: 'border-[#1577BC]' }, { name: 'Springboot', color: 'bg-[#98E279]', - borderColor: 'border-[#68BC44]', + borderColor: 'border-[#68BC44]' }, { name: 'AWS', color: 'bg-[#FF9F59]', - borderColor: 'border-[#EF6703]', + borderColor: 'border-[#EF6703]' }, { name: 'Docker', color: 'bg-[#B8E0FF]', - borderColor: 'border-[#2596ED]', + borderColor: 'border-[#2596ED]' }, { name: 'Node-RED', color: 'bg-[#FF7474]', - borderColor: 'border-[#8F0101]', + borderColor: 'border-[#8F0101]' }, { name: 'Maven', color: 'bg-[#FF6B80]', - borderColor: 'border-[#CA1A33]', + borderColor: 'border-[#CA1A33]' }, { name: 'Saas', color: 'bg-[#6AB8EC]', - borderColor: 'border-[#2275AD]', + borderColor: 'border-[#2275AD]' }, { name: 'Kubernetes-native', color: 'bg-[#D7C7F2]', - borderColor: 'border-[#A387D2]', + borderColor: 'border-[#A387D2]' }, { name: 'Scala', color: 'bg-[#D7C7F2]', - borderColor: 'border-[#A387D2]', + borderColor: 'border-[#A387D2]' }, { name: 'Azure', color: 'bg-[#4B93FF]', - borderColor: 'border-[#015ADF]', + borderColor: 'border-[#015ADF]' }, { name: 'Jenkins', color: 'bg-[#D7C7F2]', - borderColor: 'border-[#A387D2]', + borderColor: 'border-[#A387D2]' }, { name: 'Flask', color: 'bg-[#D7C7F2]', - borderColor: 'border-[#A387D2]', + borderColor: 'border-[#A387D2]' }, { name: 'Nest Js', color: 'bg-[#E1224E]', - borderColor: 'border-[#B9012b]', - }, + borderColor: 'border-[#B9012b]' + } ]; module.exports = { languagesColor, technologiesColor }; diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index 9ef57e5cab31..57b152e49570 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -1,9 +1,10 @@ -const schema = require('./tools-schema.json'); const axios = require('axios'); const Ajv = require('ajv'); const addFormats = require('ajv-formats'); const Fuse = require('fuse.js'); +const schema = require('./tools-schema.json'); const { categoryList } = require('./categorylist'); + const ajv = new Ajv(); addFormats(ajv, ['uri']); const validate = ajv.compile(schema); @@ -14,7 +15,7 @@ const options = { includeScore: true, shouldSort: true, threshold: 0.4, - keys: ['tag'], + keys: ['tag'] }; const fuse = new Fuse(categoryList, options); @@ -24,28 +25,19 @@ const fuse = new Fuse(categoryList, options); // isAsyncAPIrepo boolean variable to define whether the tool repository is under // AsyncAPI organization or not, to create a JSON tool object as required in the frontend // side to show ToolCard. -const createToolObject = async ( - toolFile, - repositoryUrl = '', - repoDescription = '', - isAsyncAPIrepo = '', -) => { - let resultantObject = { +const createToolObject = async (toolFile, repositoryUrl = '', repoDescription = '', isAsyncAPIrepo = '') => { + const resultantObject = { title: toolFile.title, description: toolFile?.description ? toolFile.description : repoDescription, links: { ...toolFile.links, - repoUrl: toolFile?.links?.repoUrl - ? toolFile.links.repoUrl - : repositoryUrl, + repoUrl: toolFile?.links?.repoUrl ? toolFile.links.repoUrl : repositoryUrl }, filters: { ...toolFile.filters, - hasCommercial: toolFile?.filters?.hasCommercial - ? toolFile.filters.hasCommercial - : false, - isAsyncAPIOwner: isAsyncAPIrepo, - }, + hasCommercial: toolFile?.filters?.hasCommercial ? toolFile.filters.hasCommercial : false, + isAsyncAPIOwner: isAsyncAPIrepo + } }; return resultantObject; }; @@ -55,43 +47,43 @@ const createToolObject = async ( // and creating a JSON tool object in which all the tools are listed in defined // categories order, which is then updated in `automated-tools.json` file. async function convertTools(data) { - let finalToolsObject = {}; + const finalToolsObject = {}; const dataArray = data.items; // initialising finalToolsObject with all categories inside it with proper elements in each category - for (var index in categoryList) { + for (const index in categoryList) { finalToolsObject[categoryList[index].name] = { description: categoryList[index].description, - toolsList: [], + toolsList: [] }; } - for (let tool of dataArray) { + for (const tool of dataArray) { try { if (tool.name.startsWith('.asyncapi-tool')) { // extracting the reference id of the repository which will be used to extract the path of the .asyncapi-tool file in the Tools repository // ex: for a url = "https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873" // the text (id) present after '=' gives us a reference id for the repo - let reference_id = tool.url.split('=')[1]; - let download_url = `https://raw.githubusercontent.com/${tool.repository.full_name}/${reference_id}/${tool.path}`; + const reference_id = tool.url.split('=')[1]; + const download_url = `https://raw.githubusercontent.com/${tool.repository.full_name}/${reference_id}/${tool.path}`; const { data: toolFileContent } = await axios.get(download_url); - //some stuff can be YAML + // some stuff can be YAML const jsonToolFileContent = await convertToJson(toolFileContent); - //validating against JSON Schema for tools file + // validating against JSON Schema for tools file const isValid = await validate(jsonToolFileContent); if (isValid) { - let repositoryUrl = tool.repository.html_url; - let repoDescription = tool.repository.description; - let isAsyncAPIrepo = tool.repository.owner.login === 'asyncapi'; - let toolObject = await createToolObject( + const repositoryUrl = tool.repository.html_url; + const repoDescription = tool.repository.description; + const isAsyncAPIrepo = tool.repository.owner.login === 'asyncapi'; + const toolObject = await createToolObject( jsonToolFileContent, repositoryUrl, repoDescription, - isAsyncAPIrepo, + isAsyncAPIrepo ); // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object @@ -99,35 +91,20 @@ async function convertTools(data) { const categorySearch = await fuse.search(category); if (categorySearch.length) { - let searchedCategoryName = categorySearch[0].item.name; - if ( - !finalToolsObject[searchedCategoryName].toolsList.find( - (element) => element === toolObject, - ) - ) - finalToolsObject[searchedCategoryName].toolsList.push( - toolObject, - ); + const searchedCategoryName = categorySearch[0].item.name; + if (!finalToolsObject[searchedCategoryName].toolsList.find((element) => element === toolObject)) + finalToolsObject[searchedCategoryName].toolsList.push(toolObject); } else { // if Tool object has a category, not defined in our categorylist, then this provides a `other` category to the tool. - if ( - !finalToolsObject['Others'].toolsList.find( - (element) => element === toolObject, - ) - ) - finalToolsObject['Others'].toolsList.push(toolObject); + if (!finalToolsObject.Others.toolsList.find((element) => element === toolObject)) + finalToolsObject.Others.toolsList.push(toolObject); } }); } else { - console.error( - 'Script is not failing, it is just dropping errors for further investigation', - ); + console.error('Script is not failing, it is just dropping errors for further investigation'); console.error('Invalid .asyncapi-tool file.'); console.error(`Located in: ${tool.html_url}`); - console.error( - 'Validation errors:', - JSON.stringify(validate.errors, null, 2), - ); + console.error('Validation errors:', JSON.stringify(validate.errors, null, 2)); } } } catch (err) { diff --git a/scripts/utils.js b/scripts/utils.js index 66d01b75afc7..fa893a6de22e 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -18,9 +18,7 @@ function convertToJson(contentYAMLorJSON) { return yamlContent; } catch (yamlError) { // If parsing as YAML also fails, throw an error - throw new Error( - `Invalid content format:\nJSON Parse Error: ${jsonError}\nYAML Parse Error: ${yamlError}`, - ); + throw new Error(`Invalid content format:\nJSON Parse Error: ${jsonError}\nYAML Parse Error: ${yamlError}`); } } } diff --git a/scripts/utils/readAndWriteJson.js b/scripts/utils/readAndWriteJson.js index d1ed2dd43a12..e3e2a6f2b6e3 100644 --- a/scripts/utils/readAndWriteJson.js +++ b/scripts/utils/readAndWriteJson.js @@ -1,5 +1,5 @@ const { - promises: { readFile, writeFile }, + promises: { readFile, writeFile } } = require('fs'); const { convertToJson } = require('../utils');