diff --git a/assets/docs/fragments/cli-installation.md b/assets/docs/fragments/cli-installation.md new file mode 100644 index 000000000000..67a0796c8528 --- /dev/null +++ b/assets/docs/fragments/cli-installation.md @@ -0,0 +1,62 @@ +### CLI Installation +Follow the [AsyncAPI CLI installation](https://github.com/asyncapi/cli#installation) instructions below, based on your computer’s operating system. + +
+MacOS + +`brew` +
+You can install in MacOS via brew: `brew install asyncapi`. + +`pkg` +
+Each release of CLI produces a MacOS dedicated pkg file that enables you to install this CLI as MacOS application. + +``` +# Download latest release. To download specific release, your link should look similar to https://github.com/asyncapi/cli/releases/download/v0.13.0/asyncapi.pkg. All releases are listed in https://github.com/asyncapi/cli/releases +curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.pkg +# Install AsyncAPI CLI +sudo installer -pkg asyncapi.pkg -target / +``` + +
+ +
+Linux + +You can install in Linux via `dpkg`, a debian package manager: + +1. `curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.deb` +2. `sudo dpkg -i asyncapi.deb` + +
+ +
+Other OS + +[Read further AsyncAPI CLI installation instructions for different operating systems](https://github.com/asyncapi/cli#installation). +
+ +#### Using NPM and Node.js +Alternitavely, you can install the [AsyncAPI CLI](https://github.com/asyncapi/cli#installation) with Node.js `>=v10` and [NPM](https://nodejs.org/en/download/package-manager/). + +
+Install CLI globally + +Install AsyncAPI CLI _globally_ with the following command: + +``` +npm install -g @asyncapi/cli +``` +
+ +
+Install specific CLI version + +To install a specific version of the AsyncAPI CLI, pass the `verion` during installation: + +``` +npm install -g @asyncapi/cli@{version} +``` + +
diff --git a/components/Calendar.js b/components/Calendar.js index 2efa7fd26f1e..8431a5416f1a 100644 --- a/components/Calendar.js +++ b/components/Calendar.js @@ -52,14 +52,18 @@ export default function Calendar({ className = '', size, text="text-left" }) { ))} - {eventsExist && ( + {eventsExist ?
- )} + : +
+ There are no meetings scheduled for next few days. +
+ } ); } diff --git a/components/MDX.js b/components/MDX.js index daa7ed720524..a321f4aaeb0c 100644 --- a/components/MDX.js +++ b/components/MDX.js @@ -38,7 +38,7 @@ function getMDXComponents() { h1: props =>

, h2: props =>

, h3: props =>

, - h4: props =>

, + h4: props =>

, h5: props =>

, h6: props =>
, blockquote: props =>
, diff --git a/components/buttons/Button.js b/components/buttons/Button.js index 1397f576b9e2..3c19313c6cb4 100644 --- a/components/buttons/Button.js +++ b/components/buttons/Button.js @@ -14,8 +14,8 @@ export default function Button({ ...props }) { - const smallButtonClasses = twMerge(` ${bgClassName} ${textClassName} transition-all duration-500 ease-in-out rounded-md px-3 py-2 text-sm font-medium tracking-heading ${className || ''}`) - const classNames = twMerge(` ${bgClassName} ${textClassName} transition-all duration-500 ease-in-out rounded-md px-4 py-3 text-md font-semibold tracking-heading ${className || ''}`) + const smallButtonClasses = twMerge(`${bgClassName} ${textClassName} transition-all duration-500 ease-in-out rounded-md px-3 py-2 text-sm font-medium tracking-heading ${className || ''}`) + const classNames = twMerge(`${bgClassName} ${textClassName} transition-all duration-500 ease-in-out rounded-md px-4 py-3 text-md font-semibold tracking-heading ${className || ''}`) if (!href) { return ( diff --git a/components/icons/ArrowDown.js b/components/icons/ArrowDown.js new file mode 100644 index 000000000000..f5a0b92e1470 --- /dev/null +++ b/components/icons/ArrowDown.js @@ -0,0 +1,7 @@ +export default function IconArrowDown({ className= '' }) { + return ( + + + + ) +} diff --git a/components/icons/Filter.js b/components/icons/Filter.js new file mode 100644 index 000000000000..7ed76bb0cd28 --- /dev/null +++ b/components/icons/Filter.js @@ -0,0 +1,14 @@ +export default function IconFilter({className=''}) { + return ( + + + + + + + + + + + ) +} diff --git a/components/icons/Search.js b/components/icons/Search.js new file mode 100644 index 000000000000..01811239f940 --- /dev/null +++ b/components/icons/Search.js @@ -0,0 +1,7 @@ +export default function IconSearch({className = ''}) { + return ( + + + + ) +} diff --git a/components/navigation/DocsNav.js b/components/navigation/DocsNav.js index 853d39c9b417..d2de1f392d8d 100644 --- a/components/navigation/DocsNav.js +++ b/components/navigation/DocsNav.js @@ -44,9 +44,9 @@ export default function DocsNav({
    • - {Object.values(subCategories).map((subCategory, index) => ( + {Object.values(subCategories).map((subCategory) => (
    • - +
        {subCategory.children && subCategory.children.map(subItem => (
      • diff --git a/components/navigation/DocsNavItem.js b/components/navigation/DocsNavItem.js index a49f7e0f9a57..dcf17037f709 100644 --- a/components/navigation/DocsNavItem.js +++ b/components/navigation/DocsNavItem.js @@ -1,14 +1,18 @@ import Link from 'next/link'; -function isActiveSlug(slug, activeSlug) { +function isActiveSlug(slug, activeSlug, sectionSlug) { + if(slug === '/docs' || (sectionSlug !== undefined && slug === sectionSlug)) { + return (slug == activeSlug) + } + const partialSlug = slug.split('/'); const partialActiveSlug = activeSlug.split('/'); const activeParts = partialActiveSlug.filter((a, idx) => a === partialSlug[idx]); return activeParts.length === partialSlug.length; } -export default function DocsNavItem({ title, slug, href, indexDocument, activeSlug, onClick = () => {}, defaultClassName = '', inactiveClassName = '', activeClassName = '', bucket }) { - const isActive = slug === '/docs' || indexDocument ? slug === activeSlug : isActiveSlug(slug, activeSlug); +export default function DocsNavItem({ title, slug, href, activeSlug, sectionSlug, onClick = () => {}, defaultClassName = '', inactiveClassName = '', activeClassName = '', bucket }) { + const isActive = isActiveSlug(slug, activeSlug, sectionSlug); const classes = `${isActive ? activeClassName : inactiveClassName} ${defaultClassName} inline-block`; return ( @@ -27,4 +31,4 @@ export default function DocsNavItem({ title, slug, href, indexDocument, activeSl ); -} +} \ No newline at end of file diff --git a/components/navigation/communityItems.js b/components/navigation/communityItems.js index 1d7bc8223e98..c6b5ff457c7c 100644 --- a/components/navigation/communityItems.js +++ b/components/navigation/communityItems.js @@ -17,7 +17,7 @@ export default [ { icon: IconTools, title: 'Tools & Services', - href: '/docs/community/tooling', + href: '/docs/tools', description: 'Explore the tools and services our awesome community has created.', }, diff --git a/components/tools/Filters.js b/components/tools/Filters.js new file mode 100644 index 000000000000..bb5ebeae9591 --- /dev/null +++ b/components/tools/Filters.js @@ -0,0 +1,134 @@ +import { useState, useContext } from 'react'; +import {twMerge} from 'tailwind-merge' +import {ToolFilterContext} from '../../context/ToolFilterContext' +import ArrowDown from '../icons/ArrowDown'; +import FiltersDropdown from './FiltersDropdown'; +import Button from '../buttons/Button' +import tags from '../../config/all-tags.json' +import {categoryList} from '../../scripts/tools/categorylist' + +export default function Filters({setOpenFilter}) { + // all the filter state variables and functions are extracted from the Context to set filters according to the UI. + const {isPaid, isAsyncAPIOwner, languages, technologies, categories, setCategories, setLanguages, setTechnologies, setisPaid, setAsyncAPIOwner} = useContext(ToolFilterContext) + + // State variables to operate dropdowns of respective filters + const [openLanguage, setopenLanguage] = useState(false) + const [openTechnology, setopenTechnology] = useState(false) + const [openCategory, setopenCategory] = useState(false) + + // Filter state variables for user checked values are created, initialising it with the values already set by user. + const [checkPaid, setCheckPaid] = useState(isPaid) + const [checkedLanguage, setCheckedLanguage] = useState(languages) + const [checkedTechnology, setCheckedTechnology] = useState(technologies) + const [checkedCategory, setCheckedCategory] = useState(categories) + const [checkOwner, setCheckOwner] = useState(isAsyncAPIOwner) + + // contains the list of languages and technologies + let languageList = tags["languages"] + let technologyList = tags["technologies"] + + // function to apply all the filters, which are selected, when `Apply Filters` is clicked. + const handleApplyFilters = () => { + setLanguages(checkedLanguage); + setTechnologies(checkedTechnology) + setCategories(checkedCategory) + setisPaid(checkPaid) + setAsyncAPIOwner(checkOwner) + setOpenFilter(false) + } + + // function to clear all the filters when `Clear Filters` is clicked. + const clearFilters =() => { + setLanguages([]) + setTechnologies([]) + setCategories([]) + setisPaid("all") + setAsyncAPIOwner(false) + setOpenFilter(false) + } + + return ( +
        +
        +
        +
        Pricing
        +
        + Clear Filters +
        +
        +
        +
        setCheckPaid("free")}> +
        Open Source
        + +
        +
        setCheckPaid("paid")}> +
        Commercial
        + +
        +
        +
        +
        +
        +
        OWNERSHIP
        +
        + +
        + Show only AsyncAPI-owned tools +
        +
        +
        +
        +
        +
        LANGUAGE
        +
        +
        setopenLanguage(!openLanguage)}> +
        + Select Languages... +
        + +
        + {openLanguage &&
        + +
        } +
        +
        +
        +
        +
        TECHNOLOGY
        +
        +
        setopenTechnology(!openTechnology)}> +
        + Select technologies... +
        + +
        + {openTechnology &&
        + +
        } +
        +
        +
        +
        +
        CATEGORY
        +
        +
        setopenCategory(!openCategory)}> +
        + Select categories... +
        + +
        + {openCategory &&
        + +
        } +
        +
        +
        +
        +
        +
        + ); +} diff --git a/components/tools/FiltersDropdown.js b/components/tools/FiltersDropdown.js new file mode 100644 index 000000000000..dc646c83ef08 --- /dev/null +++ b/components/tools/FiltersDropdown.js @@ -0,0 +1,27 @@ +import { twMerge } from "tailwind-merge"; + +export default function FiltersDropdown({dataList=[], checkedOptions=[], setStateFunction, className=''}) { + + const handleClickOption = (e, option) => { + let tempValueArray = [...checkedOptions] + let index = checkedOptions.indexOf(option) + if(index>-1){ + tempValueArray.splice(index, 1); + }else{ + tempValueArray.push(option); + } + setStateFunction(tempValueArray) + } + return ( +
        + {dataList.map((data, index) => { + let checked = checkedOptions.indexOf(data.name)!=-1 ? true : false + return ( +
        handleClickOption(e, data.name)}> + {checked ? : } +
        {data.name}
        +
        + )})} +
        + ) +} diff --git a/components/tools/Tags.js b/components/tools/Tags.js new file mode 100644 index 000000000000..ab41adc51e07 --- /dev/null +++ b/components/tools/Tags.js @@ -0,0 +1,7 @@ +export default function SelectTags({name='', bgColor, borderColor}) { + return ( +
        + {name} +
        + ) +} diff --git a/components/tools/ToolDashboard.js b/components/tools/ToolDashboard.js new file mode 100644 index 000000000000..0de755b286aa --- /dev/null +++ b/components/tools/ToolDashboard.js @@ -0,0 +1,134 @@ +import { useState, useContext, useEffect, useRef } from 'react'; +import { ToolFilterContext } from '../../context/ToolFilterContext' +import ToolsData from '../../config/tools.json' +import FilterIcon from '../icons/Filter'; +import SearchIcon from '../icons/Search'; +import ToolsList from './ToolsList'; +import Filters from './Filters'; + +export default function ToolDashboard() { + const filterRef = useRef() // used to provide ref to the Filter menu and outside click close feature + const [openFilter, setOpenFilter] = useState(false) + // filter parameters extracted from the context + const { isPaid, isAsyncAPIOwner, languages, technologies, categories } = useContext(ToolFilterContext) + const [searchName, setSearchName] = useState('') // state variable used to get the search name + const [toolsList, setToolsList] = useState({}) // state variable used to set the list of tools according to the filters applied + const [checkToolsList, setCheckToolsList] = useState(true) // state variable used to check whether any tool is available according to the needs of user. + + // useEffect function to enable the close Modal feature when clicked outside of the modal + useEffect(() => { + const checkIfClickOutside = (e) => { + if ((openFilter && filterRef.current && !filterRef.current.contains(e.target))) + setOpenFilter(false) + } + document.addEventListener("mousedown", checkIfClickOutside) + return () => { + document.removeEventListener("mousedown", checkIfClickOutside) + } + }) + + // Function to update the list of tools according to the current filters applied + const updateToolsList = () => { + let tempToolsList = {} + + // Tools data list is first filtered according to the category filter if applied by the user. + // Hence if any category is selected, then only respective tools will be selected for further check on filters + if (categories.length > 0) { + for (let category of categories) { + Object.keys(ToolsData).forEach((key) => { + if (key === category) tempToolsList[key] = JSON.parse(JSON.stringify(ToolsData[key])) + }) + } + } else { + // if no category is selected, then all tools are selected for further check on filters + tempToolsList = JSON.parse(JSON.stringify(ToolsData)); + } + + // checkToolsList is initially made false to check whether any tools are present according to the filters. + setCheckToolsList(false) + + // Each tool selected, is then traversed to check against each filter variable (only if the filter is applied), + // whether they match with the filter applied or not. + Object.keys(tempToolsList).forEach((category) => { + tempToolsList[category].toolsList = tempToolsList[category].toolsList.filter((tool) => { + + // These are filter check variable for respective filters, which is initially made true. + // If the particular filter is applied by user, the respective check variable is made false first, + // and then tool parameters are checked against the filter variable value to decide it matches the filter + // criteria or not. + let isLanguageTool = true, isTechnologyTool = true, isSearchTool = true, isAsyncAPITool = true, isPaidTool = true; + if (languages.length) { + isLanguageTool = false; + for (let language of languages) { + if (tool?.filters?.language && language === tool.filters.language.name) isLanguageTool = true; + } + } + if (technologies.length) { + isTechnologyTool = false; + for (let technology of technologies) { + if (tool?.filters?.technology && tool.filters.technology.find((item) => item.name === technology)) isTechnologyTool = true; + } + } + if (searchName) { + isSearchTool = tool.title.toLowerCase().includes(searchName.toLowerCase()) + } + if (isAsyncAPIOwner) + isAsyncAPITool = tool.filters.isAsyncAPIOwner === isAsyncAPIOwner ? true : false + + if (isPaid !== "all") { + if (isPaid === "free") isPaidTool = tool.filters.hasCommercial === false; + else isPaidTool = tool.filters.hasCommercial === true; + } + + return isLanguageTool && isTechnologyTool && isSearchTool && isAsyncAPITool && isPaidTool; + }) + if (tempToolsList[category].toolsList.length) setCheckToolsList(true) + }) + setToolsList(tempToolsList) + } + + useEffect(() => { + updateToolsList() + }, [isPaid, isAsyncAPIOwner, languages, technologies, categories, searchName]) + + return ( +
        +
        +
        +
        +
        setOpenFilter(!openFilter)}> + +
        Filter
        +
        + {openFilter && ( +
        + +
        + )} +
        +
        +
        + + setSearchName(e.target.value)} + /> + {searchName && } +
        +
        +
        + {checkToolsList ? :
        + +
        Sorry, we don't have tools according to your needs.
        +
        } +
        +
        + ) +} diff --git a/components/tools/ToolsCard.js b/components/tools/ToolsCard.js new file mode 100644 index 000000000000..8eeb93247f4e --- /dev/null +++ b/components/tools/ToolsCard.js @@ -0,0 +1,107 @@ +import { useState, useRef, useEffect } from 'react' +import Heading from '../typography/Heading'; +import Paragraph from '../typography/Paragraph'; +import Tag from './Tags'; +import TextTruncate from 'react-text-truncate'; + +export default function ToolsCard({ toolData }) { + const [showDescription, setShowDescription] = useState(false) + const [showMoreDescription, setShowMoreDescription] = useState(false) + const descriptionRef = useRef(null) + useEffect(() => { + let divHeight = descriptionRef.current.offsetHeight; + let numberOfLines = divHeight/20; + if(numberOfLines > 3) setShowMoreDescription(true) + else setShowMoreDescription(false) + }, []) + + let onGit = false; + const url = new URL(toolData.links.repoUrl) + if (url.host == 'github.com') onGit = true + else onGit = false + + return ( +
        +
        +
        +
        + {toolData.title} +
        + {toolData.filters.hasCommercial === false ? 'Open Source' : 'Commercial'} +
        +
        +
        + +
        (setTimeout(() => {if(showMoreDescription) setShowDescription(true)}, 500))}> +
        +
        + {showDescription &&
        (setShowDescription(false))}> + + {toolData.description} + +
        } +
        +
        +
        +
        + {(toolData?.filters?.language || toolData?.filters?.technology?.length>0) && +
        + {toolData.filters.language &&
        +
        LANGUAGES
        +
        + +
        +
        } + {toolData.filters.technology.length > 0 && <>
        +
        TECHNOLOGIES
        +
        + {toolData.filters.technology.map((item, index) => ( + + ))} +
        +
        } +
        } + {(toolData.links.repoUrl || toolData.links.websiteUrl) && <> +
        +
        + {onGit ? + +
        + +
        View on Github
        +
        +
        : + +
        +
        View Source Code
        +
        +
        + } + {toolData.links.websiteUrl && ( + <> +
        + +
        + +
        Visit Website
        +
        +
        + + )} +
        + } +
        + ); +} diff --git a/components/tools/ToolsList.js b/components/tools/ToolsList.js new file mode 100644 index 000000000000..f97f4215f75c --- /dev/null +++ b/components/tools/ToolsList.js @@ -0,0 +1,26 @@ +import ToolsCard from './ToolsCard'; +import Heading from '../typography/Heading' +import Paragraph from '../typography/Paragraph' +export default function toolsList({ toolsData }) { + return ( +
        + {Object.keys(toolsData).map((categoryName, index) => { + if(toolsData[categoryName].toolsList.length > 0) return ( +
        + + {categoryName} + + + {toolsData[categoryName].description} + +
        +
        + {toolsData[categoryName].toolsList.map((tool, toolIndex) => ( + + ))} +
        +
        ) + })} +
        + ); +} diff --git a/config/all-tags.json b/config/all-tags.json new file mode 100644 index 000000000000..dcb17cf8ce24 --- /dev/null +++ b/config/all-tags.json @@ -0,0 +1 @@ +{"languages":[{"name":"Go","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]"}],"technologies":[{"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":"WebComponents","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"AsyncAPI Generator","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"VSCode","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"SmartPaste","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}]} \ No newline at end of file diff --git a/config/meetings.json b/config/meetings.json index 7537193ce206..0637a088a01e 100644 --- a/config/meetings.json +++ b/config/meetings.json @@ -1,7 +1 @@ -[ - { - "title": "Spec 3.0 Meeting", - "url": "https://github.com/asyncapi/community/issues/546", - "date": "Wed, 21 Dec 2022 16:00:00 GMT" - } -] \ No newline at end of file +[] \ No newline at end of file diff --git a/config/tools-automated.json b/config/tools-automated.json index 06257e9d1dd8..2f76c682b6f1 100644 --- a/config/tools-automated.json +++ b/config/tools-automated.json @@ -1 +1 @@ -{"APIs":{"description":"The following is a list of APIs that expose functionality related to AsyncAPI.","toolsList":[]},"Code-first tools":{"description":"The following is a list of tools that generate AsyncAPI documents from your code.","toolsList":[]},"Code Generators":{"description":"The following is a list of tools that generate code from an AsyncAPI document; not the other way around.","toolsList":[{"title":"Sample Tool","description":"Tool for testing","links":{"websiteUrl":"https://akshatnema.netlify.app","docsUrl":"","repoUrl":"https://github.com/akshatnema/Login-Registration-project"},"filters":{"language":"javascript","technology":["react"],"categories":["code generator"],"hasCommercial":false,"isAsyncAPIOwner":false}}]},"Converters":{"description":"The following is a list of tools that do not yet belong to any specific category but are also useful for the community.","toolsList":[]},"Directories":{"description":"The following is a list of directories that index public AsyncAPI documents.","toolsList":[]},"Documentation Generators":{"description":"The following is a list of tools that generate human-readable documentation from an AsyncAPI document.","toolsList":[]},"Editors":{"description":"The following is a list of editors or related tools that allow editing of AsyncAPI document.","toolsList":[]},"UI components":{"description":"The following is a list of UI components to view AsyncAPI documents.","toolsList":[{"title":"AsyncAPI React component","description":"React component for rendering documentation from your specification in real-time in the browser. It also provides a WebComponent and bundle for Angular and Vue","links":{"repoUrl":"https://github.com/asyncapi/asyncapi-react"},"filters":{"languages":["TypeScript"],"technology":["React","WebComponents"],"categories":["ui-component"],"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Frameworks":{"description":"The following is a list of API/application frameworks that make use of AsyncAPI.","toolsList":[]},"GitHub Actions":{"description":"The following is a list of GitHub Actions that you can use in your workflows","toolsList":[{"title":"GitHub Action for Generator","description":"GitHub Action to generate all the things from your AsyncAPI document using the AsyncAPI generator","links":{"repoUrl":"https://github.com/asyncapi/github-action-for-generator"},"filters":{"technology":["AsyncAPI Generator"],"categories":["github-actions"],"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Validators":{"description":"The following is a list of tools that validate AsyncAPI documents.","toolsList":[]},"Compare tools":{"description":"The following is a list of tools that compare AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Diff","description":"Diff is a library that compares two AsyncAPI Documents and provides information about the differences by pointing out explicitly information like breaking changes.","links":{"repoUrl":"https://github.com/asyncapi/diff"},"filters":{"languages":["TypeScript"],"technology":["TypeScript"],"categories":["compare-tool"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Others":{"description":"The following is a list of tools that comes under Other category.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":["TypeScript"],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"CLIs":{"description":"The following is a list of tools that you can work with in terminal or do some CI/CD automation.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":["TypeScript"],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Bundlers":{"description":"The following is a list of tools that you can work with to bundle AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Bundler","description":"Combine multiple AsyncAPI specification files into one","links":{"repoUrl":"https://github.com/asyncapi/bundler"},"filters":{"languages":["TypeScript"],"technology":["TypeScript"],"categories":["bundler"],"isAsyncAPIOwner":true}}]},"IDE Extensions":{"description":"The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others","toolsList":[{"title":"asyncapi-preview","description":"VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n","links":{"repoUrl":"https://github.com/asyncapi/vs-asyncapi-preview"},"filters":{"technology":["VSCode","SmartPaste"],"categories":["ide-extension"],"isAsyncAPIOwner":true}}]}} \ No newline at end of file +{"APIs":{"description":"The following is a list of APIs that expose functionality related to AsyncAPI.","toolsList":[]},"Code-first tools":{"description":"The following is a list of tools that generate AsyncAPI documents from your code.","toolsList":[]},"Code Generators":{"description":"The following is a list of tools that generate code from an AsyncAPI document; not the other way around.","toolsList":[{"title":"Sample Tool","description":"Tool for testing","links":{"websiteUrl":"https://akshatnema.netlify.app","docsUrl":"","repoUrl":"https://github.com/akshatnema/Login-Registration-project"},"filters":{"language":"javascript","technology":["react"],"categories":["code generator"],"hasCommercial":false,"isAsyncAPIOwner":false}}]},"Converters":{"description":"The following is a list of tools that do not yet belong to any specific category but are also useful for the community.","toolsList":[]},"Directories":{"description":"The following is a list of directories that index public AsyncAPI documents.","toolsList":[]},"Documentation Generators":{"description":"The following is a list of tools that generate human-readable documentation from an AsyncAPI document.","toolsList":[]},"Editors":{"description":"The following is a list of editors or related tools that allow editing of AsyncAPI document.","toolsList":[]},"UI components":{"description":"The following is a list of UI components to view AsyncAPI documents.","toolsList":[{"title":"AsyncAPI React component","description":"React component for rendering documentation from your specification in real-time in the browser. It also provides a WebComponent and bundle for Angular and Vue","links":{"repoUrl":"https://github.com/asyncapi/asyncapi-react"},"filters":{"languages":["TypeScript"],"technology":["React","WebComponents"],"categories":["ui-component"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Frameworks":{"description":"The following is a list of API/application frameworks that make use of AsyncAPI.","toolsList":[]},"GitHub Actions":{"description":"The following is a list of GitHub Actions that you can use in your workflows","toolsList":[{"title":"GitHub Action for Generator","description":"GitHub Action to generate all the things from your AsyncAPI document using the AsyncAPI generator","links":{"repoUrl":"https://github.com/asyncapi/github-action-for-generator"},"filters":{"technology":["AsyncAPI Generator"],"categories":["github-actions"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Validators":{"description":"The following is a list of tools that validate AsyncAPI documents.","toolsList":[]},"Compare tools":{"description":"The following is a list of tools that compare AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Diff","description":"Diff is a library that compares two AsyncAPI Documents and provides information about the differences by pointing out explicitly information like breaking changes.","links":{"repoUrl":"https://github.com/asyncapi/diff"},"filters":{"languages":["TypeScript"],"technology":["TypeScript"],"categories":["compare-tool"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"CLIs":{"description":"The following is a list of tools that you can work with in terminal or do some CI/CD automation.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":["TypeScript"],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Bundlers":{"description":"The following is a list of tools that you can work with to bundle AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Bundler","description":"Combine multiple AsyncAPI specification files into one","links":{"repoUrl":"https://github.com/asyncapi/bundler"},"filters":{"languages":["TypeScript"],"technology":["TypeScript"],"categories":["bundler"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"IDE Extensions":{"description":"The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others","toolsList":[{"title":"asyncapi-preview","description":"VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n","links":{"repoUrl":"https://github.com/asyncapi/vs-asyncapi-preview"},"filters":{"technology":["VSCode","SmartPaste"],"categories":["ide-extension"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Others":{"description":"The following is a list of tools that comes under Other category.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":["TypeScript"],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]}} \ No newline at end of file diff --git a/config/tools.json b/config/tools.json index b7bcfc7e1f37..d061bca0e17c 100644 --- a/config/tools.json +++ b/config/tools.json @@ -1 +1 @@ -{"APIs":{"description":"The following is a list of APIs that expose functionality related to AsyncAPI.","toolsList":[]},"Code-first tools":{"description":"The following is a list of tools that generate AsyncAPI documents from your code.","toolsList":[]},"Code Generators":{"description":"The following is a list of tools that generate code from an AsyncAPI document; not the other way around.","toolsList":[{"title":"Sample Tool","description":"Tool for testing","links":{"websiteUrl":"https://akshatnema.netlify.app","docsUrl":"","repoUrl":"https://github.com/akshatnema/Login-Registration-project"},"filters":{"language":{"name":"Javascript","color":"#F2F1C7","borderColor":"#BFBE86"},"technology":[],"categories":["code generator"],"hasCommercial":false,"isAsyncAPIOwner":false}}]},"Converters":{"description":"The following is a list of tools that do not yet belong to any specific category but are also useful for the community.","toolsList":[]},"Directories":{"description":"The following is a list of directories that index public AsyncAPI documents.","toolsList":[]},"Documentation Generators":{"description":"The following is a list of tools that generate human-readable documentation from an AsyncAPI document.","toolsList":[{"title":"asyncapi-asciidoc-template","description":"Asciidoc template for the asyncapi generator","links":{"repoUrl":"https://gitlab.com/djencks/asyncapi-asciidoc-template"},"filters":{"language":{"name":"Javascript","color":"#F2F1C7","borderColor":"#BFBE86"},"technology":[],"categories":["documentation generator"],"hasCommercial":false,"isAsyncAPIOwner":false}}]},"Editors":{"description":"The following is a list of editors or related tools that allow editing of AsyncAPI document.","toolsList":[]},"UI components":{"description":"The following is a list of UI components to view AsyncAPI documents.","toolsList":[{"title":"AsyncAPI React component","description":"React component for rendering documentation from your specification in real-time in the browser. It also provides a WebComponent and bundle for Angular and Vue","links":{"repoUrl":"https://github.com/asyncapi/asyncapi-react"},"filters":{"languages":["TypeScript"],"technology":[],"categories":["ui-component"],"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Frameworks":{"description":"The following is a list of API/application frameworks that make use of AsyncAPI.","toolsList":[]},"GitHub Actions":{"description":"The following is a list of GitHub Actions that you can use in your workflows","toolsList":[{"title":"GitHub Action for Generator","description":"GitHub Action to generate all the things from your AsyncAPI document using the AsyncAPI generator","links":{"repoUrl":"https://github.com/asyncapi/github-action-for-generator"},"filters":{"technology":[],"categories":["github-actions"],"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Validators":{"description":"The following is a list of tools that validate AsyncAPI documents.","toolsList":[]},"Compare tools":{"description":"The following is a list of tools that compare AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Diff","description":"Diff is a library that compares two AsyncAPI Documents and provides information about the differences by pointing out explicitly information like breaking changes.","links":{"repoUrl":"https://github.com/asyncapi/diff"},"filters":{"languages":["TypeScript"],"technology":[],"categories":["compare-tool"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Others":{"description":"The following is a list of tools that comes under Other category.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":[],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"CLIs":{"description":"The following is a list of tools that you can work with in terminal or do some CI/CD automation.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":[],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Bundlers":{"description":"The following is a list of tools that you can work with to bundle AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Bundler","description":"Combine multiple AsyncAPI specification files into one","links":{"repoUrl":"https://github.com/asyncapi/bundler"},"filters":{"languages":["TypeScript"],"technology":[],"categories":["bundler"],"isAsyncAPIOwner":true}}]},"IDE Extensions":{"description":"The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others","toolsList":[{"title":"asyncapi-preview","description":"VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n","links":{"repoUrl":"https://github.com/asyncapi/vs-asyncapi-preview"},"filters":{"technology":[],"categories":["ide-extension"],"isAsyncAPIOwner":true}}]}} \ No newline at end of file +{"APIs":{"description":"The following is a list of APIs that expose functionality related to AsyncAPI.","toolsList":[]},"Code-first tools":{"description":"The following is a list of tools that generate AsyncAPI documents from your code.","toolsList":[]},"Code Generators":{"description":"The following is a list of tools that generate code from an AsyncAPI document; not the other way around.","toolsList":[{"title":"Sample Tool","description":"Tool for testing","links":{"websiteUrl":"https://akshatnema.netlify.app","docsUrl":"","repoUrl":"https://github.com/akshatnema/Login-Registration-project"},"filters":{"language":{"name":"JavaScript","color":"bg-[#F2F1C7]","borderColor":"border-[#BFBE86]"},"technology":[{"name":"React JS","color":"bg-[#9FECFA]","borderColor":"border-[#08D8FE]"}],"categories":["code generator"],"hasCommercial":false,"isAsyncAPIOwner":false}}]},"Converters":{"description":"The following is a list of tools that do not yet belong to any specific category but are also useful for the community.","toolsList":[]},"Directories":{"description":"The following is a list of directories that index public AsyncAPI documents.","toolsList":[]},"Documentation Generators":{"description":"The following is a list of tools that generate human-readable documentation from an AsyncAPI document.","toolsList":[{"title":"asyncapi-asciidoc-template","description":"Asciidoc template for the asyncapi generator","links":{"repoUrl":"https://gitlab.com/djencks/asyncapi-asciidoc-template"},"filters":{"language":{"name":"JavaScript","color":"bg-[#F2F1C7]","borderColor":"border-[#BFBE86]"},"technology":[{"name":"React JS","color":"bg-[#9FECFA]","borderColor":"border-[#08D8FE]"}],"categories":["documentation generator"],"hasCommercial":false,"isAsyncAPIOwner":false}}]},"Editors":{"description":"The following is a list of editors or related tools that allow editing of AsyncAPI document.","toolsList":[]},"UI components":{"description":"The following is a list of UI components to view AsyncAPI documents.","toolsList":[{"title":"AsyncAPI React component","description":"React component for rendering documentation from your specification in real-time in the browser. It also provides a WebComponent and bundle for Angular and Vue","links":{"repoUrl":"https://github.com/asyncapi/asyncapi-react"},"filters":{"languages":["TypeScript"],"technology":[{"name":"React JS","color":"bg-[#9FECFA]","borderColor":"border-[#08D8FE]"},{"name":"WebComponents","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["ui-component"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Frameworks":{"description":"The following is a list of API/application frameworks that make use of AsyncAPI.","toolsList":[]},"GitHub Actions":{"description":"The following is a list of GitHub Actions that you can use in your workflows","toolsList":[{"title":"GitHub Action for Generator","description":"GitHub Action to generate all the things from your AsyncAPI document using the AsyncAPI generator","links":{"repoUrl":"https://github.com/asyncapi/github-action-for-generator"},"filters":{"technology":[{"name":"AsyncAPI Generator","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["github-actions"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"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.","toolsList":[]},"Validators":{"description":"The following is a list of tools that validate AsyncAPI documents.","toolsList":[]},"Compare tools":{"description":"The following is a list of tools that compare AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Diff","description":"Diff is a library that compares two AsyncAPI Documents and provides information about the differences by pointing out explicitly information like breaking changes.","links":{"repoUrl":"https://github.com/asyncapi/diff"},"filters":{"languages":["TypeScript"],"technology":[{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["compare-tool"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"CLIs":{"description":"The following is a list of tools that you can work with in terminal or do some CI/CD automation.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":[{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Bundlers":{"description":"The following is a list of tools that you can work with to bundle AsyncAPI documents.","toolsList":[{"title":"AsyncAPI Bundler","description":"Combine multiple AsyncAPI specification files into one","links":{"repoUrl":"https://github.com/asyncapi/bundler"},"filters":{"languages":["TypeScript"],"technology":[{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["bundler"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"IDE Extensions":{"description":"The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others","toolsList":[{"title":"asyncapi-preview","description":"VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n","links":{"repoUrl":"https://github.com/asyncapi/vs-asyncapi-preview"},"filters":{"technology":[{"name":"VSCode","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"SmartPaste","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["ide-extension"],"hasCommercial":false,"isAsyncAPIOwner":true}}]},"Others":{"description":"The following is a list of tools that comes under Other category.","toolsList":[{"title":"AsyncAPI CLI","description":"One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n","links":{"websiteUrl":"https://www.asyncapi.com/tools/cli","repoUrl":"https://github.com/asyncapi/cli"},"filters":{"technology":[{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}],"categories":["others","cli"],"hasCommercial":false,"isAsyncAPIOwner":true}}]}} \ No newline at end of file diff --git a/context/ToolFilterContext.js b/context/ToolFilterContext.js new file mode 100644 index 000000000000..0df4adf1c747 --- /dev/null +++ b/context/ToolFilterContext.js @@ -0,0 +1,16 @@ +import { createContext, useState } from 'react' +export const ToolFilterContext = createContext() + +export default function ToolFilter({ children }) { + const [isPaid, setisPaid] = useState("all"); + const [isAsyncAPIOwner, setAsyncAPIOwner] = useState(false) + const [languages, setLanguages] = useState([]) + const [technologies, setTechnologies] = useState([]) + const [categories, setCategories] = useState([]) + + return ( + + {children} + + ) +} \ No newline at end of file diff --git a/dashboard.json b/dashboard.json index 048f1601163c..abc96fe878bf 100644 --- a/dashboard.json +++ b/dashboard.json @@ -17,39 +17,26 @@ "score": 51.11707679736806 }, { - "id": "I_kwDOBW5R_c47-31p", - "isPR": false, + "id": "PR_kwDOBW5R_c5ARCuj", + "isPR": true, "isAssigned": true, - "title": "Create New page for /tools/", - "author": "iamVP7", - "resourcePath": "/asyncapi/website/issues/383", + "title": "docs: new guide for message validation", + "author": "starlightknown", + "resourcePath": "/asyncapi/website/pull/1005", "repo": "asyncapi/website", - "labels": [ - { - "name": "enhancement", - "color": "84b6eb" - }, - { - "name": "🎨 design", - "color": "0D67D3" - }, - { - "name": "gsoc", - "color": "F4D03F" - } - ], - "score": 44.512061256135105 + "labels": [], + "score": 27.28158593117958 }, { - "id": "PR_kwDOBW5R_c5ARCuj", + "id": "PR_kwDOBW5R_c5AyxaN", "isPR": true, "isAssigned": true, - "title": "docs: new guide for message validation", + "title": "docs: new tutorial \"validate asyncapi documents using studio\"", "author": "starlightknown", - "resourcePath": "/asyncapi/website/pull/1005", + "resourcePath": "/asyncapi/website/pull/1022", "repo": "asyncapi/website", "labels": [], - "score": 24.122665454937735 + "score": 24.697014632436254 }, { "id": "PR_kwDOBGu-185AIQgf", @@ -60,18 +47,7 @@ "resourcePath": "/asyncapi/spec/pull/847", "repo": "asyncapi/spec", "labels": [], - "score": 24.122665454937735 - }, - { - "id": "PR_kwDOBW5R_c5AyxaN", - "isPR": true, - "isAssigned": true, - "title": "docs: new tutorial \"validate asyncapi documents using studio\"", - "author": "starlightknown", - "resourcePath": "/asyncapi/website/pull/1022", - "repo": "asyncapi/website", - "labels": [], - "score": 23.26114168868996 + "score": 24.409840043686994 }, { "id": "PR_kwDOFLhIt849RhNn", @@ -84,6 +60,17 @@ "labels": [], "score": 22.68679251119144 }, + { + "id": "PR_kwDOFLhIt85AY9Ib", + "isPR": true, + "isAssigned": false, + "title": "docs: how changes in the spec are introduced", + "author": "AceTheCreator", + "resourcePath": "/asyncapi/community/pull/488", + "repo": "asyncapi/community", + "labels": [], + "score": 21.25091956744515 + }, { "id": "PR_kwDOBW5R_c5AL1kI", "isPR": true, @@ -106,17 +93,6 @@ "labels": [], "score": 21.25091956744515 }, - { - "id": "PR_kwDOFLhIt85AY9Ib", - "isPR": true, - "isAssigned": false, - "title": "docs: how changes in the spec are introduced", - "author": "AceTheCreator", - "resourcePath": "/asyncapi/community/pull/488", - "repo": "asyncapi/community", - "labels": [], - "score": 20.67657038994663 - }, { "id": "PR_kwDOFXtyC849zwGo", "isPR": true, @@ -129,56 +105,77 @@ "score": 20.67657038994663 }, { - "id": "PR_kwDOCoBobc4xN9Px", + "id": "PR_kwDOBW5R_c5DWzbr", "isPR": true, - "isAssigned": false, - "title": "fix: throw meaningful errors", - "author": "ritik307", - "resourcePath": "/asyncapi/parser-js/pull/449", - "repo": "asyncapi/parser-js", + "isAssigned": true, + "title": "feat: ambassador program page", + "author": "AceTheCreator", + "resourcePath": "/asyncapi/website/pull/1123", + "repo": "asyncapi/website", "labels": [], - "score": 19.815046623698855 + "score": 20.38939580119737 }, { - "id": "PR_kwDOBW5R_c4-vMid", - "isPR": true, + "id": "MDU6SXNzdWUzNjkwNDExMDc=", + "isPR": false, "isAssigned": false, - "title": "feat: added new /tools page", - "author": "akshatnema", - "resourcePath": "/asyncapi/website/pull/940", + "title": "Support request/reply pattern", + "author": "adrianhopebailie", + "resourcePath": "/asyncapi/spec/issues/94", + "repo": "asyncapi/spec", + "labels": [ + { + "name": "keep-open", + "color": "fce250" + } + ], + "score": 19.378036838463604 + }, + { + "id": "I_kwDOBW5R_c5Pi3rO", + "isPR": false, + "isAssigned": false, + "title": "Epic roadmap to the new AsyncAPI community section", + "author": "AceTheCreator", + "resourcePath": "/asyncapi/website/issues/903", "repo": "asyncapi/website", - "labels": [], - "score": 19.527872034949596 + "labels": [ + { + "name": "🎨 design", + "color": "0D67D3" + } + ], + "score": 19.240697446200336 } ], "goodFirstIssues": [ { - "id": "I_kwDOBGu-185ZLGtq", - "title": "Cleanup readme with icons of sponsors", + "id": "I_kwDOBW5R_c5Z22jm", + "title": "when there are no upcoming meeting we should write something and not leave whitespace", "isAssigned": false, - "resourcePath": "/asyncapi/spec/issues/883", - "repo": "asyncapi/spec", + "resourcePath": "/asyncapi/website/issues/1183", + "repo": "asyncapi/website", "author": "derberg", - "area": "docs", + "area": "javascript", "labels": [ { "name": "enhancement", - "color": "a2eeef" + "color": "84b6eb" } ] }, { - "id": "I_kwDOCHlHJM5XfhdE", - "title": "[Docs Bug 🐞 report]: Links in main readme files are dead", + "id": "I_kwDOBW5R_c5Z2zWN", + "title": "update subscribe for meetings link on landing page", "isAssigned": false, - "resourcePath": "/asyncapi/generator/issues/873", - "repo": "asyncapi/generator", - "author": "jonaslagoni", - "area": "docs", + "resourcePath": "/asyncapi/website/issues/1182", + "repo": "asyncapi/website", + "author": "derberg", + "area": "javascript", "labels": [ { - "name": "🐞 docs bug", - "color": "FFD23F" + "name": "enhancement", + "color": "84b6eb" } ] }, @@ -250,21 +247,6 @@ } ] }, - { - "id": "I_kwDOE8Qh385T6fcd", - "title": "Add example to generate all models within the same file", - "isAssigned": false, - "resourcePath": "/asyncapi/modelina/issues/949", - "repo": "asyncapi/modelina", - "author": "jonaslagoni", - "area": "Unknown", - "labels": [ - { - "name": "enhancement", - "color": "a2eeef" - } - ] - }, { "id": "I_kwDOB5hCo85Ttv6g", "title": "Traits can be defined as double arrays", @@ -390,10 +372,6 @@ { "name": "enhancement", "color": "a2eeef" - }, - { - "name": "stale", - "color": "ededed" } ] }, @@ -458,6 +436,10 @@ { "name": "enhancement", "color": "a2eeef" + }, + { + "name": "stale", + "color": "ededed" } ] }, diff --git a/package-lock.json b/package-lock.json index 9c4e2da810a2..1b605c52ee4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "lodash": "^4.17.21", "markdown-to-txt": "^2.0.1", "markdown-toc": "1.2.0", - "mermaid": "^9.1.6", + "mermaid": "^9.3.0", "moment": "^2.29.4", "monaco-editor": "^0.20.0", "next": "^12.0.0", @@ -49,7 +49,7 @@ "react-ga": "^3.1.2", "react-gtm-module": "^2.0.11", "react-scrollspy": "^3.4.2", - "react-syntax-highlighter": "^15.5.0", + "react-syntax-highlighter": "12.2.1", "react-text-truncate": "^0.16.0", "react-twitter-embed": "^3.0.3", "react-typing-animation": "^1.6.2", @@ -563,11 +563,14 @@ } }, "node_modules/@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", + "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/template": { @@ -2125,6 +2128,17 @@ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "optional": true, + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -2537,9 +2551,9 @@ } }, "node_modules/d3": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.6.1.tgz", - "integrity": "sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.0.tgz", + "integrity": "sha512-a5rNemRadWkEfqnY5NsD4RdCP9vn8EIJ4I5Rl14U0uKH1SXqcNmk/h9aGaAF1O98lz6L9M0IeUcuPa9GUYbI5A==", "dependencies": { "d3-array": "3", "d3-axis": "3", @@ -2621,11 +2635,6 @@ "node": ">=12" } }, - "node_modules/d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -2896,11 +2905,6 @@ "d3-selection": "2 - 3" } }, - "node_modules/d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, "node_modules/d3-zoom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", @@ -2916,305 +2920,13 @@ "node": ">=12" } }, - "node_modules/dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", - "dependencies": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "node_modules/dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", - "dependencies": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "node_modules/dagre-d3/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/dagre-d3/node_modules/d3": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", - "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", - "dependencies": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "node_modules/dagre-d3/node_modules/d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "node_modules/dagre-d3/node_modules/d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "dependencies": { - "d3-array": "1", - "d3-path": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "node_modules/dagre-d3/node_modules/d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "dependencies": { - "d3-array": "^1.1.1" - } - }, - "node_modules/dagre-d3/node_modules/d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" - }, - "node_modules/dagre-d3/node_modules/d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "dependencies": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "dependencies": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json", - "csv2tsv": "bin/dsv2dsv", - "dsv2dsv": "bin/dsv2dsv", - "dsv2json": "bin/dsv2json", - "json2csv": "bin/json2dsv", - "json2dsv": "bin/json2dsv", - "json2tsv": "bin/json2dsv", - "tsv2csv": "bin/dsv2dsv", - "tsv2json": "bin/dsv2json" - } - }, - "node_modules/dagre-d3/node_modules/d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" - }, - "node_modules/dagre-d3/node_modules/d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "dependencies": { - "d3-dsv": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "dependencies": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" - }, - "node_modules/dagre-d3/node_modules/d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "dependencies": { - "d3-array": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" - }, - "node_modules/dagre-d3/node_modules/d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "node_modules/dagre-d3-es": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.6.tgz", + "integrity": "sha512-CaaE/nZh205ix+Up4xsnlGmpog5GGm81Upi2+/SBHxwNwrccBb3K51LzjZ1U6hgvOlAEUsVWf1xSTzCyKpJ6+Q==", "dependencies": { - "d3-color": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" - }, - "node_modules/dagre-d3/node_modules/d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" - }, - "node_modules/dagre-d3/node_modules/d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" - }, - "node_modules/dagre-d3/node_modules/d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "node_modules/dagre-d3/node_modules/d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "dependencies": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "node_modules/dagre-d3/node_modules/d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "dependencies": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, - "node_modules/dagre-d3/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "dependencies": { - "d3-path": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" - }, - "node_modules/dagre-d3/node_modules/d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "dependencies": { - "d3-time": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "node_modules/dagre-d3/node_modules/d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "dependencies": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "node_modules/dagre-d3/node_modules/d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "node_modules/dagre-d3/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "d3": "^7.7.0", + "lodash-es": "^4.17.21" } }, "node_modules/debug": { @@ -3282,6 +2994,12 @@ "node": ">=0.4.0" } }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", @@ -3391,9 +3109,9 @@ } }, "node_modules/dompurify": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz", - "integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz", + "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==" }, "node_modules/domutils": { "version": "2.8.0", @@ -4263,6 +3981,15 @@ "node": ">=4" } }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "optional": true, + "dependencies": { + "delegate": "^3.1.2" + } + }, "node_modules/google-auth-library": { "version": "7.14.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", @@ -4314,14 +4041,6 @@ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, - "node_modules/graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "dependencies": { - "lodash": "^4.17.15" - } - }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -4516,9 +4235,10 @@ } }, "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "version": "9.15.10", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", + "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==", + "deprecated": "Version no longer supported. Upgrade to @latest", "engines": { "node": "*" } @@ -5267,6 +4987,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -5426,16 +5151,12 @@ } }, "node_modules/lowlight": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.12.1.tgz", + "integrity": "sha512-OqaVxMGIESnawn+TU/QMV5BJLbUghUfjDWPAtFqDYDmDtr4FnB+op8xM+pR7nKlauHNUHXGt0VgWatFB8voS5w==", "dependencies": { - "fault": "^1.0.0", - "highlight.js": "~10.7.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "fault": "^1.0.2", + "highlight.js": "~9.15.0" } }, "node_modules/lru-cache": { @@ -5584,19 +5305,28 @@ } }, "node_modules/mermaid": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.1.7.tgz", - "integrity": "sha512-MRVHXy5FLjnUQUG7YS3UN9jEN6FXCJbFCXVGJQjVIbiR6Vhw0j/6pLIjqsiah9xoHmQU6DEaKOvB3S1g/1nBPA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.3.0.tgz", + "integrity": "sha512-mGl0BM19TD/HbU/LmlaZbjBi//tojelg8P/mxD6pPZTAYaI+VawcyBdqRsoUHSc7j71PrMdJ3HBadoQNdvP5cg==", "dependencies": { "@braintree/sanitize-url": "^6.0.0", "d3": "^7.0.0", - "dagre": "^0.8.5", - "dagre-d3": "^0.6.4", - "dompurify": "2.4.0", - "graphlib": "^2.1.8", + "dagre-d3-es": "7.0.6", + "dompurify": "2.4.1", "khroma": "^2.0.0", - "moment-mini": "2.24.0", - "stylis": "^4.0.10" + "lodash-es": "^4.17.21", + "moment-mini": "^2.24.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "uuid": "^9.0.0" + } + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/micromatch": { @@ -5869,6 +5599,11 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7153,15 +6888,15 @@ } }, "node_modules/react-syntax-highlighter": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", - "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==", + "version": "12.2.1", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-12.2.1.tgz", + "integrity": "sha512-CTsp0ZWijwKRYFg9xhkWD4DSpQqE4vb2NKVMdPAkomnILSmsNBHE0n5GuI5zB+PU3ySVvXvdt9jo+ViD9XibCA==", "dependencies": { "@babel/runtime": "^7.3.1", - "highlight.js": "^10.4.1", - "lowlight": "^1.17.0", - "prismjs": "^1.27.0", - "refractor": "^3.6.0" + "highlight.js": "~9.15.1", + "lowlight": "1.12.1", + "prismjs": "^1.8.4", + "refractor": "^2.4.1" }, "peerDependencies": { "react": ">= 0.14.0" @@ -7311,31 +7046,59 @@ "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=" }, "node_modules/refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-2.10.1.tgz", + "integrity": "sha512-Xh9o7hQiQlDbxo5/XkOX6H+x/q8rmlmZKr97Ie1Q8ZM32IRRd3B/UxuA/yXDW79DBSXGWxm2yRTbcTVmAciJRw==", "dependencies": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" + "hastscript": "^5.0.0", + "parse-entities": "^1.1.2", + "prismjs": "~1.17.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/refractor/node_modules/hastscript": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", + "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "dependencies": { + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "node_modules/refractor/node_modules/prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", - "engines": { - "node": ">=6" + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", + "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", + "optionalDependencies": { + "clipboard": "^2.0.0" } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", @@ -7720,6 +7483,12 @@ "kind-of": "^6.0.0" } }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "optional": true + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -8270,6 +8039,12 @@ "xtend": "~4.0.1" } }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, "node_modules/tiny-merge-patch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tiny-merge-patch/-/tiny-merge-patch-0.1.2.tgz", @@ -9215,11 +8990,11 @@ } }, "@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", + "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/template": { @@ -10489,6 +10264,17 @@ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, + "clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "optional": true, + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -10848,9 +10634,9 @@ } }, "d3": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.6.1.tgz", - "integrity": "sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.0.tgz", + "integrity": "sha512-a5rNemRadWkEfqnY5NsD4RdCP9vn8EIJ4I5Rl14U0uKH1SXqcNmk/h9aGaAF1O98lz6L9M0IeUcuPa9GUYbI5A==", "requires": { "d3-array": "3", "d3-axis": "3", @@ -10917,11 +10703,6 @@ "d3-path": "1 - 3" } }, - "d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, "d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -11103,11 +10884,6 @@ "d3-timer": "1 - 3" } }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, "d3-zoom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", @@ -11120,293 +10896,13 @@ "d3-transition": "2 - 3" } }, - "dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dagre-d3-es": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.6.tgz", + "integrity": "sha512-CaaE/nZh205ix+Up4xsnlGmpog5GGm81Upi2+/SBHxwNwrccBb3K51LzjZ1U6hgvOlAEUsVWf1xSTzCyKpJ6+Q==", "requires": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", - "requires": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "d3": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", - "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", - "requires": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "requires": { - "d3-array": "^1.1.1" - } - }, - "d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" - }, - "d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" - }, - "d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "requires": { - "d3-dsv": "1" - } - }, - "d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" - }, - "d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" - }, - "d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" - }, - "d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" - }, - "d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" - }, - "d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "requires": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, - "d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" - }, - "d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } + "d3": "^7.7.0", + "lodash-es": "^4.17.21" } }, "debug": { @@ -11465,6 +10961,12 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, "deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", @@ -11549,9 +11051,9 @@ } }, "dompurify": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz", - "integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz", + "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==" }, "domutils": { "version": "2.8.0", @@ -12374,6 +11876,15 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "optional": true, + "requires": { + "delegate": "^3.1.2" + } + }, "google-auth-library": { "version": "7.14.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", @@ -12425,14 +11936,6 @@ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, - "graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "requires": { - "lodash": "^4.17.15" - } - }, "gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -12601,9 +12104,9 @@ } }, "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + "version": "9.15.10", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", + "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==" }, "html-void-elements": { "version": "1.0.5", @@ -13264,6 +12767,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -13425,12 +12933,12 @@ } }, "lowlight": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.12.1.tgz", + "integrity": "sha512-OqaVxMGIESnawn+TU/QMV5BJLbUghUfjDWPAtFqDYDmDtr4FnB+op8xM+pR7nKlauHNUHXGt0VgWatFB8voS5w==", "requires": { - "fault": "^1.0.0", - "highlight.js": "~10.7.0" + "fault": "^1.0.2", + "highlight.js": "~9.15.0" } }, "lru-cache": { @@ -13556,19 +13064,27 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "mermaid": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.1.7.tgz", - "integrity": "sha512-MRVHXy5FLjnUQUG7YS3UN9jEN6FXCJbFCXVGJQjVIbiR6Vhw0j/6pLIjqsiah9xoHmQU6DEaKOvB3S1g/1nBPA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.3.0.tgz", + "integrity": "sha512-mGl0BM19TD/HbU/LmlaZbjBi//tojelg8P/mxD6pPZTAYaI+VawcyBdqRsoUHSc7j71PrMdJ3HBadoQNdvP5cg==", "requires": { "@braintree/sanitize-url": "^6.0.0", "d3": "^7.0.0", - "dagre": "^0.8.5", - "dagre-d3": "^0.6.4", - "dompurify": "2.4.0", - "graphlib": "^2.1.8", + "dagre-d3-es": "7.0.6", + "dompurify": "2.4.1", "khroma": "^2.0.0", - "moment-mini": "2.24.0", - "stylis": "^4.0.10" + "lodash-es": "^4.17.21", + "moment-mini": "^2.24.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "uuid": "^9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + } } }, "micromatch": { @@ -13792,6 +13308,11 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, + "non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -14803,15 +14324,15 @@ } }, "react-syntax-highlighter": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", - "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==", + "version": "12.2.1", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-12.2.1.tgz", + "integrity": "sha512-CTsp0ZWijwKRYFg9xhkWD4DSpQqE4vb2NKVMdPAkomnILSmsNBHE0n5GuI5zB+PU3ySVvXvdt9jo+ViD9XibCA==", "requires": { "@babel/runtime": "^7.3.1", - "highlight.js": "^10.4.1", - "lowlight": "^1.17.0", - "prismjs": "^1.27.0", - "refractor": "^3.6.0" + "highlight.js": "~9.15.1", + "lowlight": "1.12.1", + "prismjs": "^1.8.4", + "refractor": "^2.4.1" } }, "react-test-renderer": { @@ -14961,26 +14482,53 @@ "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=" }, "refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-2.10.1.tgz", + "integrity": "sha512-Xh9o7hQiQlDbxo5/XkOX6H+x/q8rmlmZKr97Ie1Q8ZM32IRRd3B/UxuA/yXDW79DBSXGWxm2yRTbcTVmAciJRw==", "requires": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" + "hastscript": "^5.0.0", + "parse-entities": "^1.1.2", + "prismjs": "~1.17.0" }, "dependencies": { + "hastscript": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", + "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "requires": { + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + } + }, + "parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", + "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", + "requires": { + "clipboard": "^2.0.0" + } } } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regexp.prototype.flags": { "version": "1.4.3", @@ -15320,6 +14868,12 @@ "kind-of": "^6.0.0" } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "optional": true + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -15781,6 +15335,12 @@ "xtend": "~4.0.1" } }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, "tiny-merge-patch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tiny-merge-patch/-/tiny-merge-patch-0.1.2.tgz", diff --git a/package.json b/package.json index 337f7a7ebe5e..5ddd71785af9 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "lodash": "^4.17.21", "markdown-to-txt": "^2.0.1", "markdown-toc": "1.2.0", - "mermaid": "^9.1.6", + "mermaid": "^9.3.0", "moment": "^2.29.4", "monaco-editor": "^0.20.0", "next": "^12.0.0", @@ -75,7 +75,7 @@ "react-ga": "^3.1.2", "react-gtm-module": "^2.0.11", "react-scrollspy": "^3.4.2", - "react-syntax-highlighter": "^15.5.0", + "react-syntax-highlighter": "12.2.1", "react-text-truncate": "^0.16.0", "react-twitter-embed": "^3.0.3", "react-typing-animation": "^1.6.2", diff --git a/pages/docs/tools/generator/_section.md b/pages/docs/tools/generator/_section.md new file mode 100644 index 000000000000..ba3fa2f6d39a --- /dev/null +++ b/pages/docs/tools/generator/_section.md @@ -0,0 +1,4 @@ +--- +title: Generator +weight: 3 +--- \ No newline at end of file diff --git a/pages/docs/tools/generator/api.md b/pages/docs/tools/generator/api.md new file mode 100644 index 000000000000..1e53742b7cd1 --- /dev/null +++ b/pages/docs/tools/generator/api.md @@ -0,0 +1,344 @@ +--- +title: Library API +weight: 75 +--- + +Reference API documentation for AsyncAPI Generator library. + + + +## Generator +**Kind**: global class + +* [Generator](#Generator) + * [new Generator(templateName, targetDir, options)](#new_Generator_new) + * _instance_ + * [.templateName](#Generator+templateName) : `String` + * [.targetDir](#Generator+targetDir) : `String` + * [.entrypoint](#Generator+entrypoint) : `String` + * [.noOverwriteGlobs](#Generator+noOverwriteGlobs) : `Array.` + * [.disabledHooks](#Generator+disabledHooks) : `Object.)>` + * [.output](#Generator+output) : `String` + * [.forceWrite](#Generator+forceWrite) : `Boolean` + * [.debug](#Generator+debug) : `Boolean` + * [.install](#Generator+install) : `Boolean` + * [.templateConfig](#Generator+templateConfig) : `Object` + * [.hooks](#Generator+hooks) : `Object` + * [.mapBaseUrlToFolder](#Generator+mapBaseUrlToFolder) : `Object` + * [.templateParams](#Generator+templateParams) : `Object` + * [.originalAsyncAPI](#Generator+originalAsyncAPI) : `String` + * [.generate(asyncapiDocument)](#Generator+generate) ⇒ `Promise` + * [.configureTemplate()](#Generator+configureTemplate) + * [.generateFromString(asyncapiString, [parserOptions])](#Generator+generateFromString) ⇒ `Promise` + * [.generateFromURL(asyncapiURL)](#Generator+generateFromURL) ⇒ `Promise` + * [.generateFromFile(asyncapiFile)](#Generator+generateFromFile) ⇒ `Promise` + * [.installTemplate([force])](#Generator+installTemplate) + * _static_ + * [.getTemplateFile(templateName, filePath, [templatesDir])](#Generator.getTemplateFile) ⇒ `Promise` + + + + +### new Generator +Instantiates a new Generator object. + +**Params** + +- templateName `String` - Name of the template to generate. +- targetDir `String` - Path to the directory where the files will be generated. +- options `Object` + - [.templateParams] `String` - Optional parameters to pass to the template. Each template define their own params. + - [.entrypoint] `String` - Name of the file to use as the entry point for the rendering process. Use in case you want to use only a specific template file. Note: this potentially avoids rendering every file in the template. + - [.noOverwriteGlobs] `Array.` - List of globs to skip when regenerating the template. + - [.disabledHooks] `Object.)>` - Object with hooks to disable. The key is a hook type. If key has "true" value, then the generator skips all hooks from the given type. If the value associated with a key is a string with the name of a single hook, then the generator skips only this single hook name. If the value associated with a key is an array of strings, then the generator skips only hooks from the array. + - [.output] `String` ` = 'fs'` - Type of output. Can be either 'fs' (default) or 'string'. Only available when entrypoint is set. + - [.forceWrite] `Boolean` ` = false` - Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir. Default is set to false. + - [.install] `Boolean` ` = false` - Install the template and its dependencies, even when the template has already been installed. + - [.debug] `Boolean` ` = false` - Enable more specific errors in the console. At the moment it only shows specific errors about filters. Keep in mind that as a result errors about template are less descriptive. + - [.mapBaseUrlToFolder] `Object.` - Optional parameter to map schema references from a base url to a local base folder e.g. url=https://schema.example.com/crm/ folder=./test/docs/ . + +**Example** +```js +const path = require('path'); +const generator = new Generator('@asyncapi/html-template', path.resolve(__dirname, 'example')); +``` +**Example** *(Passing custom params to the template)* +```js +const path = require('path'); +const generator = new Generator('@asyncapi/html-template', path.resolve(__dirname, 'example'), { + templateParams: { + sidebarOrganization: 'byTags' + } +}); +``` + + + +* generator.templateName : `String`** : +Name of the template to generate. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.targetDir : `String`** : +Path to the directory where the files will be generated. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.entrypoint : `String`** : +Name of the file to use as the entry point for the rendering process. Use in case you want to use only a specific template file. Note: this potentially avoids rendering every file in the template. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.noOverwriteGlobs : `Array.`** : +List of globs to skip when regenerating the template. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.disabledHooks : `Object.)>`** : +Object with hooks to disable. The key is a hook type. If key has "true" value, then the generator skips all hooks from the given type. If the value associated with a key is a string with the name of a single hook, then the generator skips only this single hook name. If the value associated with a key is an array of strings, then the generator skips only hooks from the array. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.output : `String`** : +Type of output. Can be either 'fs' (default) or 'string'. Only available when entrypoint is set. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.forceWrite : `Boolean`** : +Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir. Default is set to false. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.debug : `Boolean`** : +Enable more specific errors in the console. At the moment it only shows specific errors about filters. Keep in mind that as a result errors about template are less descriptive. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.install : `Boolean`** : +Install the template and its dependencies, even when the template has already been installed. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.templateConfig : `Object`** : +The template configuration. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.hooks : `Object`** : +Hooks object with hooks functions grouped by the hook type. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.mapBaseUrlToFolder : `Object`** : +Maps schema URL to folder. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.templateParams : `Object`** : +The template parameters. The structure for this object is based on each individual template. + +**Kind**: instance property of [`Generator`](#Generator) + + + +* generator.originalAsyncAPI : `String`** : +AsyncAPI string to use as a source. + +**Kind**: instance property of [`Generator`](#Generator) + + + +### generator.generate +Generates files from a given template and an AsyncAPIDocument object. + +**Kind**: instance method of [`Generator`](#Generator) +**Params** + +- asyncapiDocument `AsyncAPIDocument` - AsyncAPIDocument object to use as source. + +**Example** +```js +generator + .generate(myAsyncAPIdocument) + .then(() => { + console.log('Done!'); + }) + .catch(console.error); +``` +**Example** *(Using async/await)* +```js +try { + await generator.generate(myAsyncAPIdocument); + console.log('Done!'); +} catch (e) { + console.error(e); +} +``` + + + +* generator.configureTemplate()** : +Configure the templates based the desired renderer. + +**Kind**: instance method of [`Generator`](#Generator) + + + +### generator.generateFromString +Generates files from a given template and AsyncAPI string. + +**Kind**: instance method of [`Generator`](#Generator) +**Params** + +- asyncapiString `String` - AsyncAPI string to use as source. +- [parserOptions] `Object` ` = {}` - AsyncAPI parser options. Check out [@asyncapi/parser](https://www.github.com/asyncapi/parser-js) for more information. + +**Example** +```js +const asyncapiString = ` +asyncapi: '2.0.0' +info: + title: Example + version: 1.0.0 +... +`; +generator + .generateFromString(asyncapiString) + .then(() => { + console.log('Done!'); + }) + .catch(console.error); +``` +**Example** *(Using async/await)* +```js +const asyncapiString = ` +asyncapi: '2.0.0' +info: + title: Example + version: 1.0.0 +... +`; + +try { + await generator.generateFromString(asyncapiString); + console.log('Done!'); +} catch (e) { + console.error(e); +} +``` + + + +### generator.generateFromURL +Generates files from a given template and AsyncAPI file stored on external server. + +**Kind**: instance method of [`Generator`](#Generator) +**Params** + +- asyncapiURL `String` - Link to AsyncAPI file + +**Example** +```js +generator + .generateFromURL('https://example.com/asyncapi.yaml') + .then(() => { + console.log('Done!'); + }) + .catch(console.error); +``` +**Example** *(Using async/await)* +```js +try { + await generator.generateFromURL('https://example.com/asyncapi.yaml'); + console.log('Done!'); +} catch (e) { + console.error(e); +} +``` + + + +### generator.generateFromFile +Generates files from a given template and AsyncAPI file. + +**Kind**: instance method of [`Generator`](#Generator) +**Params** + +- asyncapiFile `String` - AsyncAPI file to use as source. + +**Example** +```js +generator + .generateFromFile('asyncapi.yaml') + .then(() => { + console.log('Done!'); + }) + .catch(console.error); +``` +**Example** *(Using async/await)* +```js +try { + await generator.generateFromFile('asyncapi.yaml'); + console.log('Done!'); +} catch (e) { + console.error(e); +} +``` + + + +### generator.installTemplate +Downloads and installs a template and its dependencies + +**Kind**: instance method of [`Generator`](#Generator) +**Params** + +- [force] `Boolean` ` = false` - Whether to force installation (and skip cache) or not. + + + + +### Generator.getTemplateFile +Returns the content of a given template file. + +**Kind**: static method of [`Generator`](#Generator) +**Params** + +- templateName `String` - Name of the template to generate. +- filePath `String` - Path to the file to render. Relative to the template directory. +- [templatesDir] `String` ` = DEFAULT_TEMPLATES_DIR` - Path to the directory where the templates are installed. + +**Example** +```js +const Generator = require('@asyncapi/generator'); +const content = await Generator.getTemplateFile('@asyncapi/html-template', 'partials/content.html'); +``` +**Example** *(Using a custom `templatesDir`)* +```js +const Generator = require('@asyncapi/generator'); +const content = await Generator.getTemplateFile('@asyncapi/html-template', 'partials/content.html', '~/my-templates'); +``` diff --git a/pages/docs/tools/generator/asyncapi-document.md b/pages/docs/tools/generator/asyncapi-document.md new file mode 100644 index 000000000000..8e487ab74e2c --- /dev/null +++ b/pages/docs/tools/generator/asyncapi-document.md @@ -0,0 +1,87 @@ +--- +title: "AsyncAPI document" +weight: 40 +--- + +The **AsyncAPI document** defines a standard, protocol-agnostic interface that describes message-based or event-driven APIs. The AsyncAPI document allows people or machines communicating with one another, to understand the capabilities of an event-driven API without requiring access to the source code, documentation, or inspecting the network traffic. + +This document allows you to define your API structures and formats, including channels the end user can subscribe to and the message formats they receive. + +The documents describing the message-driven API under the AsyncAPI specification are represented as JSON objects and conform to JSON standards. YAML, a superset of JSON, can also be used to represent an API. + +> - To learn how to create an AsyncAPI document or refresh your knowledge about the syntax and structure of the AsyncAPI document, check out our [latest specification documentation](https://www.asyncapi.com/docs/reference/specification/latest). +> - You can develop, validate, and convert the AsyncAPI document to the latest version or preview your AsyncAPI document in a more readable way using the [AsyncAPI Studio](https://studio.asyncapi.com/). + +In the following sections, you'll learn about the inner working of the generator, what happens once the AsyncAPI document is fed to the generator, and how you can access the content of the document in your template. + +## AsyncAPI document generation process +1. The **Generator** receives the **AsyncAPI Document** as input. +2. The **Generator** sends to the **[Parser](parser)** the **asyncapiString** is a stringified version of the original **AsyncAPI Document** to validate and parse it. +3. The **Parser** validates the **AsyncAPI Document** using additional schema-related plugins, either the OpenAPI schema, RAML data types, or Avro schema. +4. If the **Parser** determines that the **AsyncAPI Document** is valid, it manipulates the original JSON/YAML document and provides a set of helper functions in return, bundling them together into an **asyncapi** variable that is an instance of [**AsyncAPIDocument**](https://github.com/asyncapi/parser-js/blob/master/API.md#module_@asyncapi/parser+AsyncAPIDocument). +5. At this point, the **Generator** passes the **originalAsyncAPI** and the **asyncapi** which make up part of the **[Template Context](asyncapi-context)** to the **Render Engine**. +6. The **Template Context** is accessible to the template files that are passed to either the [react](react-render-engine) or [nunjucks](nunjucks-render-engine) **Render Engines**. + +``` mermaid +graph LR + A[Template Context] + B{Generator} + C[Parser] + D[Render Engine] + E[AsyncAPI Document] --> B + subgraph Generator + B -->| asyncapiString | C + C --> | asyncapi -> AsyncAPIDocument type | A + B--> | originalAsyncAPI -> Stringified document | A + A --> D + end + ``` +The AsyncAPI document's content is accessible to you while writing your template in two distinct ways: +* The `originalAsyncAPI`, which is a stringified version of the AsyncAPI document provided as input, without any modifications. +* The `asyncapi` (`AsyncAPIDocument`) which is an object with a set of helper functions, that comes as a result of the `Parser` manipulating the `originalAyncAPI` .The `asyncapi` functions make it easier to access the contents of AsyncAPI documents in your templates. + +In the following sections, you will learn how to use either the **originalAsyncAPI** or the **asyncapi** in your template. + +### Method 1: `originalAsyncAPI` and template +One way of using the contents of the AsyncAPI document inside your template files is by using its stringified version that reflects the same contents as the AsyncAPI document provided as input to the generator. You can access it directly in your templates using the `originalAsyncAPI` variable. You also access it via the [hooks](hooks) `generator.originalAsyncAPI` because `originalAsyncAPI` is also a part of the generator instance that is passed to hooks. + +```js +//example use case for using a stringified AsyncAPI document inside template hooks + +const fs = require('fs'); +const path = require('path'); + +function createAsyncapiFile(generator) { + const asyncapi = generator.originalAsyncAPI; + let extension; + + try { + JSON.parse(asyncapi); + extension = 'json'; + } catch (e) { + extension = 'yaml'; + } + + const outputFileName = `asyncapi.${extension}`; + + const asyncapiOutputLocation = path.resolve('./'', outputFileName); + + fs.writeFileSync(asyncapiOutputLocation, asyncapi); +``` + + +### Method 2: `asyncapi` and template +A major advantage of using `asyncapi` (which is an instance of `AsyncAPIDocument`) is that it enables the developer to easily access the AsyncAPI documents' content by simply invoking a function. + +Once the specification YAML or JSON document is passed as input to the generator, it is passed on to the [Parser](parser) library, which then manipulates the asyncAPI document to a more structured document called the `AsyncAPIDocument`. Once the parser returns the document to the generator, the generator passes it to the render engine. The render engine makes the `AsyncAPIDocument` object accessible to your template through the `asyncapi` variable. + +For example, if you want to extract the version of your API from AsyncAPI document, you can do that by calling `asyncapi.version()`. You can say that this one is easy to access from JSON objects, but there are more complex scenarios. For example, to get access to all messages from all channels, you can call `asyncapi.allMessages()` instead of iterating through a complex JSON object on your own. + +In the sample code snippet below, notice how you can access the contents of the AsyncAPI document in your template using `asyncapi` variable from the context: + +```js + const apiName = asyncapi.info().title(); + const channels = asyncapi.channels(); +``` + +> To learn about the various instances you can use to access the documents' content, look at the API of the AsyncAPI JavaScript Parser and the structure of [AsyncAPIDocument](https://github.com/asyncapi/parser-js/blob/master/API.md#module_@asyncapi/parser+AsyncAPIDocument) diff --git a/pages/docs/tools/generator/configuration-file.md b/pages/docs/tools/generator/configuration-file.md new file mode 100644 index 000000000000..37650fef5c70 --- /dev/null +++ b/pages/docs/tools/generator/configuration-file.md @@ -0,0 +1,78 @@ +--- +title: "Configuration file" +weight: 90 +--- + +The `generator` property from `package.json` file must contain a JSON object that may have the following information: + +|Name|Type|Description| +|---|---|---| +|`renderer`| String | Its value can be either `react` or `nunjucks` (default). +|`supportedProtocols`| [String] | A list with all the protocols this template supports. +|`parameters`| Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`. +|`parameters[param].description`| String | A user-friendly description about the parameter. +|`parameters[param].default`| Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters. +|`parameters[param].required`| Boolean | Whether the parameter is required or not. +|`conditionalFiles`| Object[String, Object] | An object containing all the file paths that should be conditionally rendered. Each key represents a file path and each value must be an object with the keys `subject` and `validation`. The file path should be relative to the `template` directory inside the template. +|`conditionalFiles[filePath].subject`| String | The `subject` is a [JMESPath](http://jmespath.org/) query to grab the value you want to apply the condition to. It queries an object with the whole AsyncAPI document and, when specified, the given server. The object looks like this: `{ asyncapi: { ... }, server: { ... } }`. If the template supports `server` parameter, you can access server details like for example protocol this way: `server.protocol`. During validation with `conditionalFiles` only the server that template user selected is available in the specification file. For more information about `server` parameter [read about special parameters](#special-parameters). +|`conditionalFiles[filePath].validation`| Object | The `validation` is a JSON Schema Draft 07 object. This JSON Schema definition will be applied to the JSON value resulting from the `subject` query. If validation doesn't have errors, the condition is met, and therefore the given file will be rendered. Otherwise, the file is ignored. Check [JSON Schema Validation](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.6) document for a list of all possible validation keywords. +|`nonRenderableFiles`| [String] | A list of file paths or [globs](https://en.wikipedia.org/wiki/Glob_(programming)) that must be copied "as-is" to the target directory, i.e., without performing any rendering process. This is useful when you want to copy binary files. +|`generator`| [String] | A string representing the generator version-range the template is compatible with. This value must follow the [semver](https://nodejs.dev/learn/semantic-versioning-using-npm) syntax. E.g., `>=1.0.0`, `>=1.0.0 <=2.0.0`, `~1.0.0`, `^1.0.0`, `1.0.0`, etc. [Read more about semver](https://docs.npmjs.com/about-semantic-versioning). +|`filters`| [String] | A list of modules containing functions that can be used as Nunjucks filters. In case of external modules, remember they need to be added as a dependency in `package.json` of your template. +|`hooks`| Object[String, String] or Object[String, Array[String]] | A list of modules containing hooks, except for the ones you keep locally in your template in default location. For each module you must specify the exact name of the hook that should be used in the template. For a single hook you can specify it as a string, for more you must pass an array of strings. In case of external modules, remember they need to be added as a dependency in `package.json` of your template. + +### Example + +```json +"generator": +{ + "renderer": "react", + "supportedProtocols": ["amqp", "mqtt"], + "parameters": { + "server": { + "description": "The server you want to use in the code.", + "required": true + }, + "dummyParameter": { + "description": "Example of parameter with default value.", + "default": "just a string", + "required": false + } + }, + "conditionalFiles": { + "path/to/file/that/is/relative/to/template/dir/test-amqp.js": { + "subject": "server.protocol", + "validation": { + "const": "amqp" + } + }, + "path/to/file/that/is/relative/to/template/dir/support.html": { + "subject": "info.contact", + "validation": { + "required": ["url"] + } + } + }, + "nonRenderableFiles": [ + "src/api/middlewares/*.*", + "lib/lib/config.js" + ], + "generator": "<2.0.0", + "filters": [ + "@asyncapi/generator-filters" + ], + "hooks": { + "@asyncapi/generator-hooks": "hookFunctionName" + } +} +``` + +## Special parameters + +There are some template parameters that have a special meaning: + +|Name|Description| +|---|---| +|`server`| It is used to let the template know which server from the AsyncAPI specification file you want to use. In some cases, this may be required. For instance, when generating code that connects to a specific server. Use this parameter in case your template relies on users' information about what server from the specification file they want to use during generation. You also need this parameter if you want to use `server.protocol` notation within `conditionalFiles` configuration option. Once you decide to specify this parameter for your template, it is recommended you make it a mandatory parameter otherwise a feature like `conditionalFiles` is not going to work if your users do not use this parameter obligatory. + + diff --git a/pages/docs/tools/generator/file-templates.md b/pages/docs/tools/generator/file-templates.md new file mode 100644 index 000000000000..d84c7d3a37a4 --- /dev/null +++ b/pages/docs/tools/generator/file-templates.md @@ -0,0 +1,67 @@ +--- +title: "File templates" +weight: 140 +--- + +It is possible to generate files for each specific object in your AsyncAPI documentation. For example, you can specify a filename like `$$channel$$.js` to generate a file for each channel defined in your AsyncAPI. The following file-template names and extra variables in them are available: + + - `$$channel$$`, within the template-file you have access to two variables [`channel`](https://github.com/asyncapi/parser-js/blob/master/API.md#Channel) and [`channelName`](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument+channels). Where the `channel` contains the current channel being rendered. + - `$$message$$`, within the template-file you have access to two variables [`message`](https://github.com/asyncapi/parser-js/blob/master/API.md#Message) and [`messageName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Message+uid). Where `message` contains the current message being rendered. + - `$$schema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. Only schemas from [Components object](https://www.asyncapi.com/docs/specifications/2.0.0/#a-name-componentsobject-a-components-object) are used. + - `$$everySchema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. Every [Schema object](https://www.asyncapi.com/docs/specifications/2.0.0/#schemaObject) from the entire AsyncAPI file is used. + - `$$objectSchema$$`, within the template-file you have access to two variables [`schema`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema) and [`schemaName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Schema+uid). Where `schema` contains the current schema being rendered. All the [Schema objects](https://www.asyncapi.com/docs/specifications/2.0.0/#schemaObject) with type object is used. + - `$$parameter$$`, within the template-file you have access to two variables [`parameter`](https://github.com/asyncapi/parser-js/blob/master/API.md#ChannelParameter) and [`parameterName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Channel+parameters). Where the `parameter` contains the current parameter being rendered. + - `$$securityScheme$$`, within the template-file you have access to two variables [`securityScheme`](https://github.com/asyncapi/parser-js/blob/master/API.md#SecurityScheme) and [`securitySchemeName`](https://github.com/asyncapi/parser-js/blob/master/API.md#Components+securitySchemes). Where `securityScheme` contains the current security scheme being rendered. + +The file name will be equal to `*Name` variable. + +### Example + +The file name is `$$schema$$.txt`, the content of this file is: +``` +Schema name is '{{schemaName}}' and properties are: +{% for propName, prop in schema.properties() %} +- {{prop.uid()}} +{% endfor %} +``` + +With following AsyncAPI: +``` +components: + schemas: + peoplePayload: + type: object + properties: + event: + $ref: "#/components/schemas/people" + people: + type: object + properties: + id: + type: integer +``` + +The generator creates two files `peoplePayload.txt` and `people.txt` with the following content: +``` +Schema name is 'peoplePayload' and properties are: +- people +``` + +and +``` +Schema name is 'people' and properties are: +- id +``` + +### React + +The above way of rendering **file templates** works for both `nunjucks` and `react` render engines, but `react` also has another, more generic way to render multiple files. It is enough to return an array of `File` components in the rendering component. See the following example: + +```tsx +export default function({ asyncapi }) { + return [ + Content, + Content + ] +} +``` \ No newline at end of file diff --git a/pages/docs/tools/generator/hooks.md b/pages/docs/tools/generator/hooks.md new file mode 100644 index 000000000000..5d294a1c01a7 --- /dev/null +++ b/pages/docs/tools/generator/hooks.md @@ -0,0 +1,81 @@ +--- +title: "Hooks" +weight: 130 +--- + +Hooks are functions called by the generator on a specific moment in the generation process. Hooks can be anonymous functions but you can also add function names. These hooks can have arguments provided to them or being expected to return a value. +The following types of hooks are currently supported: + +|Hook type|Description| Return type | Arguments +|---|---|---|---| +| `generate:before` | Called after registration of all filters and before the generator starts processing of the template. | void : Nothing is expected to be returned. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md) +| `generate:after` | Called at the very end of the generation. | void : Nothing is expected to be returned. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md) +| `setFileTemplateName ` | Called right before saving a new file generated by [file template](./file-templates.md). | string : a new filename for the generator to use for the file template. | [The generator instance](https://github.com/asyncapi/generator/blob/master/docs/api.md) and object in the form of `{ "originalFilename" : string }` + +The generator parses: +- All the files in the `.hooks` directory inside the template. +- All modules listed in the template configuration and triggers only hooks that names were added to the config. You can use the official AsyncAPI [hooks library](https://github.com/asyncapi/generator-hooks). To learn how to add hooks to configuration [read more about the configuration file](#configuration-file). + +### Examples + +> Some of the examples have names of hook functions provided and some not. Keep in mind that hook functions kept in template in default location do not require a name. Name is required only if you keep hooks in non default location or in a separate library, because such hooks need to be explicitly configured in the configuration file. For more details on hooks configuration [read more about the configuration file](#configuration-file). + +Most basic modules with hooks look like this: +```js +module.exports = { + 'generate:after': generator => console.log('This runs after generation is complete') +} +``` + +Below you have an example Hook that after generation creates an AsyncAPI file. + +```js +const fs = require('fs'); +const path = require('path'); + +module.exports = { + 'generate:after': generator => { + const asyncapi = generator.originalAsyncAPI; + let extension; + + try { + JSON.parse(asyncapi); + extension = 'json'; + } catch (e) { + extension = 'yaml'; + } + + fs.writeFileSync(path.resolve(generator.targetDir, `asyncapi.${extension}`), asyncapi); + } +}; +``` +And here an example Hook that before generation switches `publish` and `subscribe` operations for each channel. + +```js +module.exports = { + 'generate:before': function switchOperations(generator) { + const asyncapi = generator.asyncapi; + for (let [key, value] of Object.entries(asyncapi.channels())) { + let publish = value._json.publish; + value._json.publish = value._json.subscribe; + value._json.subscribe = publish; + if (!value._json.subscribe) { + delete value._json.subscribe; + } + if (!value._json.publish) { + delete value._json.publish; + } + } + }; +}; +``` + +Example hook for changing the filename of a template file. Replaces all '-' characters with '_'. +```js +module.exports = { + 'setFileTemplateName': (generator, hookArguments) => { + const currentFilename = hookArguments.originalFilename ; + return currentFilename.replace('-', '_') + }; +}; +``` \ No newline at end of file diff --git a/pages/docs/tools/generator/index.md b/pages/docs/tools/generator/index.md new file mode 100644 index 000000000000..2789cc747875 --- /dev/null +++ b/pages/docs/tools/generator/index.md @@ -0,0 +1,53 @@ +--- +title: "Introduction" +weight: 10 +--- + +The AsyncAPI generator is a tool that generates anything you want using the **[AsyncAPI Document](generator/asyncapi-documents)** and **[Template](generator/template)** that are supplied as inputs to the AsyncAPI CLI. The generator was built with extensibility in mind; you can use the generator to generate anything you want, provided that it can be defined in a template, such as code, diagrams, markdown files, microservices, and applications. A number of [community-maintained templates](https://github.com/search?q=topic%3Aasyncapi+topic%3Agenerator+topic%3Atemplate) are now available for immediate usage. + +### Generator use cases +- Generation of interactive and understandable API documentation +- Generation of APIs' client libraries +- Generation of APIs' boilerplate code + +### Generator advantages +- Quick to setup and easy to use on a regular basis +- Effortless generation of complex documents +- Number of community maintained AsyncAPI templates + +### Generation process +1. The **Generator** receives the **[Template](generator/template)** and **[AsyncAPI Document](generator/asyncapi-document)** as inputs. +2. The **Generator** sends to the **[Parser](generator/parser)** the **asyncapiString** which is a stringified version of the original **AsyncAPI Document**. +3. The **Parser** uses additional plugins such as the OpenAPI, RAML, or Avro schemas to validate custom schemas of message payloads defined in the **AsyncAPI Document**. +4. If the **Parser** determines that the original **AsyncAPI Document** is valid, it manipulates the document and returns a set of helper functions and properties and bundles them together into an **asyncapi** variable that is an instance of [**AsyncAPIDocument**](https://github.com/asyncapi/parser-js/blob/master/API.md#module_@asyncapi/parser+AsyncAPIDocument). The **asyncapi** helper functions make it easier to access the contents of the AsyncAPI Document. +5. At this point, the **Generator** passes the **[asyncapi](generator/asyncapi-document#method-2-asyncapi-and-template)**, the **[originalAsyncAPI](generator/asyncapi-document#method-1-originalasyncapi-and-template)**, and the **params** which collectively make up the **[Template Context](generator/asyncapi-context)** to the **Render Engine**. +6. AsyncAPI has two **Render Engines**([react](generator/react-render-engine) and [nunjucks](generator/nunjucks-render-engine). Depending on which one you've specified in your `package.json`, the **Generator** knows the right **Render Engine** to pass both the **Template Files** and the **Template Context**. +7. Once the **Render Engine** receives the **Template Files** and the **Template Context**, it injects all the dynamic values in your react or nunjucks based **Template Files** using the **Template Context**. As a result, the **Render Engine** generates **markdown**, **pdf**, **boilerplate code**, and **anything else** you specified to be generated as output. + +> You can generate anything you want using the generator as long as it can be defined in a **Template**. + +The diagram below depicts the entire process of passing the **Template** and **AsyncAPI Document** to the AsyncAPI generator tool, how the generator uses these inputs to generate the desired output, and example outputs you can get from the render engine. + +``` mermaid +graph LR + A[Template Context] + B{Generator} + C[Parser] + D[Render Engine] + E[AsyncAPI Document] --> B + F[Template] --> B + subgraph Generator Library + B -->| asyncapiString | C + C --> | asyncapi | A + B--> | originalAsyncAPI | A + B--> | params | A + A --> D + B --> | Template Files | D + end + D --> O[HTML] + D --> M[Markdown] + D --> N[Node.js] + D --> J[Java Spring Boot] + D --> K[Anything else] + ``` +**`params`** are template-specific options passed to the `asyncapi generate fromTemplate` CLI command to customize the generated output. \ No newline at end of file diff --git a/pages/docs/tools/generator/installation-guide.md b/pages/docs/tools/generator/installation-guide.md new file mode 100644 index 000000000000..69e81b53ff43 --- /dev/null +++ b/pages/docs/tools/generator/installation-guide.md @@ -0,0 +1,81 @@ +--- +title: "Installation guide" +weight: 20 +--- + +You can use the generator library to generate whatever you want in your event-driven architecture apps. Find your preferred method below: +- [AsyncAPI CLI](#asyncapi-cli) +- [Generator library in Node.js apps](#generator-library-in-nodejs-apps) + +## Prerequisites +Before you install and use the AsyncAPI CLI and the generator library, ensure you meet the prerequisites below, then [install the CLI](#installation). +1. Node.js v12.16 and higher +2. Npm v6.13.7 and higher + +To verify the versions of Node and Npm you have, run the following command on your terminal: +``` +npm -v +``` +``` +node -v +``` + +If you don't have either Node or Npm installed, use the [official node.js installer](https://nodejs.org/en/download/). + +If you have the correct versions installed, proceed to the CLI installation guide below. Otherwise, upgrading the Npm or Node version is lower than the recommended versions specified above. + +## AsyncAPI CLI +The AsyncAPI CLI tool allows you to do many different things with the [AsyncAPI document](asyncapi-document). You can generate message-based API boilerplate code, documentation, or anything else you need as long as you specify it in your [template](template) or the existing template already supports it. To use the generator via the AsyncAPI CLI, you need to install the AsyncAPI CLI tool. + +### Installation + +#### Install AsyncAPI CLI using NPM + +The AsyncAPI CLI is a NodeJS project, so the easiest way to install it is by using the following `npm` command: +``` +npm install -g @asyncapi/cli +``` + +To install a specific version of the generator tool, pass the version during installation: +``` +npm install -g @asyncapi/cli@{version} +``` + +#### MacOS +You can install in MacOS by using brew: `brew install asyncapi`. + +#### Linux +You can install in Linux by using `dpkg`, a package manager for debian: +1. `curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.deb` +2. `sudo dpkg -i asyncapi.deb` + +#### Other operating systems +For further installation instructions for different operating systems, read the [AsyncAPI CLI documentation](https://github.com/asyncapi/cli#installation). + +> **Remember:** +> Each [community-developed template](https://github.com/search?q=topic%3Aasyncapi+topic%3Agenerator+topic%3Atemplate) is dependent on a certain version of the generator for it to work correctly. Before you install the generator CLI, check the template's `package.json` for the version of the generator CLI your template is compatible with. Read the [versioning docs](versioning) to learn why it's important to use certain generator versions with your templates. + +### Update AsyncAPI CLI +There are several reasons why you might want to update your generator version: +* You have the generator tool installed but want to use the latest released features. To upgrade to the latest version, use the command below: +``` +npm install -g @asyncapi/cli +``` +* If your template isn't compatible with the latest generator version, you can update it to a specific version of the generator. Check the [version you need](https://github.com/asyncapi/cli/releases) and specify the version you want by using the **@** symbol as shown in the command below: +``` +npm install -g @asyncapi/cli@{version} +``` +> Sometimes you have to force additional npm installation like this: `npm install -g --force @asyncapi/cli` + +### Uninstall AsyncAPI CLI +To uninstall the generator, use the following command: +``` +npm uninstall @asyncapi/cli -g +``` + +> :memo: **Note:** To use the generator in your CI/CD pipeline to automate whatever you generate for your event-driven architecture apps, install the AsyncAPI CLI in your pipeline. If you are using GitHub Actions, use [Github Actions for Generator](https://github.com/marketplace/actions/generator-for-asyncapi-documents). + +## Generator library in Node.js apps +Use the generator library in your Node.js projects by installing it via the following command: `npm install @asyncapi/generator`. + +> Don't include the `-g` flag in the installation command above since you're not installing the generator library globally but in your Node.js project. diff --git a/pages/docs/tools/generator/nunjucks-render-engine.md b/pages/docs/tools/generator/nunjucks-render-engine.md new file mode 100644 index 000000000000..727cd2121883 --- /dev/null +++ b/pages/docs/tools/generator/nunjucks-render-engine.md @@ -0,0 +1,78 @@ +--- +title: "Nunjucks render engine" +weight: 120 +--- + +[Nunjucks](https://mozilla.github.io/nunjucks) is the default render engine, however, we strongly recommend adopting the [React](#react) engine. + +### Common assumptions + +1. Templates may contain [Nunjucks filters or helper functions](https://mozilla.github.io/nunjucks/templating.html#builtin-filters). [Read more about filters](#filters). +1. Templates may contain `partials` (reusable chunks). They must be stored in the `.partials` directory under the template directory. [Read more about partials](#partials). +1. Templates may contain multiple files. Unless stated otherwise, all files will be rendered. +1. The default variables you have access to in any the template file are the following: + - `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument) of the Parser to understand what structure you have access to in this parameter. + - `originalAsyncAPI` that is an original spec file before it is parsed. + - `params` that contain the parameters provided when generating. + +### Partials + +Files from the `.partials` directory do not end up with other generated files in the target directory. In this directory you should keep reusable templates chunks that you can [include](https://mozilla.github.io/nunjucks/templating.html#include) in your templates. You can also put there [macros](https://mozilla.github.io/nunjucks/templating.html#macro) to use them in templates, like in below example: + +```html +{# tags.html #} +{% macro tags(tagList) %} +
        + {% for tag in tagList %} + {{tag.name()}} + {% endfor %} +
        +{% endmacro %} + +{# operations.html #} +{% from "./tags.html" import tags %} +{{ tags(operation.tags()) }} +``` + +### Filters + +A filter is a helper function that you can create to perform complex tasks. They are JavaScript files that register one or many [Nunjuck filters](https://mozilla.github.io/nunjucks/api.html#custom-filters). The generator parses all the files in the `filters` directory. Functions exported from these files are registered as filters. + +You can use the filter function in your template as in the following example: + +```js +const {{ channelName | camelCase }} = '{{ channelName }}'; +``` + +The generator also supports asynchronous filters. Asynchronous filters receive as the last argument a callback to resume rendering. Asynchronous filters must be annotated with the `async` keyword. Make sure to call the callback with two arguments: `callback(err, res)`. `err` can be `null`. See the following example of how to use asynchronous filters: + +```js +const filter = module.exports; + +async function asyncCamelCase(str, callback) { + try { + const result = // logic for camel casing str + callback(null, result); + } catch (error) { + callback(error); + } +} +filter.renderAsyncContent = renderAsyncContent; + +// using in template +{{ channelName | asyncCamelCase }} +``` + +Unfortunately, if you need to use Promise, filter still must be annotated with the `async` keyword: + +```js +async function asyncCamelCase(str, callback) { + return new Promise((resolve, reject) => { + // logic with callback + }); +} +``` + +In case you have more than one template and want to reuse filters, you can put them in a single library. You can configure such a library in the template configuration under `filters` property. You can also use the official AsyncAPI [filters library](https://github.com/asyncapi/generator-filters). To learn how to add such filters to configuration [read more about the configuration file](#configuration-file). + + diff --git a/pages/docs/tools/generator/parser.md b/pages/docs/tools/generator/parser.md new file mode 100644 index 000000000000..2ff57070adeb --- /dev/null +++ b/pages/docs/tools/generator/parser.md @@ -0,0 +1,96 @@ +--- +title: "Parser" +weight: 60 +--- + +## Parser + +The AsyncAPI Parser is a package used to parse and validate the [AsyncAPI documents](asyncapi-document.md) in your Node.js or browser application. These documents can be either in YAML or JSON format. + +The Parser validates these documents using dedicated schema-supported plugins. + +Supported schemas: + +- AsyncAPI schema (no plugin needed) +- OpenAPI schema +- JSON schema +- Avro schema +- RAML data-type schema + +The Parser allows the template developer to easily access schemas provided in the above supported formats. This is because the JavaScript parser converts all of them into JSON schema. + +If the document is valid, the Parser returns an `AsyncAPIDocument instance` with a set of helper functions that enable easier access to the contents of the AsyncAPI document. The parser provides dereferenced output. During the dereference process, the AsyncAPI parser substitutes a reference with a full definition. The dereferenced output is always in JSON format. The parser provides a message listing all errors if a document is invalid. The original AsyncAPI document is part of the [Template Context](template-context.md) as the generator also passes the original AsyncAPI document to the template context. + +The following AsyncAPI document example has two channels: `channelOne` and `channelTwo`. Each channel has one operation and a single message: + +```yaml +asyncapi: '2.5.0' +info: + title: Demo API + version: '1.0.0' +channels: + channelOne: + publish: + summary: This is the first sample channel + operationId: onMessage + message: + name: FirstMessage + payload: + id: + type: integer + minimum: 0 + description: Id of the channel + sentAt: + type: string + format: date-time + description: Date and time when the message was sent. + channelTwo: + publish: + summary: This is the second sample channel + operationId: messageRead + message: + name: SecondMessage + payload: + id: + type: integer + minimum: 0 + description: Id of the channel + sentAt: + type: string + format: date-time + description: Date and time when the message was sent. +``` +We can use helper functions provided by the Parser to operate on the above JSON file. For example, we can use the helper method `asyncAPIDocument.channelNames()`, which returns an array of all channel names currently present in the AsyncAPI document. Another example where you can use a helper function is to list out messages present in your JSON file. Instead of fetching a single message one at a time, you can use the function `asyncAPIDocument.allMessages()` that returns the map of all messages in your AsyncAPI document. + +```js + const channelNames = asyncAPIDocument.channelNames(); + const messages = asyncAPIDocument.allMessages(); +``` + +> The Parser gives you access to a number of these [helper functions](https://github.com/asyncapi/parser-js/blob/master/API.md) that you can implement to access the contents of your AsyncAPI document. + +## AsyncAPI document validation process + +1. **AsyncAPI document** is fed as an input to the Generator. +1. Generator sends the AsyncAPI document to the Parser as **asyncapiString**; the stringified version of the original AsyncAPI document. +1. The Parser uses additional plugins such as the OpenAPI, RAML, or Avro schemas to validate custom schemas of message payloads defined in the AsyncAPI document. +1. If the AsyncAPI document is invalid, it throws an error based on the encountered failure type. For example, if the AsyncAPI document is not a string nor a JavaScript object, the Parser throws an `invalid-document-type` error. + Similarly, you may encounter errors such as: + - `invalid-json` + - `invalid-yaml` + - `impossible-to-convert-to-json` +1. If the document is valid, the Parser modifies the AsyncAPI document, returns a set of helper functions, and bundles them together into the **asyncapi** variable. These helper functions in the form of an **asyncapi** variable are passed to the **Template Context**. +1. The Template Context passes all of these values to the [**Render Engine**](react-render-engine.md) of your choice. Finally, the Render Engine generates whatever output you may have specified in your template. (i.e. code, documentation, diagrams, pdfs, applications, etc.) + +```mermaid +graph TD + A[AsyncAPI document] --> B + B[Generator] -->|asyncapiString| C(Parser) + C --> D{Validation} + D -->|invalid| B + D -->|asyncapi -> helper functions| E[Template Context] + E --> F[Render Engine] +``` + +> To learn more about the Parser and access all of its features, check out the AsyncAPI [Parser’s GitHub repository](https://github.com/asyncapi/parser-js). + diff --git a/pages/docs/tools/generator/react-render-engine.md b/pages/docs/tools/generator/react-render-engine.md new file mode 100644 index 000000000000..b985bee7f380 --- /dev/null +++ b/pages/docs/tools/generator/react-render-engine.md @@ -0,0 +1,80 @@ +--- +title: "React render engine" +weight: 110 +--- + +[React](https://reactjs.org) is the render engine that we strongly suggest you should use for any new templates. The only reason it is not the default render engine is to stay backward compatible. + +* It enables the possibility of [debugging](#debugging-react-template) your template (this is not possible with Nunjucks). +* It provides better error stack traces. +* Provides better support for separating code into more manageable chunks/components. +* The readability of the template is much better compared to Nunjucks syntax. +* Better tool support for development. +* Introduces testability of components which is not possible with Nunjucks. + +When writing React templates you decide whether to use CommonJS, ES5, or ES6 modules since everything is bundled together before the rendering process takes over. We use our own React renderer which can be found in the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk). +There you can find information about how the renderer works or how we transpile your template files. + +Your React template always require `@asyncapi/generator-react-sdk` as a dependency. `@asyncapi/generator-react-sdk` is required to access the `File` component which is required as a root component for a file to be rendered. Furthermore it provides some common components to make your development easier, like `Text` or `Indent`. + +Let's consider a basic React template as the one below called `MyTemplate.js`: + +```js +import { File, Text } from "@asyncapi/generator-react-sdk"; + +export default function({ asyncapi, params, originalAsyncAPI }) { + return ( + + Some text that should render as is + + ); +} +``` + +The exported default function returns a `File` component as a root component which the generator uses to determine what file should be generated. In our case, we overwrite the default functionality of saving the file as `MyTemplate.js` but instead use the filename `asyncapi.md`. It is then specified that we should render `Some text that should render as is\n` within that file. Notice the `\n` character at the end, which is automatically added after the `Text` component. + +For further information about components, props etc. see the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk) + +### Common assumptions + +1. Generator renders all files located in the `template` directory if they meet the following conditions: + - `File` is the root component + - The file is not in the list of `nonRenderableFiles` in the template configuration +1. New lines are automatically added after each `Text` component. +1. The props you have access to in rendering function is: + - `asyncapi` that is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-js/blob/master/API.md#AsyncAPIDocument) of the Parser to understand what structure you have access to in this parameter. + - `originalAsyncAPI` that is an original spec file before it is parsed. + - `params` that contain the parameters provided when generating. +1. All the file templates are supported where the variables are provided after the default props as listed above. + +### Debugging React template in VSCode + +With React, it enables you to debug your templates. For Visual Studio Code, we have created a boilerplate [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to enable debug in your template. Add the following launch configuration: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Debug template", + "timeout": 10000, + "sourceMaps": true, + "args": [ + "./asyncapi.yml", + "./template", + "--output", + "./output", + "--install", + "--force-write" + ], + "program": "ag" + } + ] +} +``` + +Now replace `./asyncapi.yml` with your document of choice. Replace `./template` with the path to your React template. You can now debug your template by adding any breakpoints you want and inspect your code. + + diff --git a/pages/docs/tools/generator/special-file-names.md b/pages/docs/tools/generator/special-file-names.md new file mode 100644 index 000000000000..536eee841d5a --- /dev/null +++ b/pages/docs/tools/generator/special-file-names.md @@ -0,0 +1,11 @@ +--- +title: "Special file names" +weight: 160 +--- + +We use NPM behind the scenes to download and install the templates. Since NPM will not fetch files like `.gitignore`, you should name them differently. Luckily, the Generator will take care of renaming them back for you. The following is a table of the special file names: + +|Special file name|Output file name| +|---|---| +|`{.gitignore}`|`.gitignore`| +|`{.npmignore}`|`.npmignore`| \ No newline at end of file diff --git a/pages/docs/tools/generator/template-context.md b/pages/docs/tools/generator/template-context.md new file mode 100644 index 000000000000..b8f5c93409f9 --- /dev/null +++ b/pages/docs/tools/generator/template-context.md @@ -0,0 +1,41 @@ +--- +title: "Template context" +weight: 100 +--- + +While using the generator tool, you may want dynamic values populated to your templates and rendered in the output. The generator can achieve that using the **template context**. +The **template context** allows you to access the contents of the [AsyncAPI document](asyncapi-document.md) and inject dynamic values to the template files passed to the asyncAPI CLI during the generation process. The render engine then displays these dynamically assigned values in the output. + +## Generation process +1. The **Generator** receives **Template** and **params** as input. +2. The **Generator** sends to the **Parser** the **asyncapiString** which is a stringified version of the original **AsyncAPI document**. +3. The **Parser** validates the format of the **asyncapiString** using OpenAPI, RAML, or Avro schemas. +4. If the **asyncapiString** is valid, the **parser** manipulates it, returns a set of helper functions and properties, and bundles them into an **asyncapi** variable. The **asyncapi** variable is an instance of the **AsyncAPI document**. The helper functions and properties make it easier to access the contents of the **AsyncAPI document** in the template. +5. The **Generator** then passes the **params**, which are template-specific options used to customize the output, the **Template files**, and the **asyncapi** which collectively make up the **Template Context**. +6. The **Template Context** is then passed to the **Render Engine**. The **Render Engine** then injects all the dynamic values from the **Template Context** into the **Template files**. + +``` mermaid +graph LR + A[Template Context] + B{Generator} + C[Parser] + D[Render Engine] + E[Template] --> B + F[Params] --> B + G[AsyncAPI Document] --> B + subgraph Generator + B -->| params | A + B--> | asyncapiString| C + B -->| originalAsyncAPI | A + C --> | asyncapi -> AsyncAPIDocument type | A + B--> | Template Files | D + A --> D + end +``` + +## Template context +The extra context passed to the render engine during the generation process and made accessible in the templates includes: + +- **`originalAsyncAPI`** is a stringified version of the original AsyncAPI document that the user passed to the Generator. +- **`asyncapi`** is a parsed AsyncAPI document with helper functions and properties. You should use it to access document contents e.g `asyncapi.title`. +- **`params`** is an object with all the parameters passed to the Generator by the user. \ No newline at end of file diff --git a/pages/docs/tools/generator/template-development.md b/pages/docs/tools/generator/template-development.md new file mode 100644 index 000000000000..28d921526b38 --- /dev/null +++ b/pages/docs/tools/generator/template-development.md @@ -0,0 +1,153 @@ +--- +title: "Template development" +weight: 80 +--- + +## Minimum template requirements + +Let's break down the minimum template requirements: the `template` directory and a `package.json` file. + +> You can also check [Template for Generator Templates](https://github.com/asyncapi/template-for-generator-templates) project to see show-case template based on the AsyncAPI Generator. + +### `template` directory + +The `template` directory stores generated outputs in files. In other words, the generator processes all the files stored in this directory. + +```js +import { File, Text } from "@asyncapi/generator-react-sdk"; + +export default function({ asyncapi, params, originalAsyncAPI }) { +return ( + + My application's markdown file. + App name: **{ asyncapi.info().title() }** + +); +} +``` +### `package.json` file + +Before the generation process begins, the generator installs the template into its dependencies. A `package.json` file is necessary to identify the template name. + +The following block shows an example `package.json` file that points to the [React Render Engine](react-render-engine.md) and necessary dependencies: + +```json +{ + "name": "myTemplate", + "generator": { + "renderer": "react" + }, + "dependencies": { + "@asyncapi/generator-react-sdk": "^0.2.25" + } +} +``` + +The above example of a `template/index.js` file shows the generation process result. The user also receives an `asyncapi.md` file with hardcoded and dynamic (application title from the AsyncAPI document) information. + +Every template must depend on the [`@asyncapi/generator-react-sdk` package](https://github.com/asyncapi/generator-react-sdk), which contains a template file's basic components. + +## Additional configuration options + +You must configure the generator's `package.json` file to contain JSON objects with the required parameters for template configuration, such as: + +|Name|Type|Description| +|---|---|---| +|`renderer`| String | Its value can be either `react` or `nunjucks` (default). +|`supportedProtocols`| [String] | A list with all the protocols this template supports. +|`parameters`| Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`. +|`parameters[param].description`| String | A user-friendly description about the parameter. +|`parameters[param].default`| Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters. +|`parameters[param].required`| Boolean | Whether the parameter is required or not. + +The above table lists some configuration options that help the generator achieve a specific set of tasks throughout the generation process. The `generator` property from 'package.json' contains all the configuration information. To learn more about template configuration and various supported parameters, read the [generator configuration file](configuration-file.md). + +> Whenever you make a change to the package.json, make sure you perform an update by running `npm install`; this command synchronizes with the `package-lock.json` and validates the file. + +### `package.json` configuration options + +The following examples show some advanced configurations that we can use in our `package.json` file: + +```json +{ + "name": "myTemplate", + "generator": { + "renderer": "react", + "supportedProtocols": "mqtt" + }, + "dependencies": { + "@asyncapi/generator-react-sdk": "^0.2.25" + } +} +``` +The above `package.json` file has a newly added configuration called `supportedProtocols` which is set to `mqtt`. This configuration displays all the protocols that this template supports. You can have multiple supported protocols in our template. + +For example, if you want to generate an output using the above template, you need to have an AsyncAPI document with servers that use `mqtt` to generate your desired output. If your AsyncAPI document has server connections with `kafka`, the generation process will be terminated since the only supported protocol mentioned is `mqtt`. + +### Accessing template parameters + +Additionally, we can also have a configuration called `parameters`, which is an object with all the parameters that can be passed when generating the template: + +```json +{ + "name": "myTemplate", + "generator": { + "renderer": "react", + "supportedProtocols": "mqtt", + "parameters": { + "version": { + "description": "Overrides application version under `info.version` in the AsyncAPI document.", + "required": false + } + } + }, + "dependencies": { + "@asyncapi/generator-react-sdk": "^0.2.25" + } +} +``` + +The default version of your application is always fetched from your AsyncAPI document. The above configuration helps the template user override the existing version with a new one on the command line. + +The changes done in the template will be as follows: + +Original: + +```js +App name: **{ asyncapi.info().title() }** +``` + +Newer: + +```js +App name: **{ asyncapi.info().title() }** +Version is: **{params.version || asyncapi.info.version()}** +``` + +Now that you have added all the configuration options, you can start the generation process using the generator CLI. You can pass these parameters via the CLI: `--param name=value or -p name=value`. +The above configuration helps template users override the existing version with a new version on the command line. (Example: `-p version=2.0.0`) + +## Hooks + +[Hooks](hooks.md) enable templates to perform multiple tasks. You can add Hooks to your template as fractions of code. In the template, you must store it in the `hooks` directory under the template directory. You can also store it in other modules and external libraries or configure it inside the template. The generation process can perform multiple actions. + +**Templates** can perform multiple actions _before_ or _after_ the generation process with the help of **hooks**. + +Hooks help you change the specification version with the new `version` that you can pass before the generation process even begins: + +```js +module.exports = { + 'generate:before': ({ asyncapi, templateParams = {} }) => { + const version = templateParams.version || asyncapi.info().version(); + asyncapi._json.info.version = version; + } +}; +``` +This can be an even better alternative to overriding the `version` parameter we discussed in the previous section. A markdown document will be generated, and the AsyncAPI document passed to the generator will be returned with the overwritten version. + +The updated template looks like the following: + +```js +App name: **{ asyncapi.info().title() }** +Version: **{asyncapi.info.version()}** +``` diff --git a/pages/docs/tools/generator/template.md b/pages/docs/tools/generator/template.md new file mode 100644 index 000000000000..a08688e78ae0 --- /dev/null +++ b/pages/docs/tools/generator/template.md @@ -0,0 +1,73 @@ +--- +title: "Template" +weight: 50 +--- + +## Template + +A template is a project that specifies the generation process output by using the AsyncAPI generator and an [AsyncAPI document](asyncapi-file.md). These files describe the generation results depending on the AsyncAPI document's content. + +Examples outputs: + +- Code +- Documentation +- Markdown diagrams +- Python and Java applications + +A template is an independent Node.js project unrelated to the `generator` repository. AsyncAPI templates are managed, released, and published separately. You can also create templates and manage templates on your own. + +The generator uses the official [Arborist](https://www.npmjs.com/package/@npmcli/arborist) NPM library. (This means templates do not have to be published to package managers to use them.) Arborist helps the generator fetch the template's source code and use it for the generation process. + +You can store template projects on a local drive or as a `git` repository during the development process. + +## Template generation process + +1. Template is provided as input to the **Generator**. +2. **asyncapi** is the original AsyncAPI document injected into your template file by default. +3. **params** are the parameters you pass to the generator CLI. Later, you can also pass these **params** further to other components. +4. The generator passes both the original **asyncapi**, the original AsyncAPI document, and the **params** to the **Template Context**. +5. Concurrently, the generator passes **Template files** to the **Render engine** as well. AsyncAPI uses two render engines — _react_ and _nunjucks_. +6. Once the Render Engine receives both the Template Files and the Template Context, it injects all the dynamic values into your react or nunjucks engine, based on the Template Files using the Template Context. +7. The render engine generates whatever output you may have specified in your template. (i.e. code, documentation, diagrams, pdfs, applications, etc.) + +```mermaid +graph LR + A[Template Context] + B{Generator} + D[Render Engine] + F[Template] --> B + subgraph Generator Library + B --> | asyncapi | A + B--> | params | A + A --> D + B --> | Template Files | D + end +``` + +## Generator `templates` list + +AsyncAPI has a list of available templates to enhance your generation process. Templates are stored as repositories on AsyncAPI's official GitHub profile. + + + + +Template Name | Description | Source code +---|---|--- +`@asyncapi/nodejs-template` | Generates Node.js service that uses Hermes package | [Nodej.s template](https://github.com/asyncapi/nodejs-template) +`@asyncapi/nodejs-ws-template` | Generates Node.js service that supports WebSocket protocol only | [Node.js WebSocket template](https://github.com/asyncapi/nodejs-ws-template) +`@asyncapi/java-template` | Generates Java JMS application | [Java template](https://github.com/asyncapi/java-template) +`@asyncapi/java-spring-template` | Generates Java Spring service | [Java spring template](https://github.com/asyncapi/java-spring-template) +`@asyncapi/java-spring-cloud-stream-template` | Generates Java Spring Cloud Stream service | [Java spring cloud stream template](https://github.com/asyncapi/java-spring-cloud-stream-template) +`@asyncapi/python-paho-template` | Generates Python service that uses Paho library | [Python paho template](https://github.com/asyncapi/python-paho-template) +`@asyncapi/html-template` | Generates HTML documentation site | [HTML template](https://github.com/asyncapi/html-template) +`@asyncapi/markdown-template` | Generates documentation in Markdown file | [Markdown template](https://github.com/asyncapi/markdown-template) +`@asyncapi/ts-nats-template` | Generates TypeScript NATS client | [TypeScript/Node.js NATS template](https://github.com/asyncapi/ts-nats-template/) +`@asyncapi/go-watermill-template` | Generates Go client using Watermill | [GO watermill template](https://github.com/asyncapi/go-watermill-template) +`@asyncapi/dotnet-nats-template` | Generates .NET C# client using NATS | [.NET C# NATS template](https://github.com/asyncapi/dotnet-nats-template) + + + +> Some of these templates are maintained by various third-party organizations. The README file usually contains this information and more, such as configuration options the user can pass to the template, usage, technical requirements, etc. + +> Check out all our community [generator templates](https://github.com/search?q=topic%3Aasyncapi+topic%3Agenerator+topic%3Atemplate) + diff --git a/pages/docs/tools/generator/typescript-support.md b/pages/docs/tools/generator/typescript-support.md new file mode 100644 index 000000000000..5c785cd3ca2c --- /dev/null +++ b/pages/docs/tools/generator/typescript-support.md @@ -0,0 +1,13 @@ +--- +title: "TypeScript support" +weight: 150 +--- + +The AsyncAPI generator has TypeScript support for [hooks](#hooks) and Nunjucks's [filters](#filters). Assumptions: + +- Installing the `typescript` package and creating the` tsconfig.json` file isn't necessary. +- Source code of the hook/filter must have `.ts` extension. +- Each package related to the typings for TypeScript like `@types/node` must be installed in the template under `dependencies` array. This is because the Generator transpiles the TypeScript code on-the-fly while rendering the template, and cannot use packages under `devDependencies`. +- Each template should have `@types/node` package installed to enable support for typings for Node. + + diff --git a/pages/docs/tools/generator/usage.md b/pages/docs/tools/generator/usage.md new file mode 100644 index 000000000000..3315bf0fcaac --- /dev/null +++ b/pages/docs/tools/generator/usage.md @@ -0,0 +1,151 @@ +--- +title: "Usage" +weight: 30 +--- + +There are two ways to use the generator: +- [Generator CLI](#generator-cli) +- [Generator library](#using-as-a-modulepackage) + +## Generator CLI +```bash +Usage: asyncapi generate fromTemplate