diff --git a/.storybook/AsyncAPIStorybookTheme.ts b/.storybook/AsyncAPIStorybookTheme.ts new file mode 100644 index 000000000000..9213d73cd955 --- /dev/null +++ b/.storybook/AsyncAPIStorybookTheme.ts @@ -0,0 +1,42 @@ +import { create } from '@storybook/theming/create'; + +export default create({ + // Brand Information + brandTitle: 'AsyncAPI Initiative', + brandUrl: 'https://www.asyncapi.com/', + brandImage: 'img/logos/asyncapi-horizontal-white-logo.svg', + brandTarget: '_blank', + + // Typography + fontBase: '"Work Sans", sans-serif', + fontCode: 'monospace', + + + // Themes + base: 'dark', + + /* -- FULL THEME IS NOT BEING USED DUE TO LACK OF STORYBOOK SUPPORT FOR CUSTOMIZING THE SETTINGS & ACTIONS BAR BG/TEXTCOLOR INDEPENDENTLY. -- + colorPrimary: '#47BCEE', + colorSecondary: '#8851FB', + + // UI + appBg: '#1b1130', + appContentBg: '#ffffff', + appPreviewBg: '#ffffff', + appBorderColor: '#dfe6ea', + appBorderRadius: 4, + + // Text colors + textColor: '#ffffff', + textInverseColor: '#ffffff', + textMutedColor: '#5c6870', + inputTextColor: '#2e3438', + + // Toolbar + barTextColor: '#9E9E9E', + + // Toolbar default and active colors + booleanBg: '#dfe6ea', + booleanSelectedBg: '#8851FB' + */ +}); diff --git a/.storybook/manager.ts b/.storybook/manager.ts new file mode 100644 index 000000000000..cc32cf0e2e41 --- /dev/null +++ b/.storybook/manager.ts @@ -0,0 +1,6 @@ +import { addons } from '@storybook/manager-api'; +import AsyncAPIStorybookTheme from './AsyncAPIStorybookTheme'; + +addons.setConfig({ + theme: AsyncAPIStorybookTheme, +}); diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index c8e7c3b7f91b..29ac0d62998b 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,6 +1,7 @@ import React from "react"; import "../styles/globals.css"; import type { Preview } from "@storybook/react"; +import { themes } from '@storybook/theming'; import { Title, Subtitle, @@ -20,6 +21,7 @@ const preview: Preview = { }, }, docs: { + theme: themes.light, toc: { title: 'Table of contents', }, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1334921c2813..6a20e1c3395f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,20 @@ -# Contributing to AsyncAPI -We love your input! We want to make contributing to this project as easy and transparent as possible. +# Welcome to AsyncAPI -## Contribution recogniton +Welcome to our open-source project! We're excited to have you join our community and contribute to making our project better. Please follow this guide to ensure a smooth contribution process and maintain the quality of our codebase and documentation. -We use [All Contributors](https://allcontributors.org/docs/en/specification) specification to handle recognitions. For more details read [this](https://github.com/asyncapi/community/blob/master/recognize-contributors.md) document. +We encourage all contributors to familiarize themselves with these guidelines and actively participate in the project's growth. If you have any questions or need assistance, don't hesitate to contact the project maintainers or community members. -## Summary of the contribution flow +## Code of Conduct + +AsyncAPI has adopted a Code of Conduct (CoC) that we expect project participants to adhere to. Please [read the full CoC text](./CODE_OF_CONDUCT.md) to understand the expected behavior. + +## Our Development Process + +We use Github to host code, track issues, feature requests, and accept pull requests. + +## Contribution flow -The following is a summary of the ideal contribution flow. Please, note that Pull Requests can also be rejected by the maintainers when appropriate. +The following is a summary of the ideal contribution flow. ``` ┌───────────────────────┐ @@ -36,44 +43,70 @@ The following is a summary of the ideal contribution flow. Please, note that Pul └───────────────────────┘ ``` -## Code of Conduct -AsyncAPI has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](./CODE_OF_CONDUCT.md) so that you can understand what sort of behaviour is expected. +Issues and pull requests without activity from the creator within 14 days will be automatically closed by a triager or committer. However, closure does not mean rejection. If you wish to revisit a closed issue or pull a request, open a new one referencing the closed item. -## Our Development Process -We use Github to host code, to track issues and feature requests, as well as accept pull requests. +Issues and pull requests without activity from the triager or committer within 14 days may occur for many reasons. The creator may use the `/ptal` comment in the pull request to call out maintainers. -## Issues -[Open an issue](https://github.com/asyncapi/asyncapi/issues/new) **only** if you want to report a bug or a feature. Don't open issues for questions or support, instead join our [Slack workspace](https://www.asyncapi.com/slack-invite) and ask there. Don't forget to follow our [Slack Etiquette](https://github.com/asyncapi/community/blob/master/slack-etiquette.md) while interacting with community members! It's more likely you'll get help, and much faster! +### Issues -## Bug Reports and Feature Requests +[Open an issue](https://github.com/asyncapi/asyncapi/issues/new) **only** if you want to report a bug or a feature. Don't open issues for questions or support; join our [AsyncAPI Slack workspace](https://www.asyncapi.com/slack-invite) and post your queries on the relevant channels. Don't forget to follow our [Slack Etiquette](https://github.com/asyncapi/community/blob/master/slack-etiquette.md) while interacting with community members! It's more likely you'll get help, and much faster! -Please use our issues templates that provide you with hints on what information we need from you to help you out. +### Bug Reports and Feature Requests -## Pull Requests +Please use our issues templates, which provide hints on what information we need from you to help you out. -**Please, make sure you open an issue before starting with a Pull Request, unless it's a typo or a really obvious error.** Pull requests are the best way to propose changes to the specification. Get familiar with our document that explains [Git workflow](https://github.com/asyncapi/community/blob/master/git-workflow.md) used in our repositories. +### Pull Requests -## Conventional commits +**Please open an issue before starting a Pull Request unless it's a typo or a really obvious error.** Pull requests are the best way to propose changes to the specification. It may be rejected if no issue was created first to discuss the need for a pull request. -Our repositories follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. Releasing to GitHub and NPM is done with the support of [semantic-release](https://semantic-release.gitbook.io/semantic-release/). +Get familiar with our document that explains the [Git workflow](https://github.com/asyncapi/community/blob/master/git-workflow.md) used in our repositories. -Pull requests should have a title that follows the specification, otherwise, merging is blocked. If you are not familiar with the specification simply ask maintainers to modify. You can also use this cheatsheet if you want: +## Conventional commits + +Our repositories follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. -- `fix: ` prefix in the title indicates that PR is a bug fix and PATCH release must be triggered. -- `feat: ` prefix in the title indicates that PR is a feature and MINOR release must be triggered. -- `docs: ` prefix in the title indicates that PR is only related to the documentation and there is no need to trigger release. -- `chore: ` prefix in the title indicates that PR is only related to cleanup in the project and there is no need to trigger release. -- `test: ` prefix in the title indicates that PR is only related to tests and there is no need to trigger release. -- `refactor: ` prefix in the title indicates that PR is only related to refactoring and there is no need to trigger release. +Pull requests should have a title that follows the specification; otherwise, merging is blocked. If you are unfamiliar with the specification, ask maintainers to modify it. You can also use this cheatsheet if you want: -What about MAJOR release? just add `!` to the prefix, like `fix!: ` or `refactor!: ` +- `fix: ` prefix in the title indicates that the PR is a bug fix. +- `feat: ` prefix in the title indicates that the PR is a feature. +- `docs: ` prefix in the title indicates that the PR only relates to the documentation. +- `chore: ` prefix in the title indicates that the PR is only related to cleanup in the project. +- `test: ` prefix in the title indicates that the PR is only related to tests. +- `refactor: ` prefix in the title indicates that the PR is only related to refactoring. -Prefix that follows specification is not enough though. Remember that the title must be clear and descriptive with usage of [imperative mood](https://chris.beams.io/posts/git-commit/#imperative). +A prefix that follows specification is not enough. Remember that the title must be clear and descriptive, using the [imperative mood](https://chris.beams.io/posts/git-commit/#imperative). -Happy contributing :heart: +Happy contributing! :heart: ## License + When you submit changes, your submissions are understood to be under the same [Apache 2.0 License](https://github.com/asyncapi/asyncapi/blob/master/LICENSE) that covers the project. Feel free to [contact the maintainers](https://www.asyncapi.com/slack-invite) if that's a concern. -## References -This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/master/CONTRIBUTING.md). \ No newline at end of file +## Contribution recognition + +We use the [All Contributors](https://allcontributors.org/docs/en/specification) specification to handle recognitions. Read the [`recognize contributors` document](https://github.com/asyncapi/community/blob/master/recognize-contributors.md). + +## Maintainers setup + +To streamline project management and facilitate onboarding, the maintainer's setup includes two roles: `triager` and `committer`. + +There are also two separate areas of responsibility: docs and code. A committer can be responsible for code only, and a triager can be responsible for docs only. A maintainer can hold all roles and participate in different areas. + +We recognize that because of the project's size and complexity, areas of responsibility can also become more granular. For example, a committer can be responsible for docs, but only community docs or a committer can be responsible only for project design. Project maintainers assess and approve these exceptions. + +### Triager + +Triagers are responsible for labeling, commenting, and managing issues and pull requests. + +- Triagers assess newly-opened issues and pull requests. +Responsibilities include labeling issues and pull requests, commenting, closing, and reopening items as needed, as well as assisting users and novice contributors. +- Triagers are crucial in enforcing the contributor guide and maintaining a clean backlog. +If a triager plans to become a committer, they should consult existing committers to gradually gain more rights. It's crucial to earn the trust of existing committers so they feel confident in your ability to merge PRs. A triager should consistently demonstrate dedication by regularly fulfilling their duties and actively reviewing PRs, providing code/docs suggestions and recommendations. This shows the committers that the triager is knowledgeable about the docs/codebase and committed to maintaining its quality. + +### Committer + +Committers are responsible for technical oversight, pull request approval, and onboarding of new maintainers. + +- Committers approve pull requests and oversee the technical direction of the project. +- They are responsible for reviewing and approving pull requests for merging. +- Committers also play a role in onboarding new maintainers and triagers. diff --git a/components/ClickableLogo.tsx b/components/ClickableLogo.tsx index 0ce7f081e4f3..e40e7fa488c2 100644 --- a/components/ClickableLogo.tsx +++ b/components/ClickableLogo.tsx @@ -1,6 +1,6 @@ import Link from 'next/link'; -import AsyncAPILogo from './AsyncAPILogo'; +import AsyncAPILogo from './logos/AsyncAPILogo'; interface IClickableLogoProps { href?: string; diff --git a/components/Loader.stories.tsx b/components/Loader.stories.tsx new file mode 100644 index 000000000000..85d97ee88674 --- /dev/null +++ b/components/Loader.stories.tsx @@ -0,0 +1,115 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import AsyncAPIColorIcon from '@/components/icons/AsyncAPIColorIcon'; +import IconCircularLoader from '@/components/icons/CircularLoader'; + +import Loader from './Loader'; + +const meta: Meta = { + title: 'Components/Loader', + component: Loader +}; + +export default meta; + +type Story = StoryObj; + +const DarkBackgroundDecorator = (Story: any) => ( +
+ +
+); + +export const TextLoader: Story = { + args: { + loaderText: 'Loading...' + } +}; + +export const TextLoaderInDark: Story = { + decorators: [DarkBackgroundDecorator], + args: { + loaderText: 'Loading...', + dark: true + } +}; + +export const PulsatingTextLoader: Story = { + args: { + loaderText: 'Loading...', + pulsating: true + } +}; + +export const PulsatingTextLoaderInDark: Story = { + decorators: [DarkBackgroundDecorator], + args: { + loaderText: 'Loading...', + dark: true, + pulsating: true + } +}; + +export const CircularAnimationLoader: Story = { + args: { + loaderIcon: + } +}; + +export const CircularAnimationLoaderInDark: Story = { + decorators: [DarkBackgroundDecorator], + args: { + loaderIcon: , + dark: true + } +}; + +export const PulsatingIconLoader: Story = { + args: { + loaderIcon: , + pulsating: true + } +}; + +export const PulsatingIconLoaderInDark: Story = { + decorators: [DarkBackgroundDecorator], + args: { + loaderIcon: , + dark: true, + pulsating: true + } +}; + +export const CircularAnimationTextLoader: Story = { + args: { + loaderIcon: , + loaderText: 'Loading...' + } +}; + +export const CircularAnimationTextLoaderInDark: Story = { + decorators: [DarkBackgroundDecorator], + args: { + loaderIcon: , + loaderText: 'Loading...', + dark: true + } +}; + +export const PulsatingIconTextLoader: Story = { + args: { + loaderIcon: , + loaderText: 'Loading...', + pulsating: true + } +}; + +export const PulsatingIconTextLoaderInDark: Story = { + decorators: [DarkBackgroundDecorator], + args: { + loaderIcon: , + loaderText: 'Loading...', + dark: true, + pulsating: true + } +}; diff --git a/components/Loader.tsx b/components/Loader.tsx index 09324174ec2d..94fd29417659 100644 --- a/components/Loader.tsx +++ b/components/Loader.tsx @@ -1,24 +1,39 @@ +import React from 'react'; import { twMerge } from 'tailwind-merge'; interface LoaderProps { + // eslint-disable-next-line prettier/prettier + + /** The text to be displayed along with the loading animation. */ + loaderText?: string; + + /** The icon to be displayed along with the loading animation. */ + loaderIcon?: React.ReactElement | null; + + /** Additional classes for the loader. */ className?: string; + + /** Whether the loader should be in dark mode. */ dark?: boolean; + + /** Whether the loader should be pulsating. */ + pulsating?: boolean; } /** * This component displays a loader. - * @param {LoaderProps} props - The props for the Loader component - * @param {string} props.className - Additional classes for the loader - * @param {boolean} props.dark - Whether the loader should be in dark mode */ -export default function Loader({ className = '', dark = false }: LoaderProps) { +export default function Loader({ + loaderText = '', + loaderIcon = null, + className = '', + dark = false, + pulsating = false +}: LoaderProps) { return ( -
- -
Waiting for response...
+
+ {loaderIcon} +
{loaderText}
); } diff --git a/components/NewsletterSubscribe.tsx b/components/NewsletterSubscribe.tsx index 80ce7474a19d..db7b0a6407df 100644 --- a/components/NewsletterSubscribe.tsx +++ b/components/NewsletterSubscribe.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; +import IconCircularLoader from '@/components/icons/CircularLoader'; import { ButtonType } from '@/types/components/buttons/ButtonPropsType'; import { InputTypes } from '@/types/components/InputBoxPropsType'; import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; @@ -127,7 +128,7 @@ export default function NewsletterSubscribe({ {subtitle} {status === 'loading' ? ( - + } dark={dark} /> ) : (
; +} diff --git a/components/icons/CircularLoader.tsx b/components/icons/CircularLoader.tsx new file mode 100644 index 000000000000..7cca8dfd8fe9 --- /dev/null +++ b/components/icons/CircularLoader.tsx @@ -0,0 +1,18 @@ +interface CircularLoaderProps { + // eslint-disable-next-line prettier/prettier + + /** Whether the loader should be in dark mode. */ + dark?: boolean; +} + +/** + * CircularLoader Icon + */ +export default function IconCircularLoader({ dark = false }: CircularLoaderProps) { + return ( + + ); +} diff --git a/components/icons/Icons.mdx b/components/icons/Icons.mdx index 7ae712388093..cb6496377a38 100644 --- a/components/icons/Icons.mdx +++ b/components/icons/Icons.mdx @@ -2,6 +2,7 @@ import { Meta, Title, IconGallery, IconItem } from '@storybook/blocks'; import IconAmbassador from './Ambassador'; import IconAsyncAPI from './AsyncAPI'; +import AsyncAPIColorIcon from './AsyncAPIColorIcon'; import IconArrowUp from './ArrowUp'; import IconArrowDown from './ArrowDown'; import IconArrowLeft from './ArrowLeft'; @@ -60,6 +61,7 @@ import IconUsers from './Users'; import Webinar from './Webinar'; import IconYoutube from './YouTube'; import IconYoutubeGray from './YouTubeGray'; +import IconCircularLoader from './CircularLoader'; @@ -70,31 +72,29 @@ These are the icons used in the AsyncAPI website. ## AsyncAPI Icons - - - + + + -{' '} + + + -{' '} - -{' '} - - - - + + + ## Social Media Icons @@ -104,50 +104,34 @@ These are the icons used in the AsyncAPI website. -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - @@ -164,265 +148,184 @@ These are the icons used in the AsyncAPI website. -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - -{' '} - - - - + + + + + + + + diff --git a/components/AsyncAPILogo.tsx b/components/logos/AsyncAPILogo.tsx similarity index 100% rename from components/AsyncAPILogo.tsx rename to components/logos/AsyncAPILogo.tsx diff --git a/components/AsyncAPILogoLight.tsx b/components/logos/AsyncAPILogoLight.tsx similarity index 100% rename from components/AsyncAPILogoLight.tsx rename to components/logos/AsyncAPILogoLight.tsx diff --git a/components/logos/logos.mdx b/components/logos/logos.mdx index c863c4eb059b..06e65b1c46ca 100644 --- a/components/logos/logos.mdx +++ b/components/logos/logos.mdx @@ -5,6 +5,8 @@ import AxwayLogo from './Axway'; import SlackLogo from './Slack'; import AdidasLogo from './Adidas'; import SalesforceLogo from './Salesforce'; +import AsyncAPILogo from './AsyncAPILogo'; +import AsyncAPILogoLight from './AsyncAPILogoLight'; @@ -13,29 +15,31 @@ import SalesforceLogo from './Salesforce'; These are the logos of various companies used in the AsyncAPI website. - - - + + + + + + + -{' '} + + + -{' '} - -{' '} - - - - + + + diff --git a/components/navigation/MobileNavMenu.tsx b/components/navigation/MobileNavMenu.tsx index a108cdaf9a2d..1c6f57e130f9 100644 --- a/components/navigation/MobileNavMenu.tsx +++ b/components/navigation/MobileNavMenu.tsx @@ -2,9 +2,9 @@ import Link from 'next/link'; import { useState } from 'react'; import { SearchButton } from '../AlgoliaSearch'; -import AsyncAPILogo from '../AsyncAPILogo'; import NavItemDropdown from '../icons/NavItemDropdown'; import SearchIcon from '../icons/SearchIcon'; +import AsyncAPILogo from '../logos/AsyncAPILogo'; import communityItems from './communityItems'; import learningItems from './learningItems'; import MenuBlocks from './MenuBlocks'; diff --git a/components/navigation/NavBar.tsx b/components/navigation/NavBar.tsx index 56cda97c5c06..ae8371702033 100644 --- a/components/navigation/NavBar.tsx +++ b/components/navigation/NavBar.tsx @@ -6,12 +6,12 @@ import { useEffect, useState } from 'react'; import { defaultLanguage, languages, useTranslation } from '../../utils/i18n'; import i18nPaths from '../../utils/i18nPaths'; import { SearchButton } from '../AlgoliaSearch'; -import AsyncAPILogo from '../AsyncAPILogo'; import GithubButton from '../buttons/GithubButton'; import { isMobileDevice } from '../helpers/is-mobile'; import { useOutsideClick } from '../helpers/use-outside-click'; import IconLoupe from '../icons/Loupe'; import LanguageSelect from '../languageSelector/LanguageSelect'; +import AsyncAPILogo from '../logos/AsyncAPILogo'; import CommunityPanel from './CommunityPanel'; import LearningPanel from './LearningPanel'; import MobileNavMenu from './MobileNavMenu'; diff --git a/components/tools/Checkbox.stories.tsx b/components/tools/Checkbox.stories.tsx new file mode 100644 index 000000000000..d9691aff1813 --- /dev/null +++ b/components/tools/Checkbox.stories.tsx @@ -0,0 +1,45 @@ +import { useArgs } from '@storybook/preview-api'; +import type { Meta, StoryObj } from '@storybook/react'; + +import type { CheckboxProps } from '@/types/components/tools/CheckboxPropsType'; + +import Checkbox from './Checkbox'; + +const meta: Meta = { + title: 'Components/Checkbox', + component: Checkbox +}; + +export default meta; + +type Story = StoryObj; + +export const DefaultCheckbox: Story = { + args: { + name: 'Check me!', + checked: true + }, + + render: (args: CheckboxProps) => { + const [{ checked }, updateArgs] = useArgs(); + + const handleClickOption = () => { + updateArgs({ checked: !checked }); + }; + + return ; + } +}; + +export const ColorfulCheckbox: Story = { + ...DefaultCheckbox, + + args: { + ...DefaultCheckbox.args, + bgColor: 'bg-gray-200', + textColor: 'text-primary-500', + borderColor: 'border-primary-500', + checkedStateBgColor: 'bg-primary-500', + checkedStateTextColor: 'text-white' + } +}; diff --git a/components/tools/Checkbox.tsx b/components/tools/Checkbox.tsx new file mode 100644 index 000000000000..439bb040be02 --- /dev/null +++ b/components/tools/Checkbox.tsx @@ -0,0 +1,40 @@ +import { twMerge } from 'tailwind-merge'; + +import type { CheckboxProps } from '@/types/components/tools/CheckboxPropsType'; + +/** + * This component renders a checkbox. + */ +const Checkbox = ({ + name, + checked, + bgColor = 'bg-white', + textColor = 'text-secondary-600', + borderColor = 'border-secondary-600', + checkedStateBgColor = 'bg-secondary-600', + checkedStateTextColor = 'text-white', + handleClickOption +}: CheckboxProps) => { + const handleClick = (event: React.MouseEvent) => { + event.stopPropagation(); // Prevents the event from propagating to parent elements + handleClickOption(name); + }; + + return ( +
+ {checked ? ( + checked + ) : ( + unchecked + )} +
{name}
+
+ ); +}; + +export default Checkbox; diff --git a/components/tools/Filters.tsx b/components/tools/Filters.tsx index a565d2130b8b..0ca822b7eea9 100644 --- a/components/tools/Filters.tsx +++ b/components/tools/Filters.tsx @@ -13,6 +13,7 @@ import ArrowDown from '../icons/ArrowDown'; import { CardData } from './CardData'; import FiltersDisplay from './FiltersDisplay'; import FiltersDropdown from './FiltersDropdown'; +import Toggle from './Toggle'; interface FiltersProps { setOpenFilter: React.Dispatch>; @@ -164,20 +165,7 @@ export default function Filters({ setOpenFilter }: FiltersProps) { />
- -
Show only AsyncAPI-owned tools
+

diff --git a/components/tools/FiltersDropdown.tsx b/components/tools/FiltersDropdown.tsx index fbf2d5c7a205..beb68e81eb5a 100644 --- a/components/tools/FiltersDropdown.tsx +++ b/components/tools/FiltersDropdown.tsx @@ -2,6 +2,8 @@ import { twMerge } from 'tailwind-merge'; import type { Category, Language, Technology } from '@/types/components/tools/ToolDataType'; +import Checkbox from './Checkbox'; + type DataList = Language[] | Technology[] | Category[]; interface FiltersDropdownProps { @@ -25,7 +27,7 @@ export default function FiltersDropdown({ setCheckedOptions, className = '' }: FiltersDropdownProps) { - const handleClickOption = (event: React.MouseEvent, option: string) => { + const handleClickOption = (option: string) => { const isChecked = checkedOptions.includes(option); const updatedOptions = isChecked ? checkedOptions.filter((item) => item !== option) : [...checkedOptions, option]; @@ -40,22 +42,7 @@ export default function FiltersDropdown({ {dataList.map((data, index) => { const checked = checkedOptions.includes(data.name); - return ( -
handleClickOption(event, data.name)} - > - {checked ? ( - checked - ) : ( - unchecked - )} -
{data.name}
-
- ); + return ; })} ); diff --git a/components/tools/Toggle.stories.tsx b/components/tools/Toggle.stories.tsx new file mode 100644 index 000000000000..2fcaf81c26df --- /dev/null +++ b/components/tools/Toggle.stories.tsx @@ -0,0 +1,42 @@ +import { useArgs } from '@storybook/preview-api'; +import type { Meta, StoryObj } from '@storybook/react'; + +import type { ToggleProps } from '@/types/components/tools/TogglePropsType'; + +import Toggle from './Toggle'; + +const meta: Meta = { + title: 'Components/Toggle', + component: Toggle +}; + +export default meta; + +type Story = StoryObj; + +export const DefaultToggle: Story = { + args: { + checked: true, + label: 'Toggle me!' + }, + + render: (args: ToggleProps) => { + const [{ checked }, updateArgs] = useArgs(); + + const setChecked = () => { + updateArgs({ checked: !checked }); + }; + + return ; + } +}; + +export const ColorfulToggle: Story = { + ...DefaultToggle, + + args: { + ...DefaultToggle.args, + bgColor: 'bg-gray-200', + checkedStateBgColor: 'bg-primary-500' + } +}; diff --git a/components/tools/Toggle.tsx b/components/tools/Toggle.tsx new file mode 100644 index 000000000000..bfa324b8538b --- /dev/null +++ b/components/tools/Toggle.tsx @@ -0,0 +1,33 @@ +import { twMerge } from 'tailwind-merge'; + +import type { ToggleProps } from '@/types/components/tools/TogglePropsType'; + +/** + * Toggle component for displaying and controlling a toggle switch. + */ +const Toggle = ({ + checked, + setChecked, + label, + bgColor = 'bg-gray-200', + checkedStateBgColor = 'bg-secondary-500' +}: ToggleProps) => { + return ( + + ); +}; + +export default Toggle; diff --git a/components/tools/ToolsDashboard.tsx b/components/tools/ToolsDashboard.tsx index da74ade22edb..bec91768c97d 100644 --- a/components/tools/ToolsDashboard.tsx +++ b/components/tools/ToolsDashboard.tsx @@ -1,6 +1,7 @@ import { useRouter } from 'next/router'; import { useContext, useEffect, useRef, useState } from 'react'; +import AsyncAPIColorIcon from '@/components/icons/AsyncAPIColorIcon'; import type { ToolsListData } from '@/types/components/tools/ToolDataType'; import ToolsDataList from '../../config/tools.json'; @@ -9,6 +10,7 @@ import ArrowDown from '../icons/ArrowDown'; import Cross from '../icons/Cross'; import FilterIcon from '../icons/Filter'; import SearchIcon from '../icons/Search'; +import Loader from '../Loader'; import CategoryDropdown from './CategoryDropdown'; import Filters from './Filters'; import ToolsList from './ToolsList'; @@ -20,7 +22,6 @@ const ToolsData = ToolsDataList as ToolsListData; */ export default function ToolsDashboard() { const router = useRouter(); - const loader = 'img/loaders/loader.png'; // preloader image for the tools const [loading, setLoading] = useState(false); // used to handle the preloader on the page const filterRef = useRef(); // used to provide ref to the Filter menu and outside click close feature @@ -226,10 +227,7 @@ export default function ToolsDashboard() { )} {loading ? ( -
- loading -
Loading Tools...
-
+ } pulsating /> ) : (
{checkToolsList ? ( diff --git a/config/AMBASSADORS_MEMBERS.json b/config/AMBASSADORS_MEMBERS.json index 1eef57473b15..c86c4cca9898 100644 --- a/config/AMBASSADORS_MEMBERS.json +++ b/config/AMBASSADORS_MEMBERS.json @@ -686,5 +686,45 @@ "link": "https://www.asyncapi.com/casestudies/hdiglobal" } ] + }, + { + "name": "Lorna Mitchell", + "bio": "Lorna is based in Yorkshire, UK; she is a technology leader and expert in developer experience, passionate about enhancing APIs and developer tools. In her day job as VP of Developer Experience at Redocly, she works on API and documentation tools for technical teams. Lorna is a published author and a regular speaker at conferences, sharing her insights on a variety of tech-related topics. Lorna serves on the OpenUK board, is on the Technical Steering Committee for OpenAPI specification, and maintains open source projects. To learn more about Lorna's activities, visit her website at https://lornajane.net.", + "title": "APIs and Open Source", + "img": "https://lornajane.net/wp-content/uploads/2011/08/IMG_9410-smaller.jpg", + "github": "lornajane", + "twitter": "lornajane", + "linkedin": "lornajane", + "company": "Redocly", + "country": "UK", + "contributions": [ + { + "type": "presentation", + "title": "API Governance for AsyncAPI", + "date": { + "year": 2023, + "month": "September" + }, + "link": "https://noti.st/lornajane/aOuXwe/api-governance-for-asyncapi" + }, + { + "type": "presentation", + "title": "AsyncAPI for Apache Kafka", + "date": { + "year": 2021, + "month": "May" + }, + "link": "https://videos.confluent.io/watch/hzjXP8QmLtYRNPukNFUu2D?" + }, + { + "type": "article", + "title": "Lint AsyncAPI with Redocly CLI", + "date": { + "year": 2023, + "month": "August" + }, + "link": "https://redocly.com/docs/cli/guides/lint-asyncapi" + } + ] } ] diff --git a/config/MAINTAINERS.json b/config/MAINTAINERS.json index d34e97f45b82..1d9a5cab3e3d 100644 --- a/config/MAINTAINERS.json +++ b/config/MAINTAINERS.json @@ -963,5 +963,14 @@ "learning-paths" ], "githubID": 77982319 + }, + { + "name": "Lorenz Simon", + "github": "lorenzsimon", + "isTscMember": false, + "repos": [ + "kotlin-asyncapi" + ], + "githubID": 39913716 } ] \ No newline at end of file diff --git a/config/finance/2024/Expenses.yml b/config/finance/2024/Expenses.yml index 66e12fda9a57..1467852bbb50 100644 --- a/config/finance/2024/Expenses.yml +++ b/config/finance/2024/Expenses.yml @@ -10,6 +10,8 @@ January: - Category: AsyncAPI Conf on Tour 2023 Amount: '318.98' February: + - Category: Bounty Program + Amount: '400.00' - Category: JSON Schema Sponsorship Amount: '250.00' - Category: Community Manager @@ -50,4 +52,47 @@ May: - Category: Mentorship Program 2023 Amount: '825.00' - Category: Swag Store - Amount: '526.51' \ No newline at end of file + Amount: '526.51' + - Category: Bounty Program + Amount: '800.00' + - Category: Community Marketing Specialist + Amount: '1000.00' +June: + - Category: JSON Schema Sponsorship + Amount: '250.00' + - Category: Community Manager + Amount: '2000.00' + - Category: Community Marketing Specialist + Amount: '2000.00' + - Category: Bounty Program + Amount: '800.00' + - Category: Swag Store + Amount: '526.51' +July: + - Category: JSON Schema Sponsorship + Amount: '250.00' + - Category: Community Manager + Amount: '2000.00' + - Category: Bounty Program + Amount: '1000.00' + - Category: Swag Store + Amount: '526.51' + - Category: Community Marketing Specialist + Amount: '2000.00' + - Category: AsyncAPI Conf on Tour 2024 + Amount: '2083.41' +August: + - Category: JSON Schema Sponsorship + Amount: '250.00' + - Category: Community Manager + Amount: '2000.00' + - Category: Bounty Program + Amount: '1600.00' + - Category: Swag Store + Amount: '2556.42' + - Category: Community Marketing Specialist + Amount: '2000.00' + - Category: 3rd Party Services + Amount: '1354.35' + - Category: AsyncAPI Conf on Tour 2024 + Amount: '1384.70' \ No newline at end of file diff --git a/config/finance/2024/ExpensesLink.yml b/config/finance/2024/ExpensesLink.yml index 449c60ded4b8..97c0c087209f 100644 --- a/config/finance/2024/ExpensesLink.yml +++ b/config/finance/2024/ExpensesLink.yml @@ -26,4 +26,7 @@ link: "https://github.com/orgs/asyncapi/discussions/689" - category: "JSON Schema Sponsorship" - link: "https://github.com/orgs/asyncapi/discussions/1017" \ No newline at end of file + link: "https://github.com/orgs/asyncapi/discussions/1017" + +- category: "Community Marketing Specialist" + link: "https://github.com/orgs/asyncapi/discussions/1176" \ No newline at end of file diff --git a/markdown/blog/websocket-part2.md b/markdown/blog/websocket-part2.md index 4098bebd799a..3014381da1e5 100644 --- a/markdown/blog/websocket-part2.md +++ b/markdown/blog/websocket-part2.md @@ -147,7 +147,7 @@ Create two AsyncAPI documents. Treat those two servers as separate services that You can use AsyncAPI also to describe the security of your API. You can describe in a machine-readable way the security mechanism that protects the server. Several [security schemes](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#securitySchemeObject) are supported. In Kraken's case, I could not figure out what kind of security scheme they use from their docs. They seem to have a non-standard set up for getting the authorization token, which is why the only option was to put a human-readable-only description there. -```yaml +~~~yaml servers: public: url: ws.kraken.com @@ -166,16 +166,16 @@ servers: The resulting token must be provided in the "token" field of any new private WebSocket feed subscription: ``` - \{ + { "event": "subscribe", "subscription": - \{ + { "name": "ownTrades", "token": "WW91ciBhdXRoZW50aWNhdGlvbiB0b2tlbiBnb2VzIGhlcmUu" } } ``` -``` +~~~ ### Endpoints aka Channels @@ -436,7 +436,7 @@ For **automation** road described in section [Choosing the right road to Rome](# > You can open this document directly in AsyncAPI Studio by clicking [this](https://studio.asyncapi.com?url=https://gist.githubusercontent.com/derberg/4e419d6ff5870c7c3f5f443e8bd30535/raw/5e9b733b80a0209ba5520e5f41ab18c2a112e0a9/asyncapi-websocket-kraken.yml) link. Compare it also with the [original documentation](https://docs.kraken.com/websockets/). -```yml +~~~yaml asyncapi: 2.0.0 info: @@ -474,10 +474,10 @@ servers: The resulting token must be provided in the "token" field of any new private WebSocket feed subscription: ``` - \{ + { "event": "subscribe", "subscription": - \{ + { "name": "ownTrades", "token": "WW91ciBhdXRoZW50aWNhdGlvbiB0b2tlbiBnb2VzIGhlcmUu" } @@ -809,6 +809,6 @@ components: type: string description: Format of each pair is "A/B", where A and B are ISO 4217-A3 for standardized assets and popular unique symbol if not standardized. pattern: '[A-Z\s]+\/[A-Z\s]+' -``` +~~~ Stay tuned for more articles around WebSocket and AsyncAPI. Share your feedback and connect with the AsyncAPI community in our [Slack workspace](https://www.asyncapi.com/slack-invite/). diff --git a/markdown/docs/concepts/asyncapi-document/add-server.md b/markdown/docs/concepts/asyncapi-document/add-server.md index 4032f00ddb58..5dff23779638 100644 --- a/markdown/docs/concepts/asyncapi-document/add-server.md +++ b/markdown/docs/concepts/asyncapi-document/add-server.md @@ -46,10 +46,10 @@ Here's an example of an AsyncAPI document with two servers referenced from the ` ```yaml servers: kafka-test: - $ref: '#/components/servers/kafka-test + $ref: '#/components/servers/kafka-test' mqtt-test: - $ref: '#/components/servers/mqtt-test -components + $ref: '#/components/servers/mqtt-test' +components: servers: kafka-test: host: my.kafka.pl diff --git a/markdown/docs/tools/cli/context.md b/markdown/docs/tools/cli/context.md index 95fbcc8e0083..30803782e556 100644 --- a/markdown/docs/tools/cli/context.md +++ b/markdown/docs/tools/cli/context.md @@ -123,7 +123,7 @@ Map of filesystem paths to target AsyncAPI documents. Field Pattern | Type | Description ---|:---:|--- -{contextName} | `string` | An optional string value representing filesystem path to the target AsyncAPI document. +\{contextName\} | `string` | An optional string value representing filesystem path to the target AsyncAPI document. ### Minimal Empty Context File Raw JSON: diff --git a/markdown/docs/tools/cli/metrics_collection.md b/markdown/docs/tools/cli/metrics_collection.md index 3e89f6bddc65..cd9a4c6f7770 100644 --- a/markdown/docs/tools/cli/metrics_collection.md +++ b/markdown/docs/tools/cli/metrics_collection.md @@ -1,3 +1,8 @@ +--- +title: 'Metrics Collection' +weight: 60 +--- + # Metrics collection guideline AsyncAPI **anonymously** tracks command executions to improve the specification and tools, ensuring no sensitive data reaches our servers. It aids in comprehending how AsyncAPI tools are used and adopted, facilitating ongoing improvements to our specifications and tools. diff --git a/markdown/docs/tools/glee/authentication.md b/markdown/docs/tools/glee/authentication.md index 841bbfca78c4..031810402e64 100644 --- a/markdown/docs/tools/glee/authentication.md +++ b/markdown/docs/tools/glee/authentication.md @@ -1,45 +1,44 @@ --- -title: 'Authentication functions' +title: 'Authentication Functions' weight: 70 --- -# Getting started with Authentication functions +# Getting Started with Authentication Functions -Authentication in Glee can be done using authentication functions. Authentication functions are files that export either one or both of the `clientAuth` and `serverAuth` Node.js functions: +Authentication in Glee can be implemented using authentication functions. These functions are files that export one or both of the following Node.js functions: `clientAuth` and `serverAuth`: ```js /* websocket.js */ export async function serverAuth({ authProps, done }) { - //server auth logic + // Server authentication logic } export async function clientAuth({ parsedAsyncAPI, serverName }) { - //client auth logic + // Client authentication logic } ``` -Glee looks for authentication files in the `auth` directory by default but it can be configured using [glee config file](env-vars-config). -The name of the authentication file should be the name of the targeted server that the authentication logic should work for. +Glee searches for authentication files in the `auth` directory by default. However, this can be configured using the [glee config file](env-vars-config). The authentication file's name should match the targeted server for which the authentication logic is intended. -## Supported Authentication Values in asyncapi.yaml file +## Supported Authentication Values in the asyncapi.yaml File -AsyncAPI currently supports a variety of authentication formats as specified in the [documentation](https://www.asyncapi.com/docs/reference/specification/v3.0.0#securitySchemeObject), however Glee supports the following authentication schemas. +AsyncAPI supports a variety of authentication formats as specified in its [documentation](https://www.asyncapi.com/docs/reference/specification/v3.0.0#securitySchemeObject). Glee, however, supports the following authentication schemas: - userPassword - http ("bearer") - httpApiKey - Oauth2 -A sample `asyncapi.yaml` for a **server** with security requirements and a `userPassword` security schemes is shown below: +Below is an example of a `asyncapi.yaml` file for a **server** with security requirements and a `userPassword` security scheme: ```yaml -##server asyncAPI schema +## Server AsyncAPI Schema asyncapi: 3.0.0 info: - title: AsyncAPI IMDB server + title: AsyncAPI IMDB Server version: 1.0.0 - description: This app is a dummy server that would stream the trending/upcoming anime. + description: This app is a dummy server that streams trending/upcoming anime. servers: trendingAnimeServer: host: 'localhost:8081' @@ -53,13 +52,12 @@ components: securitySchemes: userPass: type: userPassword - ``` -A sample `asyncapi.yaml` for a **client** that implements some of the requirements of the server above is as follows: +Here's an example for a **client** that implements some requirements of the server mentioned above: ```yaml -##client asyncAPI schema +## Client AsyncAPI Schema servers: trendingAnime: host: localhost:8081 @@ -78,29 +76,28 @@ components: securitySchemes: userPass: type: userPassword - ``` -Glee can act as both a server and a client. So the need for `serverAuth` and `clientAuth`. Glee acts as a client when the server name is included in the `x-remoteServers` property in the `asyncapi.yaml` file. +Glee can function as both a server and a client. Hence, the need for both `serverAuth` and `clientAuth` functions arises. Glee acts as a client when the server name is included in the `x-remoteServers` property in the `asyncapi.yaml` file. -When Glee acts as a client, it can connect to a Glee server, and when Glee acts as a server it accepts connections from other Glee clients. Hence a Glee application can both accept connections from clients while also sending requests to other Glee applications (servers) at the same time. +When Glee operates as a client, it can connect to a Glee server. Conversely, as a server, it accepts connections from other Glee clients. Thus, a Glee application can accept connections from clients while also sending requests to other Glee servers. -When a security requirement is specified in the `asyncapi.yaml` file and Glee acts as a server, the `serverAuth` function should be implemented, if Glee acts as a client then the `clientAuth` function should be implemented. If Glee is being used as both client and server, then it should have both the `clientAuth` and `serverAuth` functions. +If a security requirement is specified in the `asyncapi.yaml` file, and Glee acts as a server, the `serverAuth` function should be implemented. If Glee acts as a client, then `clientAuth` should be implemented. If Glee is used as both client and server, both functions are necessary. ## Server Authentication in Glee -The `serverAuth` function takes an argument that can be destructured as follows +The `serverAuth` function takes an argument that can be destructured as follows: | Attribute | Description | | ---------- | --------------------------------------------------------------- | -| done | The done function that tells the server to proceed. | -| authProps | The authentication parameters recieved from the client. | -| serverName | The name of the server/broker from which the event was emitted. | -| doc | The parsedAsyncAPI schema | +| done | The function that signals the server to proceed. | +| authProps | The authentication parameters received from the client. | +| serverName | The name of the server/broker emitting the event. | +| doc | The parsed AsyncAPI schema. | -#### done() function +#### done() Function -The `done()` parameter in the `serverAuth` function allows the broker/server to know what to do next depending on the boolean value you pass to it. +The `done()` parameter in the `serverAuth` function signals to the broker/server what action to take next, based on the boolean value passed. ```js /* websocket.js */ @@ -113,22 +110,22 @@ export async function serverAuth({ authProps, done }) { } } ``` + **Parameters for done():** -*Authentication Result (Boolean): true for success, false for failure.* +- Authentication Result (Boolean): `true` for success, `false` for failure. -When `true` is passed to the done parameter, the server/broker knows to go ahead and allow the client to connect, which means authentication has succeeded. However if the `done` parameter is called with `false` then the server knows to throw an error message and reject the client, which means authentication has failed. +Passing `true` to the `done` parameter indicates that authentication has succeeded, and the server/broker can proceed to allow the client to connect. Conversely, if `false` is passed, the server will reject the client, indicating failed authentication. -`done()` should always be the last thing called in a `serverAuth` function, Glee won't execute any logic beyond the `done()` call. +The `done()` call should always be the last in the `serverAuth` function, as Glee will not execute any logic beyond this call. #### authProps -`authProps` implements a couple of methods that allows the server to retrieve the authentication parameters from the client, below are the current available methods; +The `authProps` parameter includes methods for the server to retrieve authentication parameters from the client. The current available methods are as follows: ```js export async function serverAuth({ authProps, done }) { - //some network request - + // Some network request authProps.getOauthToken() authProps.getHttpAPIKeys('api_key') authProps.getToken() @@ -140,23 +137,23 @@ export async function serverAuth({ authProps, done }) { | Method | Description | | ---------------------- | ------------------------------------------------------------------------------------------------ | -| `getOauthToken()` | returns the oauth authentication parameter | -| `getHttpAPIKeys(name)` | returns the HttpAPIKeys parameter with the specified name from either headers or query parameter | -| `getToken()` | returns the http bearer token parameter | -| `getUserPass()` | returns username and password parameters | +| `getOauthToken()` | Returns the OAuth authentication parameter. | +| `getHttpAPIKeys(name)` | Returns the HttpAPIKeys parameter with the specified name from either headers or query parameter | +| `getToken()` | Returns the HTTP bearer token parameter. | +| `getUserPass()` | Returns username and password parameters. | ## Client Authentication in Glee -The `clientAuth` function also takes an argument, and it's argument can be destructured as follows +The `clientAuth` function also takes an argument that can be destructured as follows: | Attribute | Description | | -------------- | ------------------------------------------------------------------------------------- | -| parsedAsyncAPI | The parsedAsyncAPI schema. | -| serverName | The name of the server/broker from with the authentication parameters are being sent. | +| parsedAsyncAPI | The parsed AsyncAPI schema. | +| serverName | The server/broker's name from which the authentication parameters are being sent. | -### Possible authentication parameters +### Possible Authentication Parameters -The possible authentication parameters are shown in the code snippet below: +The code snippet below illustrates the possible authentication parameters: ```js export async function clientAuth({ serverName }) { @@ -165,18 +162,18 @@ export async function clientAuth({ serverName }) { oauth: process.env.OAUTH2, apiKey: process.env.APIKEY, userPass: { - user: process.env.user, - password: process.env.password, + user: process.env.USER, + password: process.env.PASSWORD, }, } } ``` -The name of the authentication parameters should be the same as **the names specified in the `asyncapi.yaml` file.** +The names of the authentication parameters should match **the names specified in the `asyncapi.yaml` file**. -| auth type | values | +| Auth Type | Values | | ------------------------------------- | ---------------------------------------------------------------------- | -| http bearer (JWT) | Value should be a JWT string | -| Oauth2 | The value should should be a string | -| httpApiKey in headers or query params | The value should be a string | -| userPass | The value should be an object with the user and password as properties | +| HTTP bearer (JWT) | Value should be a JWT string. | +| OAuth2 | Value should be a string. | +| httpApiKey in headers or query params | Value should be a string. | +| userPass | Value should be an object with the user and password as properties. | \ No newline at end of file diff --git a/markdown/docs/tools/glee/bearerToken.md b/markdown/docs/tools/glee/bearerToken.md index db22c2b6c9ad..9bc60e394fc8 100644 --- a/markdown/docs/tools/glee/bearerToken.md +++ b/markdown/docs/tools/glee/bearerToken.md @@ -1,21 +1,21 @@ --- -title: 'Http Authentication(Bearer Token)' +title: 'HTTP Authentication (Bearer Token)' weight: 80 --- -## Getting started with Bearer Token authentication +## Getting Started with Bearer Token Authentication -Bearer Token authentication is one of the most popular forms of authentication and is widely used because of its perceived security. This guide will walk through how to implement bearer token authentication in Glee. +Bearer Token authentication is one of the most popular forms of authentication and is widely used due to its perceived security. This guide will walk you through how to implement bearer token authentication in Glee. -A sample `asyncapi.yaml` for a server with security requirements and user password security scheme is shown below: +Below is a sample `asyncapi.yaml` for a server with security requirements and a user password security scheme: ```yaml -##server asyncAPI schema +## Server AsyncAPI Schema asyncapi: 3.0.0 info: - title: AsyncAPI IMDB server + title: AsyncAPI IMDB Server version: 1.0.0 - description: This app is a dummy server that would stream the trending/upcoming anime. + description: This app is a dummy server that streams trending/upcoming anime. servers: trendingAnimeServer: host: 'localhost:8081' @@ -37,7 +37,7 @@ components: A sample `asyncapi.yaml` for a client that implements some of the requirements of the server above: ```yaml -##client asyncAPI schema +## Client AsyncAPI Schema servers: trendingAnime: host: localhost:8081 @@ -61,49 +61,46 @@ components: ``` -The Client asyncapi.yaml file **does't need to implement all the security requirements in the server, it only needs to implement the ones that it uses like *http (bearer token)* here.** +The Client `asyncapi.yaml` file **doesn't need to implement all the security requirements of the server; it only needs to implement the ones it uses, like *http (bearer token)* here.** ### Client Side -Following the client `asyncapi.yaml` file above, create a file named `trendingAnime.ts` in the `auth` directory, since that is the server that has the security Property. +Following the client `asyncapi.yaml` file above, create a file named `trendingAnime.ts` in the `auth` directory, since that is the server that has the security property. ```bash touch auth/trendingAnime.ts ``` -When using the `bearer` security scheme, it is important that you pass the parameters as follows: +When using the `bearer` security scheme, pass the parameters as follows: ```js -export async clientAuth({ parsedAsyncAPI, serverName }) { +export async function clientAuth({ parsedAsyncAPI, serverName }) { return { token: process.env.TOKEN } } ``` -Glee will utilize the `token` for server authentication, employing it in the header with the format: Authorization: Bearer {token}. +Glee will utilize the `token` for server authentication, employing it in the header with the format: `Authorization: Bearer \{token\}`. -### Server side +### Server Side -From the server `asyncapi.yaml` file above, create a file named `trendingAnimeServer.ts` in the `auth` directory, since that is the server that has the security Property. +From the server `asyncapi.yaml` file above, create a file named `trendingAnimeServer.ts` in the `auth` directory, since that is the server that has the security property. ```bash touch auth/trendingAnimeServer.ts ``` -On the server side, you can retrieve the values as follows +On the server side, you can retrieve the values as follows: ```js -export async serverAuth({ authProps, done }) { +export async function serverAuth({ authProps, done }) { authProps.getToken() - // your authentication logic here... - done(true|false) + // Your authentication logic here... + done(true || false) } ``` -So, `getToken()` returns a string which contains the token that is sent from the client. - - - +So, `getToken()` returns a string containing the token sent from the client. \ No newline at end of file diff --git a/markdown/docs/tools/glee/crypto-websockets-interactive.md b/markdown/docs/tools/glee/crypto-websockets-interactive.md index 8e0934950725..70a87b7f2ca5 100644 --- a/markdown/docs/tools/glee/crypto-websockets-interactive.md +++ b/markdown/docs/tools/glee/crypto-websockets-interactive.md @@ -14,4 +14,4 @@ Please become our alpha testers of the tutorial: 2. Let us know what you think using the channel that works for you the best: - [Slack](https://www.asyncapi.com/slack-invite/) - [Twitter](https://twitter.com/AsyncAPISpec) - - [GitHub Issue](https://github.com/asyncapi/glee/issues/) + - [GitHub Issue](https://github.com/asyncapi/glee/issues/) \ No newline at end of file diff --git a/markdown/docs/tools/glee/env-vars-config.md b/markdown/docs/tools/glee/env-vars-config.md index e48418a44a9d..9c8590e28c9f 100644 --- a/markdown/docs/tools/glee/env-vars-config.md +++ b/markdown/docs/tools/glee/env-vars-config.md @@ -1,195 +1,136 @@ --- -title: Environment variables and Configuration file +title: Configuring Environment Variables and Configuration File weight: 50 --- -# Environment Variables +## Environment Variables -Glee provides a few environment variables for you to customize the Glee application's behavior according to your specific requirements: +Glee provides several environment variables that allow you to tailor your application's behavior to fit specific needs: -|Variable|Description|Example| -|---|---|---| -|GLEE_SERVER_NAMES|A comma-separated list of the servers to load on startup.|`GLEE_SERVER_NAMES=websockets,mosquitto`| -|GLEE_SERVER_CERTS|A comma-separated list of `${serverName}:${pathToCertificateFile}`. These are the certificates to use when establishing the connection to the given server.|`GLEE_SERVER_CERTS=mosquitto:mosquitto.org.crt`| -|GLEE_SERVER_VARIABLES|A comma-separated list of `${serverName}:${serverVariable}:${value}`. These are the values to use for each server variable.|`GLEE_SERVER_VARIABLES=websockets:namespace:public`| +|Variable|Purpose|Example Usage| +|--------|-------|-------------| +|GLEE_SERVER_NAMES|Specifies a list of servers to initialize at startup, separated by commas.|`GLEE_SERVER_NAMES=websockets,mosquitto`| +|GLEE_SERVER_CERTS|Indicates server-specific certificate files in a `${serverName}:${pathToCertificateFile}` format, separated by commas.|`GLEE_SERVER_CERTS=mosquitto:mosquitto.org.crt`| +|GLEE_SERVER_VARIABLES|Sets server variables in a `${serverName}:${serverVariable}:${value}` format, separated by commas.|`GLEE_SERVER_VARIABLES=websockets:namespace:public`| -## Configuring Glee +### Handling Multiple .env Files +Glee supports loading variables from `.env.local` directly into `process.env`. This feature is handy for keeping secrets out of your repository during development. You can also set environment-specific defaults in `.env.development` or `.env.production`. -Glee comes with sensible defaults so you don't have to worry about configuration. However, sometimes you may want to change the behavior or customize Glee in different ways. For that purpose, you can use the `glee.config.js` file. +`.env.local` takes precedence over other `.env*` files. -### Configuration file +Switch between `development` and `production` environments by setting the `NODE_ENV` variable accordingly. -Glee's config file is a JavaScript file that exports an async function. Something like this: +## Customizing Glee Settings + +While Glee comes with defaults for ease of use, you may want to customize settings for specific needs. This is where `glee.config.js` comes into play. + +### The Glee Config File + +`glee.config.js` is a JavaScript file exporting an asynchronous function, structured as follows: ```js export default async function () { - // More stuff here... + // Configuration details go here... } ``` -This function must return an object with the following shape: +This function should return an object with configurable properties: ```js export default async function () { return { glee: {}, - kafka: {}, websocket: {}, - mqtt: {}, cluster: {}, http: {} } } - ``` -Here is an example of a `glee.config.js` file for reference: +For example, a typical `glee.config.js` might look like this: ```js export default async function () { return { - glee: { // Glee core configurations + glee: { // Core Glee configurations lifecycleDir: './lifecycle', functionsDir: './functions', asyncapiFilePath: './asyncapi.json', - logs: { // you can change the defualt behaviour of glee which logs everything by default. - incoming: 'channel-only', // only logs the channel not message payload. - outgoing: 'none', //log nothing. + logs: { // Adjust default logging behavior + incoming: 'channel-only', // Logs only the channel, not the message payload + outgoing: 'none', // Disables outgoing logs } }, docs: { - enabled: true, // Enable/Disable documentation generation - folder: 'docs', // Folder where you want the output of your docs to reside. - template: '@asyncapi/markdown-template' // Type of template you want to use. - } + enabled: true, // Toggles documentation generation + folder: 'docs', // Destination folder for docs + template: '@asyncapi/markdown-template' // Specifies the documentation template + }, ws: { server: { - httpServer: customServer, // A custom HTTP server of your own. - adapter: "native", // Default. Can also be 'socket.io' or a reference to a custom adapter. - port: process.env.PORT, + httpServer: customServer, // Custom HTTP server + adapter: "native", // Defaults to 'native', can be 'socket.io' or a custom adapter + port: process.env.PORT, // Server port } }, cluster: { - adapter: "redis", - name: "cluster", // Default. Name of your cluster. - url: "redis://localhost:6379", // Server URL used by adapter for clustering - }, - mqtt: { - auth: ({serverName, parsedAsyncAPI}) => { - if (serverName === 'mqtt') { - return { - cert: async () => fs.readFileSync('./cert') - clientId: '123', - username: 'user1' - password: 'pass12' - } - } - } + adapter: "redis", // Cluster adapter, default is Redis + name: "cluster", // Cluster name + url: "redis://localhost:6379", // URL for the cluster server (Redis in this case) }, http: { server: { - httpServer: customServer, // A custom HTTP server of your own. + httpServer: customServer, // Custom HTTP server adapter: 'native', - port: process.env.PORT, + port: process.env.PORT, // Server port }, - client: { - auth: { - token: process.env.TOKEN - }, - query: { - foo: 'bar' - }, - body: { - foo: 'bar' - } - } } }; } ``` -Inside the return statement, you can specify the following options: -#### Glee Core Configurations -These configurations apply to Glee itself, rather than any specific protocol. +In the return statement, configure the following options: -|Field|Default|Description| +#### Core Glee Configurations +These settings are specific to Glee itself. + +|Field|Default|Purpose| |--|--|--| -|glee.gleeDir|`.glee`|Sets the Glee directory. Your sources will be compiled here.| -|glee.lifecycleDir|`lifecycle`|Path to the directory that stores your [lifecycle events](./lifecycle-events.md).| -|glee.functionsDir|`functions`| Path to the directory that stores your [functions](./functions.md).| -|glee.asyncapiFilePath|`asyncapi.(yaml \| yml \| json)`| Path to your AsyncAPI file.| -|glee.logs| default | glee logs channel and payload by default. you can change this behaviour for incoming and outgoing messages.| -|glee.logs.incoming| "all" | Supported values are `channel-only` and `none`.| -|glee.logs.outgoing| "all" | Supported values are `channel-only` and `none`.| - -#### Generating Documentation -|Field|Description| -|--|--| -|docs.enabled|This flag enables/disables the docs generation functionality. -|docs.folder|The dedicated folder you want your generated docs to reside. -|docs.template|The AsyncAPI template you wanna use for generating your documentation. -#### Websocket Server -|Field|Description| +|glee.gleeDir|`.glee`|Determines the Glee directory for compiled sources.| +|glee.lifecycleDir|`lifecycle`|Specifies the path to [lifecycle events](./lifecycle-events.md).| +|glee.functionsDir|`functions`|Designates the path to [functions](./functions.md).| +|glee.asyncapiFilePath|`asyncapi.(yaml \| yml \| json)`|Path to your AsyncAPI file.| +|glee.logs|default|Configures logging for incoming and outgoing messages.| +|glee.logs.incoming|"all"|Options: `channel-only`, `none`.| +|glee.logs.outgoing|"all"|Options: `channel-only`, `none`.| + +#### Documentation Configuration +|Field|Purpose| |--|--| -|ws.server|Websocket server-specific configurations| -|ws.server.adapter| The Glee adapter to use for the WebSocket server. Defaults to a "native" WebSocket implementation. Other allowed values are `socket.io` (to use the [Socket.IO](https://socket.io/) Glee adapter) or a reference to a custom adapter.| -|ws.server.httpServer| A custom HTTP server of your own. E.g., an [Express](https://expressjs.com/en/4x/api.html) server or any object that implements the [http.Server](https://nodejs.org/api/http.html#http_class_http_server) interface. | -|ws.server.port| The port to use when binding the WebSocket server. This is useful when your server is behind a proxy and the port exposed for consumption is not the same as the port your application should be bound to. Defaults to the port specified in the selected AsyncAPI server.| -#### Cluster -|Field|Description| +|docs.enabled|Enables or disables documentation generation.| +|docs.folder|Specifies the output directory for documentation.| +|docs.template|Determines the AsyncAPI template for docs generation.| + +#### WebSocket Server Configuration +|Field|Purpose| |--|--| -|cluster.adapter| The Glee cluster adapter to use for communication between instances. Defaults to Redis Pub/Sub ("redis"). Can be a reference to a custom adapter.| -|cluster.name|The name of the cluster. Defaults to "cluster".| -|cluster.url|The url of the server to be used by the adapter. In case of "redis" adapter, it's the url of the Redis server.| -#### MQTT -|Field|Description| -|---|---| -|mqtt.auth| MQTT authentication configuration| -|mqtt.auth.cert| Client certificate -|mqtt.auth.clientId| MQTT client Id for authentication -|mqtt.auth.username| username parameter -|mqtt.auth.password| password parameter -#### Kafka -|Field|Description| -|---|---| -|kafka.auth| Kafka authentication configuration| -|kafka.auth.key | Kafka Broker Key -|kafka.auth.cert| Client certificate -|kafka.auth.clientId| Kafka client Id for authentication -|kafka.auth.rejectUnauthorized | Boolean flag for accepting the valid SSL certificates -|kafka.auth.username| The username to use during authentication. -|kafka.auth.password| The password to use during authentication. -#### HTTP Server -|Field|Description| +|ws.server|WebSocket server-specific settings.| +|ws.server.adapter|Selects the WebSocket server adapter: `native`, `socket.io`, or a custom one.| +|ws.server.httpServer|A custom HTTP server instance.| +|ws.server.port + +|The port for the WebSocket server.| + +#### Cluster Configuration +|Field|Purpose| |--|--| -|http.server|HTTP server-specific configurations| -|http.client|HTTP client-specific configurations| -|http.server.adapter| The Glee adapter to use for the HTTP server. Defaults to a "native" HTTP implementation.| -|websocket.server.port| The port to use when binding the HTTP server. This is useful when your server is behind a proxy and the port exposed for consumption is not the same as the port your application should be bound to. Defaults to the port specified in the selected AsyncAPI server.| -|http.client.auth| Authentication/Authorization configuration for the client| -|http.client.auth.token| HTTP Authentication header| -|http.client.query| Query object for the client to send| -|http.client.body| Body object for the client to send -#### Auth Config -Most clients like `ws`,`kafka`, and `mqtt` have auth fields that are used for passing auth parameters. All these configurations can be an object or a function that returns the specific object defined by each protocol. +|cluster.adapter|Chooses the cluster communication adapter (default: Redis Pub/Sub).| +|cluster.name|The cluster's name.| +|cluster.url|URL of the server used by the cluster adapter.| -```js -export default async function() { - ws: { - client: { - auth: { - token: process.env.TOKEN - } - } - }, - mqtt: { - auth: ({serverName, parsedAsyncAPI}) => { - if (serverName === 'mqtt') { - return { - cert: fs.readFileSync('./cert', 'utf-8') - } - } - } - } -} -``` +#### HTTP Server Configuration +|Field|Purpose| +|--|--| +|http.server|HTTP server-specific settings.| +|http.server.adapter|Selects the HTTP server adapter.| +|http.server.port|The port for the HTTP server.| diff --git a/markdown/docs/tools/glee/function-lifecycle-events.md b/markdown/docs/tools/glee/function-lifecycle-events.md index d47f8f87bcf1..3d10988d08ce 100644 --- a/markdown/docs/tools/glee/function-lifecycle-events.md +++ b/markdown/docs/tools/glee/function-lifecycle-events.md @@ -1,5 +1,5 @@ --- -title: Function and Lifecycle events +title: Functions and Lifecycle Events weight: 40 --- @@ -13,40 +13,43 @@ export default async function (event) { } ``` -Functions take a single argument, which is the event received from a broker or a client, depending which kind of API you're building. The `event` argument has the following shape: +Functions take a single argument, which is the event received from a broker or a client, depending on the type of API you're building. The `event` argument has the following structure: |Attribute|Description| -|----|----| -|payload|The payload/body of the received event. -|headers|The headers/metadata of the received event. -|channel|The name of the channel/topic from which the event was read. -|serverName|The name of the server/broker from which the event was received. +|---------|-----------| +|payload|The payload/body of the received event.| +|headers|The headers/metadata of the received event.| +|channel|The name of the channel/topic from which the event was read.| +|serverName|The name of the server/broker from which the event was received.| -Functions may return an object to tell Glee what to do next. For instance, the following example greets the user back: +Functions may return an object to instruct Glee on what action to take next. For instance, the following example sends a greeting message to the `development` server: ```js /* onHello.js */ export default async function (event) { return { - reply: [{ + send: [{ + server: 'development', + channel: 'greets', payload: 'Greetings! How is your day going?' }] - } + }; } ``` |Attribute|Type|Description| -|---|---|---| -|send|array<[OutboundMessage](#anatomy-of-an-outbound-message)>|A list of outbound messages to send when the processing of the inbound event has finished. All clients subscribed to the given channel/topic will receive the message. -|reply|array<[OutboundMessage](#anatomy-of-an-outbound-message)>|A list of outbound messages to send as a reply when the processing of the inbound event has finished. This is useful when the target of your message is the sender of the inbound event. Note, however, that this only works when you're running Glee as a server. For example, using `reply` when receiving a WebSocket message is fine and the reply will exclusively go to the client that sent the message. However, if you're receiving a message from an MQTT broker, `reply` will work exactly the same way as `send` above, and will send the message to all the clients subscribed to the given channel/topic. -##### Anatomy of an outbound message +|---------|----|-----------| +|send|array<[OutboundMessage](#anatomy-of-an-outbound-message)>|A list of outbound messages to send after processing the inbound event. All clients subscribed to the given channel/topic will receive the message. + +##### Anatomy of an Outbound Message |Attribute|Type|Description| -|---|---|---| -|payload|string|The payload/body of the message you want to send. -|headers|object<string,string>|The headers/metadata of the message you want to send. -|channel|string|The channel/topic you want to send the message to. Defaults to `event.channel`, i.e., the same channel as the received event. -|server|string|The server/broker you want to send the message to. Defaults to `event.serverName`, i.e., the same server as the received event. -## How does Glee know which function it should execute? -Glee reads your `asyncapi.yaml` file and searches for all the `receive` actions containing an `operations` attribute field. The `operations` field serves as a mechanism to bind a given operation to a specific function file. For instance, given the folowing AsyncAPI definition: +|---------|----|-----------| +|payload|string|The payload/body of the message you want to send.| +|headers|object<string,string>|The headers/metadata of the message you want to send.| +|channel|string|The channel/topic to which you want to send the message. Defaults to `event.channel`, i.e., the same channel as the received event.| +|server|string|The server/broker to which you want to send the message. Defaults to `event.serverName`, i.e., the same server as the received event.| + +## How Does Glee Determine Which Function to Execute? +Glee reads your `asyncapi.yaml` file and looks for all the `receive` actions containing an `operations` attribute field. The `operations` field serves as a mechanism to bind a specific operation to a function file. For instance, given the following AsyncAPI definition: ```yaml ... operations: @@ -61,9 +64,9 @@ Glee maps the `onHello` operation to the `functions/onHello.js` file. # Lifecycle Events -Glee lets you bind incoming messages to functions. However, sometimes we need to be proactive and be the first ones to send a message, not necessarily as a reaction to another message. Use cases can be very diverse: from sending a message to announce our client is connected to sending a message every few seconds or minutes. +Glee allows you to bind incoming messages to functions. However, sometimes it's necessary to initiate communication proactively, not merely as a reaction to another message. Use cases can vary widely: from sending a message to announce that our client is connected, to broadcasting messages at regular intervals. -To subscribe to a lifecycle event, create a file under the `lifecycle` directory. It must have the following shape: +To subscribe to a lifecycle event, create a file under the `lifecycle` directory. It must be structured as follows: ```js export default async function ({ glee, @@ -77,41 +80,40 @@ export default async function ({ export const lifecycleEvent = 'onConnect' ``` -Each file in the `lifecycle` directory must export a default async function and the `lifecycleEvent` field, which is the [name of the event](#list-of-events) you want to subscribe to. Optionally, your function can return an object following exactly the same syntax as described above in the functions definition. +Each file in the `lifecycle` directory must export a default async function and the `lifecycleEvent` field, indicating the [name of the event](#list-of-events) you wish to subscribe to. Optionally, your function can return an object following the same syntax as described above in the functions definition. -## List of events +## List of Events |Event|Description| -|---|---| -|onConnect|A connection with a broker has been established. -|onReconnect|Glee reconnected to a broker. -|onDisconnect|A connection with a broker has been closed. -|onServerReady|Your Glee server is now ready to accept connections. -|onServerConnectionOpen|A client has opened a connection with your Glee server. -|onServerConnectionClose|A client has closed the connection with your Glee server. - -All of them take a single argument which contains information about the event: - -|Attribute|Description -|---|---| -|glee|A reference to the Glee app. -|serverName|The name of the server where the event happened. -|server|The AsyncAPI definition of the server where the event happened. -|connection|The connection where the event happened. - -## Restricting the lifecycle event - -In some cases it's useful to restrict the lifecycle event to a specific server or set of servers. To do that, add a line like the following to your lifecycle file: +|-----|-----------| +|onConnect|A connection with a broker has been established.| +|onReconnect|Glee reconnected to a broker.| +|onDisconnect|A connection with a broker has been closed.| +|onServerReady|Your Glee server is now ready to accept connections.| +|onServerConnectionOpen|A client has opened a connection with your Glee server.| +|onServerConnectionClose|A client has closed the connection with your Glee server.| + +All of them take a single argument containing information about the event: + +|Attribute|Description| +|---------|-----------| +|glee|A reference to the Glee app.| +|serverName|The name of the server where the event occurred.| +|server|The AsyncAPI definition of the server where the event occurred.| +|connection|The connection where the event occurred.| + +## Restricting the Lifecycle Event + +In some cases, it's useful to restrict the lifecycle event to a specific server or set of servers. To do this, add a line like the following to your lifecycle file: ```js export const servers = ['mosquitto'] ``` -The above example makes Glee fire the lifecycle event only if it's coming from the `mosquitto` server. +The above example ensures Glee fires the lifecycle event only if it originates from the `mosquitto` server. -Additionally, you may want to restrict the lifecycle event by channel/topic. To do that, add a line like the following to your lifecycle file: +Similarly, you may want to restrict the lifecycle event to a specific channel/topic. Add a line like this to your lifecycle file: ```js export const channels = ['user/signedup'] ``` -The above example makes Glee fire the lifecycle event only if the connection has the channel `user/signedup` listed as one of its channels. -Glee maps the `onHello` operation to the `functions/onHello.js` file. +The above example ensures Glee fires the lifecycle event only if the connection includes the channel `user/signedup`. diff --git a/markdown/docs/tools/glee/glee-auth-intro.md b/markdown/docs/tools/glee/glee-auth-intro.md index 73a136df9c14..8689ce36dbf8 100644 --- a/markdown/docs/tools/glee/glee-auth-intro.md +++ b/markdown/docs/tools/glee/glee-auth-intro.md @@ -3,20 +3,19 @@ title: 'Introduction to Glee Authentication' weight: 60 --- -Glee comes with Authentication features which help you verifying the identity of users or entities attempting to access a system or application. It ensures that only authorised individuals or systems are granted access, protecting against unauthorised intrusions and data breaches. Glee simplifies this vital process by offering multiple authentication methods, each tailored to different use cases. Following methods are the different ways to sheild your application access. +Glee comes with authentication features that help you in verifying the identity of users or entities attempting to access a system or application. It ensures that only authorized individuals or systems are granted access, protecting against unauthorized intrusions and data breaches. Glee simplifies this vital process by offering multiple authentication methods, each tailored to different use cases. The following methods are different ways to shield your application access. ### Authentication Using Authentication Functions: -Glee allows you to implement custom authentication logic by utilising authentication functions. This flexible approach enables developers to craft tailored authentication mechanisms, ensuring that access to resources is controlled precisely as required. - +Glee allows you to implement custom authentication logic by utilizing authentication functions. This flexible approach enables developers to craft tailored authentication mechanisms, ensuring that access to resources is controlled precisely as required. ### HTTP Bearer Token Authentication: In today's API-driven world, bearer token authentication is a widely adopted method. Glee supports this approach, allowing clients to present a token as proof of their identity, thus ensuring secure and efficient access to resources. -### HttpApiKey Authentication: +### HTTP API Key Authentication: Glee's authentication suite includes support for API key authentication, which is vital for protecting web APIs. By using API keys, you can regulate access to your services, making it an essential component of your application's security strategy. ### Username and Password Authentication: Traditional yet still crucial, username and password authentication remains a reliable option within Glee's toolkit. This method allows users to access systems or applications by providing their unique credentials, ensuring a familiar and straightforward login experience. #### Summary -Glee's authentication features not only provide layers of security but also offer the flexibility needed to meet your unique requirements. Whether you're developing a web application, a mobile app, or any other application, Glee's authentication methods empower you to tailor your security measures to suit the demands of your project. With Glee, you can build and maintain a secure digital environment, ensuring that only authorised users and systems gain access, protecting your valuable data and resources. \ No newline at end of file +Glee's authentication features not only provide layers of security but also offer the flexibility needed to meet your unique requirements. Whether you're developing a web application, a mobile app, or any other type of application, Glee's authentication methods empower you to tailor your security measures to suit the demands of your project. With Glee, you can build and maintain a secure digital environment, ensuring that only authorized users and systems gain access, protecting your valuable data and resources. \ No newline at end of file diff --git a/markdown/docs/tools/glee/glee-template.md b/markdown/docs/tools/glee/glee-template.md deleted file mode 100644 index ec0db7a5087a..000000000000 --- a/markdown/docs/tools/glee/glee-template.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: "Create AsyncAPI Glee template" -weight: 30 ---- -This tutorial teaches you how to create a simple glee template. You'll use the AsyncAPI Glee template that you develop to generate Javascript code. Additionally, you'll create a template code with a reusable component to reuse the custom functionality you create and test your code using an WS server. - - -{`asyncapi: 3.0.0 -info: - title: 'Hello, Glee!' - version: 1.0.0 -servers: - websockets: - host: 0.0.0.0:3000 - protocol: ws -channels: - hello: - address: hello - messages: - hello: - $ref: '#/components/messages/hello' -operations: - onHello: - action: receive - channel: - $ref: '#/channels/hello' - reply: - channel: - $ref: "#/channels/hello" - SendHello: - action: send - channel: - $ref: "#/channels/hello" -components: - messages: - hello: - payload: - type: string`} - - -Let's break it down into pieces: - - -{`info: - title: 'Hello, Glee!' - version: 1.0.0`} - - -The `info` section provides general information about the API, including its title and version. - -Moving on, let's talk about the `servers` section. - - -{`servers: - websockets: - host: 0.0.0.0:3000 - protocol: ws`} - - -The servers section defines the different servers where the API can be accessed. In this case, there is a single server named "websockets" that uses the WebSocket protocol (`ws`) and listens on the address `ws://0.0.0.0:3000`. - -Now lets move on to the `channels` section. This section is used to describe the event names your API will be publishing and/or subscribing to. - - -{`channels: - hello: - address: hello - messages: - hello: - $ref: '#/components/messages/hello' -operations: - onHello: - action: receive - channel: - $ref: '#/channels/hello' - reply: - channel: - $ref: "#/channels/hello" - sendHello: - action: send - channel: - $ref: '#/channels/hello'`} - - -The channels section defines the communication channels available in the API. In this case, there's a channel named "hello". This channel supports both sending and receiving. - -The `receive` action indicates that messages received on the `hello` channel should follow the structure defined in the hello message component. Under this action, `reply` which is in a request-reply operation, contains the payload on `onHello.js` function. -The `send` action specifies that the operation with ID `sendHello` is used for sending messages to the `hello` channel. The message structure is referenced from the hello message component. - -Next is the `payload` property under `hello` message component which is used to understand how the event should look like when publishing to that channel: - - -{`components: - messages: - hello: - payload: - type: string`} - - -The components section contains reusable elements, in this case, a definition for the "hello" message. It specifies that the payload of the "hello" message should be of type string. - -## Summary - -In this tutorial, you learned how to create an AsyncAPI specification document via a simple example with a glee template. diff --git a/markdown/docs/tools/glee/httpApiKey.md b/markdown/docs/tools/glee/httpApiKey.md index ffa3dd0e8267..587851f2f4f6 100644 --- a/markdown/docs/tools/glee/httpApiKey.md +++ b/markdown/docs/tools/glee/httpApiKey.md @@ -3,19 +3,19 @@ title: 'HttpApiKey Authentication' weight: 90 --- -## Getting started with httpAPIKey authentication +## Getting Started with HttpAPIKey Authentication -This guide will walk through how to implement authentication using the `httpAPiKey` security scheme in Glee. +This guide will walk you through how to implement authentication using the `httpApiKey` security scheme in Glee. -A sample `asyncapi.yaml` for a server with security requirements and user `HttpApiKey` security scheme is shown below: +Below is a sample `asyncapi.yaml` for a server with security requirements and the `HttpApiKey` security scheme: ```yaml -##server asyncAPI schema +## Server AsyncAPI Schema asyncapi: 3.0.0 info: - title: AsyncAPI IMDB server + title: AsyncAPI IMDB Server version: 1.0.0 - description: This app is a dummy server that would stream the trending/upcoming anime. + description: This app is a dummy server that streams the trending/upcoming anime. servers: trendingAnimeServer: host: 'localhost:8081' @@ -37,7 +37,7 @@ components: A sample `asyncapi.yaml` for a client that implements some of the requirements of the server above: ```yaml -##client asyncAPI schema +## Client AsyncAPI Schema servers: trendingAnime: host: localhost:8081 @@ -58,38 +58,36 @@ components: type: httpApiKey name: api_key in: query - ``` -The `httpApiKey` could be in either the header or query parameter. +The `httpApiKey` can be located in either the header or query parameter. -The Client asyncapi.yaml file **does not need to implement all the security requirements in the server, it only needs to implement the ones that it uses like *httpApiKey* here.** +The client `asyncapi.yaml` file **does not need to implement all the security requirements of the server; it only needs to implement the ones it uses, like *httpApiKey* here.** ### Client Side -Following the client `asyncapi.yaml` file above, create a file named `trendingAnime.ts` in the `auth` directory, since that is the server that has the security Property. +Following the client `asyncapi.yaml` file above, create a file named `trendingAnime.ts` in the `auth` directory, as this is the server that has the security property. ```bash touch auth/trendingAnime.ts ``` -When using the `HttpApiKey` security scheme, it is important that you pass the parameters as follows: +When using the `HttpApiKey` security scheme, it is important to pass the parameters as follows: ```js -export async clientAuth({ parsedAsyncAPI, serverName }) { +export async function clientAuth({ parsedAsyncAPI, serverName }) { return { apiKey: process.env.APIKEY } } ``` -`apiKey` should be the name of the security requirement as specified in your `asyncapi.yaml` file, and it's value should be a string. +`apiKey` should be the name of the security requirement as specified in your `asyncapi.yaml` file, and its value should be a string. +### Server Side -### Server side - -From the server `asyncapi.yaml` file above, create a file named `trendingAnimeServer.ts` in the `auth` directory, since that is the server that has the security Property. +From the server `asyncapi.yaml` file above, create a file named `trendingAnimeServer.ts` in the `auth` directory, as this is the server that has the security property. ```bash touch auth/trendingAnimeServer.ts @@ -99,8 +97,8 @@ On the server side, you can retrieve the values as follows: ```js -export async serverAuth({ authProps, done }) { - authProps.getHttpAPIKeys('api_key')() +export async function serverAuth({ authProps, done }) { + authProps.getHttpAPIKeys('api_key') done(true) } diff --git a/markdown/docs/tools/glee/index.md b/markdown/docs/tools/glee/index.md index ef5638eec358..0f401af13030 100644 --- a/markdown/docs/tools/glee/index.md +++ b/markdown/docs/tools/glee/index.md @@ -1,17 +1,17 @@ --- -title: Getting Started +title: Kickstarting Your Journey with Glee weight: 10 --- -## Introduction +## Welcome to Glee -[Glee](https://github.com/asyncapi/glee) is a spec-first framework that helps you build server-side applications. That means it operates on the principle of defining the API specification (AsyncAPI) before diving into the actual implementation of the application logic. It leverages that principle to make you more productive: +[Glee](https://github.com/asyncapi/glee) introduces a refreshing approach to building server-side applications, emphasizing a spec-first methodology. This means your journey begins with defining the API specification (AsyncAPI) before writing a single line of application logic. Here's how Glee enhances your development experience: -- Glee ensures your code and AsyncAPI definition are on par, eliminating the problem of outdated documentation. By having both the code and the AsyncAPI definition in sync, you can ensure that the API documentation is always up to date, accurate, and reflects the current state of the application. Glee takes care of this automatically for you. -- Glee lets you focus on what matters and handles the rest for you. You only write the code for your business use-case. Glee takes care of performance, scalability, resilience, and everything you need to make your application production-ready. -- Glee validates the schema of the payload that it receives, if it doesn't conform to the schema that is defined in the AsyncAPI document, it throw an error telling user that the server received an invalid payload. +- **Always Updated Documentation**: Glee aligns your codebase with the AsyncAPI definition, ensuring your API documentation is constantly updated and reflective of your application's current capabilities. +- **Developer Centricity**: With Glee, your focus remains on the business logic. Leave the concerns of performance, scalability, and resilience to Glee, as it equips your application to be production-ready from the get-go. +- **Schema Validation**: Glee rigorously checks incoming payloads against the schema outlined in your AsyncAPI document. Any discrepancies result in an error, maintaining the integrity and reliability of your server's data processing. -Now, before you get started with a glee project, let's take a high level view of Application structure what glee resonates with. +Before you dive into Glee, let's explore its application structure and understand what makes Glee unique. ## Application structure @@ -35,121 +35,8 @@ Glee expects your project to have some files and folders with special names. Whe |functions|**Required.** This directory contains all the functions that Glee must execute when it receives a message from the server. Each file must export a default async function. |lifecycle|This directory contains application lifecycle functions. These functions will be executed when certain events happen in the application. E.g., `onConnect`, `onServerReady`, `onDisconnect`, etc. |.env|The environment variables of your application. **DO NOT PUT SECRETS HERE**. -|asyncapi.(yaml or json or yml)|**Required.** The [AsyncAPI](https://www.asyncapi.com/docs/specifications/latest) file defines your API. Make sure all the `publish` operations have an assigned `operationId` that matches a file name (excluding the extension) in the `functions` directory. -|glee.config.js| The Glee configuration file. +|asyncapi.(yaml or json or yml)|**Required.** The [AsyncAPI](https://www.asyncapi.com/docs/specifications/latest) file defines your API. Make sure all the `receive` operations have a name that matches a file name (excluding the extension) in the `functions` directory. +|glee.config.js| The Glee [configuration file](./env-vars-config.md). |package.json|**Required.** The Node.js package definition file. Make sure you include `@asyncapi/glee` as a dependency and add two scripts: `dev` and `start`. They should be running `glee dev` and `glee start` respectively. To understand the structure in a broader way, please refer to the associated page's links. - -### Let's create a glee project to simplify the app structure - -We will consider a simple WebSocket API using glee to understand its magic. We will create a simple WebSocket server that receives a current time from the client and then send a "good morning", "good evening" or "good night" respectively. - -To setup a project, you should follow our installation page on how to setup glee on your environment. - -We recommend creating a new Glee app using our official CLI which sets up everything automatically. (You don't need to create an empty directory. create-glee-app will make one for you.) To create a project, run: `asyncapi new glee` - -Once the process is completed, you should have a new Glee app ready for development and find the files that were made. - -#### Define our Spec for our API - -Glee being a spec-first framework, development starts with defining your API spec. To know more details into it, you can follow glee template to understand it step by step. For our case we will define our API: - -```yaml -asyncapi: 3.0.0 -info: - title: Greet Bot - version: 1.0.0 -servers: - websockets: - host: 0.0.0.0:3000 - protocol: ws -channels: - greet: - address: greet - messages: - greet: - $ref: '#/components/messages/greet' - time: - $ref: '#/components/messages/time' - time: - address: time - messages: - time: - $ref: '#/components/messages/time' -operations: - onGreet: - action: receive - channel: - $ref: '#/channels/greet' - reply: - channel: - $ref: '#/channels/greet' - sendGreet: - action: send - channel: - $ref: '#/channels/time' -components: - messages: - time: - payload: - type: object - properties: - currentTime: - type: number - name: - type: string - greet: - payload: - type: string - -``` - -This will be the Specification that defines our API, in our case, it is very simple, as we will be sending a name and the time of the day, and our API will greet us accordingly. - -One thing to note here is the `operations` item, this is needed and is a crucial part of glee, as this is how we will be connecting our business logic with our spec, `onGreet` is the name of the function that will be called every time a certain operation occurs. In our case whenever `/greet` channel receives a message, `onGreet` function is called. - -#### Define our operation function - -Now for our case, we will be adding a file `functions/onGreet.js` and writing up the logic for parsing our time and sending a response. - -```javascript -export default async function (event) { - const { name, time } = event.payload - const t = new Date(time) - const curHr = t.getHours() - let response = '' - if (curHr < 12) { - response = `Good Morning ${name}` - } else if (curHr < 18) { - response = `Good Afternoon ${name}` - } else { - response = `Good Evening ${name}` - } - return { - reply: [ - { - payload: response, - }, - ], - } -} - -``` - -Every file in the functions folder acts as a handler to develop business logic for glee, every file should export an async function that receives an event parameter, where you have access to payload and server details. - -#### Running and testing our application - -We will execute the application and carry out testing with Postman to ensure that it is functioning as intended. - -Now to execute our glee application, just run: - -``` -npm run dev -# or -npm run start -``` -To send a WebSocket request with a payload e.g. `{"name":"john", "time": "1567906535"}` to `ws://localhost:3000/greet`, open Postman and checkout the endpoint: - -So, this is how easy it is to build a WebSocket API using Glee. You can also check out the example code [here](https://github.com/Souvikns/greet-bot). diff --git a/markdown/docs/tools/glee/installation.md b/markdown/docs/tools/glee/installation.md index b3d587e39f31..a4cfc62ad71c 100644 --- a/markdown/docs/tools/glee/installation.md +++ b/markdown/docs/tools/glee/installation.md @@ -1,42 +1,64 @@ --- -title: 'Installation guide' -weight: 20 + +title: 'Glee Installation Guide' +weight: 30 + --- -## Glee Installation +### Preparing for Installation + +Before starting with Glee, ensure that NPM, Node.js, and the [AsyncAPI CLI](https://github.com/asyncapi/cli) are already set up on your system. + +> Need help installing AsyncAPI CLI? Check out the [CLI Installation Guide](https://www.asyncapi.com/docs/tools/cli/installation). -Before installing Glee into your project, make sure you have pre-installed NPM, NodeJs and [AsyncAPI CLI](https://github.com/asyncapi/cli) tools on your system. +### Starting with Glee -### Automatic Installation +Creating a new Glee application can be approached in three distinct ways: + * [Begin with an existing AsyncAPI document](#initialize-with-an-asyncapi-document). + * [Use a predefined template](#start-with-a-template). + * [Opt for Manual Installation](#manual-installation) (recommended for advanced users keen on understanding Glee's inner workings). -The best way to get started with Glee is by using AsyncAPI CLI, which sets up everything automatically for you. -To create a project, run: +### Initialize with an AsyncAPI Document +If you already have an AsyncAPI specification file, you can jumpstart your project by using the `-f` or `--file` flag to specify the file path. The CLI will leverage this to set up your project. ```sh -asyncapi new glee +asyncapi new glee -f asyncapi.yaml ``` -> For more information on how to install the AsynAPI CLI, you can review the [CLI installation guide](https://www.asyncapi.com/docs/tools/cli/installation). +This command generates all necessary files. Just open the project in your editor, and start integrating your authentication and business logic. + +### Start with a Template + +For those without a custom AsyncAPI file and looking to experiment, starting with a template is an excellent choice. These are simple Glee projects that the AsyncAPI CLI can generate for you. + +Use the `-t` or `--template` flag to specify the template name. Currently, two templates are available: -On installation, you'll find next steps after your project created: +1) **default**: Responds with a string upon receiving a string. +2) **tutorial**: Designed for [this tutorial](https://www.asyncapi.com/docs/tutorials/generate-code). +To initiate a project with the default template: + +```sh +asyncapi new glee -t default ``` -Your project "project" has been created successfully! +After installation, follow these steps: + +``` Next steps: cd project - npm install + npm install --ignore-scripts npm run dev -Also, you can already open the project in your favorite editor and start tweaking it +Feel free to open the project in your preferred editor and start customizing it. ``` -While making twists to your application, you can follow along with our getting started guide on the relevant page. +Refer to our Getting Started guide for further assistance during customization. ### Manual Installation -To manually create a new app, create a new folder e.g. `myapp` so the folder structure would look like below; +For a hands-on setup, start by creating a new directory, e.g., `myapp`, and structure it as follows: ``` ├─ functions (required) @@ -51,14 +73,14 @@ To manually create a new app, create a new folder e.g. `myapp` so the folder str ├─ package.json (required) ``` -Install the required packages inside a new folder: +Inside this new folder, initialize and install Glee: ```js npm init -y npm install @asyncapi/glee ``` -Open your package.json file and add the following scripts: +Edit your `package.json` to include the following scripts: ```js { @@ -70,19 +92,18 @@ Open your package.json file and add the following scripts: } ``` -These scripts refer to the different stages of developing an application. - -- `glee docs`: This script generates documentation for your project using the "Glee" documentation tool. This documentation includes information about your project's APIs, modules, and usage instructions. - -- `glee dev`: This script is used for starting a development server. It launches a local development server, build your project in development mode, or perform other development-related tasks. +These scripts serve different development stages: -- `glee start`: This script is responsible for starting your project or application. It is used to launch a production-ready server or application instance. +- `glee docs`: Generates your project documentation. +- `glee dev`: Starts a local development server, building your project in a development-friendly environment. +- `glee start`: Launches your project for production use. -#### Create `asyncapi.yaml` file and other required directories +#### Setting up `asyncapi.yaml` and Required Directories -Create a yaml file that supports capable of receiving a "hello {name}" message with the protocol as `ws` and the channel name as `hello` the hello API will subscribe to. The operationId property is `onHello` that's the name of function and the payload property is type string publishing to that channel. +Craft an `asyncapi.yaml` file capable of receiving a "hello \{name\}" message via WebSocket (`ws`) protocol on the `hello` channel. Define the operation ID as `onHello`, indicating the function to be called, and set the payload type to string for publishing on that channel. ```yaml +# AsyncAPI Specification for Hello, Glee! asyncapi: 3.0.0 info: title: 'Hello, Glee!' @@ -102,9 +123,6 @@ operations: action: receive channel: $ref: '#/channels/hello' - reply: - channel: - $ref: "#/channels/hello" SendHello: action: send channel: @@ -116,19 +134,21 @@ components: type: string ``` -Create an operation function `onHello.js` inside `myapp/functions`: +Create a function `onHello.js` in `myapp/functions`: ```js export default async function (event) { return { - reply: [{ + send: [{ + server: "websockets", + channel: "hello", payload: `Hello from Glee! You said: "${event.payload}".` }] } } ``` -#### Run the Development Server +#### Launching the Development Server -- Run `npm run dev` to start the development server. -- Connect to `ws://localhost:3000/hello` and send a WebSocket request with a payload e.g. {"john"} +- Execute `npm run dev` to start the server. +- Connect to `ws://localhost:3000/hello` and send a WebSocket request like `{"john"}`. \ No newline at end of file diff --git a/markdown/docs/tools/glee/your-first-glee-app.md b/markdown/docs/tools/glee/your-first-glee-app.md new file mode 100644 index 000000000000..dfdc3051f91c --- /dev/null +++ b/markdown/docs/tools/glee/your-first-glee-app.md @@ -0,0 +1,125 @@ +--- + +title: Building Your First Glee Application +weight: 20 + +--- + +#### Crafting Your API Specification + +Let's start with a straightforward WebSocket API using Glee. Imagine a WebSocket server that receives the current time from a client and responds with a greeting like "good morning", "good evening", or "good night" based on the time provided. + +In Glee, which is a spec-first framework, the journey begins with defining your API specification. If you're unfamiliar with what an API spec is or how to create one, we recommend going through the tutorials available [here](https://www.asyncapi.com/docs/tutorials) before proceeding. For this project, here's how we define our API: + +```yaml +asyncapi: 3.0.0 +info: + title: Greet Bot + version: 1.0.0 +servers: + websockets: + host: localhost:3000 + protocol: ws +channels: + greet: + address: /greet + messages: + greet: + payload: + type: string + time: + payload: + type: object + properties: + currentTime: + type: number + name: + type: string +operations: + receiveTime: + action: receive + channel: + $ref: '#/channels/greet' + messages: + - $ref: "#/channels/greet/messages/time" + sendGreet: + action: send + channel: + $ref: '#/channels/greet' + messages: + - $ref: "#/channels/greet/messages/greet" +``` + +Store this in a file named `asyncapi.yml`. + +This spec shows that our app can perform two operations on a single channel: receiving time and sending a greeting. We've used JSON Schema to define what `time` and `greet` messages look like. + +Note the `operations` section. It's essential in Glee, linking your business logic to your spec. For instance, `receiveTime` is the function invoked when the `/greet` channel receives a message. + +> Tip: Including a `send` operation isn't mandatory but is recommended for validating outgoing messages against your spec. + +### Initiating Your Glee Project + +For ease and efficiency, start your Glee app with our CLI, which automates the setup. In your `asyncapi.yml` file's directory, execute: `asyncapi new glee --name GreetBot --file asyncapi.yml` + +It will prompt you with a list of server names and let you select which servers you want Glee to create a server for. select the `websockets` and continue. + +Then, navigate to your application's folder and install the dependencies: + +```shell +cd GreetBot +npm install --ignore-scripts +``` + +You now have a Glee app scaffolded and ready for development. + +#### Implementing the Operation Function + +Navigate to `functions/receiveTime.js` and input the logic to analyze the time and generate the appropriate response. + +```ts +import { GleeFunction } from '@asyncapi/glee'; + +const receiveTime: GleeFunction = async (event) => { + const { name, time } = event.payload; + const t = new Date(time); + const curHr = t.getHours(); + let response = ''; + if (curHr < 12) { + response = `Good Morning, ${name}!`; + } else if (curHr < 18) { + response = `Good Afternoon, ${name}!`; + } else { + response = `Good Evening, ${name}!`; + } + return { + send: [ + { + server: 'websockets', + channel: 'greet', + payload: response, + }, + ], + }; +}; + +export default receiveTime; +``` + +> Note: Want to know more about functions? [Click Here!](./function-lifecycle-events.md) + +Each file in the `functions` directory is a handler where you can craft your business logic. Every handler should export an asynchronous function that takes an `event` parameter, giving you access to the payload and server details. + +#### Running and Evaluating Your App + +To launch and test the app's functionality, follow these steps: + +Run your Glee application using: + +``` +npm run dev +# or +npm run start +``` + +To test, open a WebSocket connection to `ws://localhost:3000/greet` in Postman and send `{"name":"John","time":"1567906535"}`. Watch as your Glee app responds appropriately. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 879c389d24d7..14183711e3d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7558,20 +7558,14 @@ "version": "8.56.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -12141,9 +12135,9 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -29893,11 +29887,10 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.92.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", - "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", @@ -29906,7 +29899,7 @@ "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", diff --git a/pages/index.tsx b/pages/index.tsx index 348311a7aa2a..f04a906e5ea5 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,23 +1,25 @@ +import Head from '@/components/Head'; +import AsyncAPIColorIcon from '@/components/icons/AsyncAPIColorIcon'; +import Loader from '@/components/Loader'; import { languageDetection } from '@/utils/i18n'; -import Head from '../components/Head'; - /** * @description This is the home page which is the first page that loads when the user visits the website. */ export default function HomePage() { - const loader: string = 'img/loaders/loader.png'; // preloader image for the tools - languageDetection(); return ( <>
-
- Loading... -
Loading...
-
+ } + className='my-60' + dark={false} + pulsating + />
); diff --git a/public/img/logos/asyncapi-horizontal-logo.svg b/public/img/logos/asyncapi-horizontal-logo.svg new file mode 100644 index 000000000000..6f0fc27579e9 --- /dev/null +++ b/public/img/logos/asyncapi-horizontal-logo.svg @@ -0,0 +1,82 @@ + + AsyncAPI Logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/logos/asyncapi-horizontal-white-logo.svg b/public/img/logos/asyncapi-horizontal-white-logo.svg new file mode 100644 index 000000000000..2a9e5c4c7167 --- /dev/null +++ b/public/img/logos/asyncapi-horizontal-white-logo.svg @@ -0,0 +1,82 @@ + + AsyncAPI Logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/types/components/tools/CheckboxPropsType.ts b/types/components/tools/CheckboxPropsType.ts new file mode 100644 index 000000000000..e535bb41dd4c --- /dev/null +++ b/types/components/tools/CheckboxPropsType.ts @@ -0,0 +1,27 @@ +export interface CheckboxProps { + // eslint-disable-next-line prettier/prettier + + /** The name to be displayed inside the checkbox. */ + name: string; + + /** If the checkbox is checked or not. */ + checked: boolean; + + /** The background color of the checkbox. */ + bgColor?: string; + + /** The text color of the checkbox. */ + textColor?: string; + + /** The border color of the checkbox. */ + borderColor?: string; + + /** The background color of the checkbox when it is checked. */ + checkedStateBgColor?: string; + + /** The text color of the checkbox when it is checked. */ + checkedStateTextColor?: string; + + /** Function to handle the click event of the checkbox. */ + handleClickOption: (name: string) => void; +} diff --git a/types/components/tools/TogglePropsType.ts b/types/components/tools/TogglePropsType.ts new file mode 100644 index 000000000000..5514aeb0f74f --- /dev/null +++ b/types/components/tools/TogglePropsType.ts @@ -0,0 +1,18 @@ +export interface ToggleProps { + // eslint-disable-next-line prettier/prettier + + /** Current state of the toggle. */ + checked: boolean; + + /** Function to update the toggle state. */ + setChecked: React.Dispatch>; + + /** Label text for the toggle. */ + label?: string; + + /** The background color of the checkbox. */ + bgColor?: string; + + /** The background color of the checkbox when it is checked. */ + checkedStateBgColor?: string; +}