diff --git a/components/Hero.js b/components/Hero.js index 81000be487cd..03f57705d801 100644 --- a/components/Hero.js +++ b/components/Hero.js @@ -10,7 +10,7 @@ import AlgoliaSearch, { SearchButton } from './AlgoliaSearch'; // Import Algolia import IconLoupe from './icons/Loupe'; import { useTranslation, -} from "next-i18next-static-site"; +} from "../lib/i18n"; export default function Hero({ className = ''}) { diff --git a/components/link.js b/components/link.js index 4fe488bf107f..de49d3b1895d 100644 --- a/components/link.js +++ b/components/link.js @@ -1,6 +1,6 @@ import Link from "next/link"; import { useRouter } from "next/router"; -import { defaultLanguage, languages } from "next-i18next-static-site"; +import { defaultLanguage, languages } from "../lib/i18n"; const LinkComponent = ({ children, locale, ...props }) => { const router = useRouter(); diff --git a/components/navigation/NavBar.js b/components/navigation/NavBar.js index 0505adfe3869..08188655f586 100644 --- a/components/navigation/NavBar.js +++ b/components/navigation/NavBar.js @@ -19,7 +19,8 @@ import { defaultLanguage, languages, useTranslation, -} from "next-i18next-static-site"; +} from "../../lib/i18n"; +import browserLanguageDetector from "../../lib/browserLanguageDetector"; const isMobile = isMobileDevice(); const uniqueLangs = [...new Set(["EN", "DE"])].map((repo) => ({ @@ -35,10 +36,15 @@ export default function NavBar({ const { pathname, query, asPath } = router; const [open, setOpen] = useState(); const [mobileMenuOpen, setMobileMenuOpen] = useState(); - const [lang, setLang] = useState("en"); const { i18n } = useTranslation(); - const changeLanguage = async (locale) => { + const changeLanguage = async (locale, langPicker) => { + + // Verifies if the language change is from langPicker or the browser-api + if(langPicker){ + localStorage.setItem('i18nLang', locale); + } + // Detect current language const slug = asPath.split("/")[1]; const langSlug = languages.includes(slug) && slug; @@ -66,6 +72,11 @@ export default function NavBar({ router.push(href); }; + // To be enabled on the last PR + // useEffect(() => { + // changeLanguage(browserLanguageDetector(), false); + // }, []); + function outsideClick(menu) { if (open !== menu) return; setOpen(null); @@ -172,8 +183,7 @@ export default function NavBar({ {/* { - setLang(value.toLowerCase()); - changeLanguage(value.toLowerCase()); + changeLanguage(value.toLowerCase(), true); }} className="" selected={i18n.language.toLocaleUpperCase()} diff --git a/config/AMBASSADORS_MEMBERS.json b/config/AMBASSADORS_MEMBERS.json index 27fa3a73a609..b4ab927f8d81 100644 --- a/config/AMBASSADORS_MEMBERS.json +++ b/config/AMBASSADORS_MEMBERS.json @@ -55,12 +55,12 @@ "title": "Senior Solution Architect / Head of API Experience and Operations", "github": "danielkocot", "twitter": "dk_1977", - "linkedin": "daniel-kocot", + "linkedin": "danielkocot", "company": "Codecentric AG", "country": "πŸ‡©πŸ‡ͺ", "contributions": [ { - "type": "article", + "type": "article", "title": "AsyncAPI - Documentation of event and message-driven architectures", "date": { "year": 2021, @@ -68,32 +68,32 @@ }, "link": "https://blog.codecentric.de/en/2021/09/asyncapi-documentation-event-message-driven-architectures/?hmsr=joyk.com&utm_source=joyk.com&utm_medium=referral" }, - { - "type": "article", + { + "type": "article", "title": "AsyncAPI specification updates", "date": { "year": 2022, "month": "February" }, - "link": "https://blog.codecentric.de/en/2022/02/asyncapi-version-2-3-0-specification-updates/" + "link": "https://blog.codecentric.de/en/2022/02/asyncapi-version-2-3-0-specification-updates/" }, { "type": "presentation", - "title": "AsyncAPI 101", + "title": "AsyncAPI 101", "date": { "year": 2022, "month": "May" - }, + }, "link": "https://www.buildingiot.de/veranstaltung-13856-0-asyncapi-101.html" }, { "type": "presentation", - "title": "Adopting AsyncAPI in Enterprisey Contexts, AsyncAPI Conference", + "title": "Adopting AsyncAPI in Enterprisey Contexts, AsyncAPI Conference", "date": { "year": 2022, "month": "November" - }, - "link": "https://www.youtube.com/watch?v=_wTcV63jrnU" + }, + "link": "https://www.youtube.com/watch?v=_wTcV63jrnU" } ] }, diff --git a/config/MAINTAINERS.json b/config/MAINTAINERS.json index 98015228c242..b9419b156425 100644 --- a/config/MAINTAINERS.json +++ b/config/MAINTAINERS.json @@ -72,7 +72,7 @@ }, { "name": "Cameron Rushton", - "github": "CameronRushton", + "github": "cameronrushton", "slack": "U01DVKKAV5K", "availableForHire": false, "company": "Solace", @@ -136,7 +136,7 @@ }, { "name": "Gerald Loeffler", - "github": "GeraldLoeffler", + "github": "geraldloeffler", "linkedin": "geraldloeffler", "slack": "U01P5QDLP0X", "availableForHire": false, @@ -167,7 +167,7 @@ }, { "name": "Khuda Dad Nomani", - "github": "KhudaDad414", + "github": "khudadad414", "twitter": "KhudaDadNomani", "linkedin": "khudadadnomani", "slack": "U01RVRD1TCL", @@ -175,10 +175,10 @@ "company": "Postman", "isTscMember": true, "repos": [ - "optimizer", "bindings", "glee", - ".github" + ".github", + "optimizer" ] }, { @@ -266,7 +266,7 @@ { "name": "Azeez Elegbede", "linkedin": "acebuild", - "github": "AceTheCreator", + "github": "acethecreator", "twitter": "_acebuild", "slack": "U01RWDD69PZ", "company": "Postman", @@ -307,7 +307,7 @@ }, { "name": "Nektarios Fifes", - "github": "NektariosFifes", + "github": "nektariosfifes", "linkedin": "nektarios-fifes-372740220", "slack": "U01SE93Q48N", "availableForHire": true, @@ -318,7 +318,7 @@ }, { "name": "Pavel Bodiachevskii", - "github": "Pakisan", + "github": "pakisan", "slack": "U0132LQU8C9", "twitter": "pbodiachevskii", "availableForHire": false, @@ -387,7 +387,7 @@ }, { "name": "Souvik De", - "github": "Souvikns", + "github": "souvikns", "slack": "U01SGCZMJKW", "twitter": "souvik_ns", "linkedin": "souvik-de-a2b941169", @@ -417,7 +417,7 @@ }, { "name": "David Pereira", - "github": "BOLT04", + "github": "bolt04", "twitter": "BOLT2938", "slack": "U02EC8BT0TX", "linkedin": "jos\u00e9-david-pereira-13ba5315a", @@ -442,7 +442,7 @@ }, { "name": "Kieran Murphy", - "github": "KieranM1999", + "github": "kieranm1999", "linkedin": "kieran-murphy-175b0412b", "availableForHire": false, "slack": "U02FT2TKM37", @@ -454,7 +454,7 @@ }, { "name": "Tom Jefferson", - "github": "JEFFLUFC", + "github": "jefflufc", "linkedin": "t-jefferson", "slack": "U02FPPCEH6H", "availableForHire": false, @@ -490,7 +490,7 @@ }, { "name": "Semen Tenishchev", - "github": "Tenischev", + "github": "tenischev", "linkedin": "semen-tenishchev", "availableForHire": true, "slack": "U011D1DAU6S", @@ -501,7 +501,7 @@ }, { "name": "Samridhi Agrawal", - "github": "Samridhi-98", + "github": "samridhi-98", "slack": "U02T2MY9W5T", "linkedin": "samridhi-agrawal-1713201ab", "availableForHire": false, @@ -538,7 +538,7 @@ }, { "name": "Florence Njeri", - "github": "Florence-Njeri", + "github": "florence-njeri", "linkedin": "florencenjeri", "slack": "U03D18YKX2M", "twitter": "njericodes", @@ -578,7 +578,7 @@ }, { "name": "Alexander Wichmann", - "github": "VisualBean", + "github": "visualbean", "linkedin": "alexcarlsen", "slack": "U04C58GB8TF", "availableForHire": false, @@ -592,7 +592,7 @@ "name": "Barba\u00f1o Gonz\u00e1lez", "linkedin": "barbano-gonzalez-moreno", "twitter": "BarbanoGonzalez", - "github": "Barbanio", + "github": "barbanio", "slack": "U01J42QDSLU", "availableForHire": false, "company": "Postman", @@ -616,7 +616,7 @@ }, { "name": "Heiko Henning", - "github": "GreenRover", + "github": "greenrover", "slack": "U03AC4G51H8", "availableForHire": false, "company": "mtrail GmbH", diff --git a/config/all-tags.json b/config/all-tags.json index d4e7190245ba..0cbbd835368c 100644 --- a/config/all-tags.json +++ b/config/all-tags.json @@ -1 +1 @@ -{"languages":[{"name":"Go/Golang","color":"bg-[#8ECFDF]","borderColor":"border-[#00AFD9]"},{"name":"Java","color":"bg-[#ECA2A4]","borderColor":"border-[#EC2125]"},{"name":"JavaScript","color":"bg-[#F2F1C7]","borderColor":"border-[#BFBE86]"},{"name":"HTML","color":"bg-[#E2A291]","borderColor":"border-[#E44D26]"},{"name":"C/C++","color":"bg-[#93CDEF]","borderColor":"border-[#0080CC]"},{"name":"C#","color":"bg-[#E3AFE0]","borderColor":"border-[#9B4F96]"},{"name":"Python","color":"bg-[#A8D0EF]","borderColor":"border-[#3878AB]"},{"name":"TypeScript","color":"bg-[#7DBCFE]","borderColor":"border-[#2C78C7]"},{"name":"Kotlin","color":"bg-[#B1ACDF]","borderColor":"border-[#756BD9]"},{"name":"Scala","color":"bg-[#FFA299]","borderColor":"border-[#DF301F]"},{"name":"Markdown","color":"bg-[#BABEBF]","borderColor":"border-[#445B64]"},{"name":"YAML","color":"bg-[#FFB764]","borderColor":"border-[#F1901F]"},{"name":"R","color":"bg-[#84B5ED]","borderColor":"border-[#246BBE]"},{"name":"Ruby","color":"bg-[#FF8289]","borderColor":"border-[#FF000F]"},{"name":"Rust","color":"bg-[#FFB8AA]","borderColor":"border-[#E43716]"},{"name":"Shell","color":"bg-[#87D4FF]","borderColor":"border-[#389ED7]"},{"name":"Groovy","color":"bg-[#B6D5E5]","borderColor":"border-[#609DBC]"}],"technologies":[{"name":"Node.js","color":"bg-[#BDFF67]","borderColor":"border-[#84CE24]"},{"name":"Hermes","color":"bg-[#8AEEBD]","borderColor":"border-[#2AB672]"},{"name":"React JS","color":"bg-[#9FECFA]","borderColor":"border-[#08D8FE]"},{"name":".NET","color":"bg-[#A184FF]","borderColor":"border-[#5026D4]"},{"name":"ASP.NET","color":"bg-[#71C2FB]","borderColor":"border-[#1577BC]"},{"name":"Springboot","color":"bg-[#98E279]","borderColor":"border-[#68BC44]"},{"name":"AWS","color":"bg-[#FF9F59]","borderColor":"border-[#EF6703]"},{"name":"Docker","color":"bg-[#B8E0FF]","borderColor":"border-[#2596ED]"},{"name":"Node-RED","color":"bg-[#FF7474]","borderColor":"border-[#8F0101]"},{"name":"Maven","color":"bg-[#FF6B80]","borderColor":"border-[#CA1A33]"},{"name":"Saas","color":"bg-[#6AB8EC]","borderColor":"border-[#2275AD]"},{"name":"Kubernetes-native","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Scala","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Azure","color":"bg-[#4B93FF]","borderColor":"border-[#015ADF]"},{"name":"Jenkins","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Flask","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Nest Js","color":"bg-[#E1224E]","borderColor":"border-[#B9012b]"},{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Socket.IO","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Liquid","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Kotlin","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Spring Cloud Streams","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"JHipster JDL","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Groovy","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Markdown","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Shell","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"WebComponents","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Babel","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Storybook","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"AsyncAPI Generator","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"JetBrains","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"IntelliJ IDEA","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"VSCode","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"SmartPaste","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}]} \ No newline at end of file +{"languages":[{"name":"Go/Golang","color":"bg-[#8ECFDF]","borderColor":"border-[#00AFD9]"},{"name":"Java","color":"bg-[#ECA2A4]","borderColor":"border-[#EC2125]"},{"name":"JavaScript","color":"bg-[#F2F1C7]","borderColor":"border-[#BFBE86]"},{"name":"HTML","color":"bg-[#E2A291]","borderColor":"border-[#E44D26]"},{"name":"C/C++","color":"bg-[#93CDEF]","borderColor":"border-[#0080CC]"},{"name":"C#","color":"bg-[#E3AFE0]","borderColor":"border-[#9B4F96]"},{"name":"Python","color":"bg-[#A8D0EF]","borderColor":"border-[#3878AB]"},{"name":"TypeScript","color":"bg-[#7DBCFE]","borderColor":"border-[#2C78C7]"},{"name":"Kotlin","color":"bg-[#B1ACDF]","borderColor":"border-[#756BD9]"},{"name":"Scala","color":"bg-[#FFA299]","borderColor":"border-[#DF301F]"},{"name":"Markdown","color":"bg-[#BABEBF]","borderColor":"border-[#445B64]"},{"name":"YAML","color":"bg-[#FFB764]","borderColor":"border-[#F1901F]"},{"name":"R","color":"bg-[#84B5ED]","borderColor":"border-[#246BBE]"},{"name":"Ruby","color":"bg-[#FF8289]","borderColor":"border-[#FF000F]"},{"name":"Rust","color":"bg-[#FFB8AA]","borderColor":"border-[#E43716]"},{"name":"Shell","color":"bg-[#87D4FF]","borderColor":"border-[#389ED7]"},{"name":"Groovy","color":"bg-[#B6D5E5]","borderColor":"border-[#609DBC]"}],"technologies":[{"name":"Node.js","color":"bg-[#BDFF67]","borderColor":"border-[#84CE24]"},{"name":"Hermes","color":"bg-[#8AEEBD]","borderColor":"border-[#2AB672]"},{"name":"React JS","color":"bg-[#9FECFA]","borderColor":"border-[#08D8FE]"},{"name":".NET","color":"bg-[#A184FF]","borderColor":"border-[#5026D4]"},{"name":"ASP.NET","color":"bg-[#71C2FB]","borderColor":"border-[#1577BC]"},{"name":"Springboot","color":"bg-[#98E279]","borderColor":"border-[#68BC44]"},{"name":"AWS","color":"bg-[#FF9F59]","borderColor":"border-[#EF6703]"},{"name":"Docker","color":"bg-[#B8E0FF]","borderColor":"border-[#2596ED]"},{"name":"Node-RED","color":"bg-[#FF7474]","borderColor":"border-[#8F0101]"},{"name":"Maven","color":"bg-[#FF6B80]","borderColor":"border-[#CA1A33]"},{"name":"Saas","color":"bg-[#6AB8EC]","borderColor":"border-[#2275AD]"},{"name":"Kubernetes-native","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Scala","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Azure","color":"bg-[#4B93FF]","borderColor":"border-[#015ADF]"},{"name":"Jenkins","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Flask","color":"bg-[#D7C7F2]","borderColor":"border-[#A387D2]"},{"name":"Nest Js","color":"bg-[#E1224E]","borderColor":"border-[#B9012b]"},{"name":"TypeScript","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Socket.IO","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Liquid","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Kotlin","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Spring Cloud Streams","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"JHipster JDL","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Groovy","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Markdown","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Shell","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"WebComponents","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Babel","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"Storybook","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"AsyncAPI Generator","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"VSCode","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"SmartPaste","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"JetBrains","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"},{"name":"IntelliJ IDEA","color":"bg-[#61d0f2]","borderColor":"border-[#40ccf7]"}]} \ No newline at end of file diff --git a/config/meetings.json b/config/meetings.json index 4ff41cecd088..bfc69416cdac 100644 --- a/config/meetings.json +++ b/config/meetings.json @@ -1,25 +1,4 @@ [ - { - "title": "Spec 3.0 Meeting", - "calLink": "https://www.google.com/calendar/event?eid=Z2l0am1xbTBhcm8xa2sxc2dyOGdoaXRmZTQgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/670", - "banner": "", - "date": "2023-04-26T15:00:00.000Z" - }, - { - "title": "Tackling interoperability challenges in open-source", - "calLink": "https://www.google.com/calendar/event?eid=M2Njb2dib2VvMXF1dmR1bGJ0ZG1tb2txMWsgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/681", - "banner": "https://user-images.githubusercontent.com/66913810/233324999-bce12c6f-6e8e-4aca-acf5-053cfa22378a.png", - "date": "2023-04-26T09:00:00.000Z" - }, - { - "title": "Community Meeting", - "calLink": "https://www.google.com/calendar/event?eid=YjcwZ2ZmOXNmMmU1YmRybXB0azk1Y2prb3MgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/688", - "banner": "https://user-images.githubusercontent.com/40604284/233369404-38892fbe-7082-4492-8aed-0a97ee8df011.png", - "date": "2023-05-02T08:00:00.000Z" - }, { "title": "AsyncAPI x Google Season of Doc's 2023", "calLink": "https://www.google.com/calendar/event?eid=Yzdyb2F1c3RjOXVvcTh2NXFiZGpyNjgzN3MgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", @@ -190,17 +169,17 @@ }, { "title": "Spec 3.0 Docs Meeting", - "calLink": "https://www.google.com/calendar/event?eid=aWhzNWwxZWkxdWVlMWhvbGs4aWY2YzU1am8gY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/791", + "calLink": "https://www.google.com/calendar/event?eid=cG9iOHNqZGlrbmg4cnUxanMzMTgyN3AxdnMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/792", "banner": "", - "date": "2023-08-03T14:30:00.000Z" + "date": "2023-08-17T14:30:00.000Z" }, { "title": "Spec 3.0 Docs Meeting", - "calLink": "https://www.google.com/calendar/event?eid=cG9iOHNqZGlrbmg4cnUxanMzMTgyN3AxdnMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/792", + "calLink": "https://www.google.com/calendar/event?eid=aHJwdnA1bzI1ajVjNzliZ2h2bm1nZnI3b3MgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/793", "banner": "", - "date": "2023-08-17T14:30:00.000Z" + "date": "2023-08-31T14:30:00.000Z" }, { "title": "Community Meeting", @@ -216,18 +195,18 @@ "banner": "", "date": "2023-07-18T08:00:00.000Z" }, - { - "title": "Spec 3.0 Meeting", - "calLink": "https://www.google.com/calendar/event?eid=aTBkZHJ2YWczcG1hZWFqbTFlMWowZjZnbzAgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/812", - "banner": "", - "date": "2023-08-02T16:00:00.000Z" - }, { "title": "Community Meeting", "calLink": "https://www.google.com/calendar/event?eid=YmlybTZwODdmMzBnNGg0b3J1OWxmdnBxNmMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", "url": "https://github.com/asyncapi/community/issues/818", "banner": "https://user-images.githubusercontent.com/40604284/256949583-958c34c8-4256-4ac5-852b-e00ec094fad0.png", "date": "2023-08-08T16:00:00.000Z" + }, + { + "title": "Spec 3.0 Meeting", + "calLink": "https://www.google.com/calendar/event?eid=NG9lc2RwN3A2djFmNmRxaHZoaWRjMnRhaDAgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/823", + "banner": "", + "date": "2023-08-02T16:00:00.000Z" } ] \ No newline at end of file diff --git a/config/newsroom_videos.json b/config/newsroom_videos.json index 3eda25f1a2dd..8dddcf03788a 100644 --- a/config/newsroom_videos.json +++ b/config/newsroom_videos.json @@ -1,4 +1,16 @@ [ + { + "image_url": "https://i.ytimg.com/vi/1tyyLGAicyE/hqdefault.jpg", + "title": "Community Meeting (August 8th 2023)", + "description": "https://github.com/asyncapi/community/issues/818 Lukasz, Animesh, Maya, and others had a brief conversation where they ...", + "videoId": "1tyyLGAicyE" + }, + { + "image_url": "https://i.ytimg.com/vi/WW5sLVHa0b8/hqdefault.jpg", + "title": "Spec 3.0 (Aug 2th 2023)", + "description": "https://github.com/asyncapi/community/issues/823.", + "videoId": "WW5sLVHa0b8" + }, { "image_url": "https://i.ytimg.com/vi/CagY5otdY14/hqdefault.jpg", "title": "Community Meeting (July 25th 2023)", @@ -16,17 +28,5 @@ "title": "Open Standards and Private Products: A DevRel's Dream or Nightmare", "description": "We are discussing the impact of open standards and working with private products as a DevRel.", "videoId": "WlD5rqmfezw" - }, - { - "image_url": "https://i.ytimg.com/vi/5o5BHJqGxIg/hqdefault.jpg", - "title": "Community Meeting (July 11th 2023)", - "description": "https://github.com/asyncapi/community/issues/784.", - "videoId": "5o5BHJqGxIg" - }, - { - "image_url": "https://i.ytimg.com/vi/Lunp8eSLONc/hqdefault.jpg", - "title": "Spec 3.0 DOCS Meeting (July 6th 2023)", - "description": "https://github.com/asyncapi/community/issues/774.", - "videoId": "Lunp8eSLONc" } ] \ No newline at end of file diff --git a/config/tools-automated.json b/config/tools-automated.json index b499a62b3399..bbd131d44883 100644 --- a/config/tools-automated.json +++ b/config/tools-automated.json @@ -72,41 +72,41 @@ } }, { - "title": "nestjs-asyncapi", - "description": "Utilize decorators to generate AsyncAPI document utilizing DTOs (similar to @nestjs/swagger) and a web UI.", + "title": "SIO-AsyncAPI", + "description": "This is code-first approach to generate AsyncAPI specification from Socket.IO server.", "links": { - "repoUrl": "https://github.com/flamewow/nestjs-asyncapi" + "websiteUrl": "https://github.com/daler-rahimov/sio-asyncapi", + "docsUrl": "https://github.com/daler-rahimov/sio-asyncapi", + "repoUrl": "https://github.com/daler-rahimov/sio-asyncapi" }, "filters": { - "language": "Typescript", + "language": "Python", "technology": [ - "Node.js", - "NestJS" + "Socket.IO", + "Flask" ], "categories": [ - "code-first" + "code-first", + "api" ], "hasCommercial": false, "isAsyncAPIOwner": false } }, { - "title": "SIO-AsyncAPI", - "description": "This is code-first approach to generate AsyncAPI specification from Socket.IO server.", + "title": "nestjs-asyncapi", + "description": "Utilize decorators to generate AsyncAPI document utilizing DTOs (similar to @nestjs/swagger) and a web UI.", "links": { - "websiteUrl": "https://github.com/daler-rahimov/sio-asyncapi", - "docsUrl": "https://github.com/daler-rahimov/sio-asyncapi", - "repoUrl": "https://github.com/daler-rahimov/sio-asyncapi" + "repoUrl": "https://github.com/flamewow/nestjs-asyncapi" }, "filters": { - "language": "Python", + "language": "Typescript", "technology": [ - "Socket.IO", - "Flask" + "Node.js", + "NestJS" ], "categories": [ - "code-first", - "api" + "code-first" ], "hasCommercial": false, "isAsyncAPIOwner": false @@ -495,18 +495,15 @@ "description": "The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others", "toolsList": [ { - "title": "jAsyncAPI - IDEA plugin", - "description": "Idea plugin for the java-asyncapi - Helps to edit and validate AsyncAPI schemas.", + "title": "asyncapi-preview", + "description": "VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n", "links": { - "websiteUrl": "https://plugins.jetbrains.com/plugin/15673-asyncapi", - "docsUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin#usage", - "repoUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin" + "repoUrl": "https://github.com/asyncapi/vs-asyncapi-preview" }, "filters": { - "language": "Kotlin", "technology": [ - "JetBrains", - "IntelliJ IDEA" + "VSCode", + "SmartPaste" ], "categories": [ "ide-extension" @@ -516,15 +513,18 @@ } }, { - "title": "asyncapi-preview", - "description": "VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n", + "title": "jAsyncAPI - IDEA plugin", + "description": "Idea plugin for the java-asyncapi - Helps to edit and validate AsyncAPI schemas.", "links": { - "repoUrl": "https://github.com/asyncapi/vs-asyncapi-preview" + "websiteUrl": "https://plugins.jetbrains.com/plugin/15673-asyncapi", + "docsUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin#usage", + "repoUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin" }, "filters": { + "language": "Kotlin", "technology": [ - "VSCode", - "SmartPaste" + "JetBrains", + "IntelliJ IDEA" ], "categories": [ "ide-extension" diff --git a/cypress/test/Hero.cy.js b/cypress/test/Hero.cy.js index d01ce53a0edd..22b8199b796f 100644 --- a/cypress/test/Hero.cy.js +++ b/cypress/test/Hero.cy.js @@ -5,8 +5,8 @@ describe('Hero Component', () => { it('displays the correct content', () => { mount(); - cy.contains('Building the future of'); - cy.contains('Event-Driven Architectures (EDA)'); + cy.contains('main.header'); + cy.contains('main.subHeader'); cy.contains('Open-Source tools to easily build and maintain your event-driven architecture.'); cy.contains('Read the docs'); cy.contains('Quick search...'); diff --git a/dashboard.json b/dashboard.json index 0f03b47ab6c6..bf420d8ae4d5 100644 --- a/dashboard.json +++ b/dashboard.json @@ -14,27 +14,29 @@ "color": "C2E0C6" } ], - "score": 53.988822684860644 + "score": 26.021935183079695 }, { - "id": "I_kwDOFLhIt84-OUI3", + "id": "PR_kwDOBW5R_c5TUuUu", + "isPR": true, + "isAssigned": false, + "title": "chore(blog): adding 3 New Articles as Blog Posts", + "author": "ivangsa", + "resourcePath": "/asyncapi/website/pull/1805", + "repo": "asyncapi/website", + "labels": [], + "score": 23.548316277439216 + }, + { + "id": "I_kwDOBGu-185CELGB", "isPR": false, "isAssigned": false, - "title": "Create educational & technical video explaining AsyncAPI's main features", - "author": "alequetzalli", - "resourcePath": "/asyncapi/community/issues/155", - "repo": "asyncapi/community", - "labels": [ - { - "name": "enhancement", - "color": "a2eeef" - }, - { - "name": "stale", - "color": "ededed" - } - ], - "score": 32.45072852866624 + "title": "Work on 3.0 release", + "author": "jonaslagoni", + "resourcePath": "/asyncapi/spec/issues/691", + "repo": "asyncapi/spec", + "labels": [], + "score": 22.9739670999407 }, { "id": "MDU6SXNzdWU5OTMxODc5ODM=", @@ -53,47 +55,24 @@ "score": 22.68679251119144 }, { - "id": "I_kwDOBW5R_c5Pi3rO", + "id": "I_kwDOBW5R_c5J6qNe", "isPR": false, "isAssigned": false, - "title": "Epic roadmap to the new AsyncAPI community section", - "author": "AceTheCreator", - "resourcePath": "/asyncapi/website/issues/903", + "title": "Measuring AsyncAPI spec adoption", + "author": "derberg", + "resourcePath": "/asyncapi/website/issues/780", "repo": "asyncapi/website", "labels": [ { - "name": "🎨 design", - "color": "0D67D3" - } - ], - "score": 22.399617922442182 - }, - { - "id": "I_kwDOBGu-184_rP6l", - "isPR": false, - "isAssigned": false, - "title": "Let channels be identified by an ID rather than their address.", - "author": "smoya", - "resourcePath": "/asyncapi/spec/issues/663", - "repo": "asyncapi/spec", - "labels": [ + "name": "enhancement", + "color": "84b6eb" + }, { - "name": "πŸ’­ Strawman (RFC 0)", - "color": "C2E0C6" + "name": "stale", + "color": "ededed" } ], - "score": 21.538094156194408 - }, - { - "id": "PR_kwDOBW5R_c5TUuUu", - "isPR": true, - "isAssigned": false, - "title": "chore(blog): adding 3 New Articles as Blog Posts", - "author": "ivangsa", - "resourcePath": "/asyncapi/website/pull/1805", - "repo": "asyncapi/website", - "labels": [], - "score": 20.67657038994663 + "score": 19.240697446200336 }, { "id": "PR_kwDOBW5R_c5VAjCE", @@ -119,6 +98,17 @@ ], "score": 16.65612614745701 }, + { + "id": "PR_kwDOFLhIt85Vmgtj", + "isPR": true, + "isAssigned": false, + "title": "feat: youtube to anchor workflow", + "author": "AnimeshKumar923", + "resourcePath": "/asyncapi/community/pull/805", + "repo": "asyncapi/community", + "labels": [], + "score": 16.36895155870775 + }, { "id": "PR_kwDOGPFxkc5Ey7vh", "isPR": true, @@ -136,16 +126,52 @@ "score": 15.794602381209232 }, { - "id": "PR_kwDOFLhIt85Vmgtj", - "isPR": true, + "id": "I_kwDOFLhIt84-OUI3", + "isPR": false, "isAssigned": false, - "title": "feat: youtube to anchor workflow", - "author": "AnimeshKumar923", - "resourcePath": "/asyncapi/community/pull/805", + "title": "Create educational & technical video explaining AsyncAPI's main features", + "author": "alequetzalli", + "resourcePath": "/asyncapi/community/issues/155", "repo": "asyncapi/community", + "labels": [ + { + "name": "enhancement", + "color": "a2eeef" + }, + { + "name": "stale", + "color": "ededed" + } + ], + "score": 15.64084401961705 + }, + { + "id": "I_kwDOCVQpZM5M_dcV", + "isPR": false, + "isAssigned": true, + "title": "DocsUI: Messages Object output", + "author": "mcturco", + "resourcePath": "/asyncapi/asyncapi-react/issues/618", + "repo": "asyncapi/asyncapi-react", "labels": [], "score": 14.645904026212197 }, + { + "id": "I_kwDOBW5R_c5BIl5P", + "isPR": false, + "isAssigned": true, + "title": "Add new page for collecting user testing participants", + "author": "mcturco", + "resourcePath": "/asyncapi/website/issues/529", + "repo": "asyncapi/website", + "labels": [ + { + "name": "enhancement", + "color": "84b6eb" + } + ], + "score": 14.645904026212197 + }, { "id": "PR_kwDOFDnrNc5RUbi_", "isPR": true, @@ -156,41 +182,39 @@ "repo": "asyncapi/cli", "labels": [], "score": 14.645904026212197 - }, + } + ], + "goodFirstIssues": [ { - "id": "MDU6SXNzdWUxMjMwODQwMDM4", - "isPR": false, + "id": "I_kwDOBGu-185t3Fe8", + "title": "Add logo of bronze sponsors to readme", "isAssigned": false, - "title": "Usages of allOf within message payload could be flattened", - "author": "jamescrowley", - "resourcePath": "/asyncapi/asyncapi-react/issues/596", - "repo": "asyncapi/asyncapi-react", + "resourcePath": "/asyncapi/spec/issues/961", + "repo": "asyncapi/spec", + "author": "derberg", + "area": "Unknown", "labels": [ { - "name": "stale", - "color": "ededed" + "name": "πŸ“‘ docs", + "color": "E50E99" } - ], - "score": 14.07155484871368 + ] }, { - "id": "PR_kwDOFLhIt85TFWOL", - "isPR": true, + "id": "I_kwDOFDnrNc5tcrDS", + "title": "Add a new flag to set context when it is created ", "isAssigned": false, - "title": "ci: verify changes to Maintainers.yaml made by the bot", - "author": "14Richa", - "resourcePath": "/asyncapi/community/pull/750", - "repo": "asyncapi/community", + "resourcePath": "/asyncapi/cli/issues/726", + "repo": "asyncapi/cli", + "author": "Souvikns", + "area": "Unknown", "labels": [ { - "name": "do-not-merge", - "color": "B60205" + "name": "enhancement", + "color": "a2eeef" } - ], - "score": 13.497205671215161 - } - ], - "goodFirstIssues": [ + ] + }, { "id": "I_kwDOBW5R_c5sqLtN", "title": "[πŸ“‘ Docs]: import Glee docs under tools folder", @@ -255,21 +279,6 @@ } ] }, - { - "id": "I_kwDOFi_gUM5rHSAR", - "title": "Show server url", - "isAssigned": false, - "resourcePath": "/asyncapi/glee/issues/475", - "repo": "asyncapi/glee", - "author": "KhudaDad414", - "area": "typescript", - "labels": [ - { - "name": "enhancement", - "color": "a2eeef" - } - ] - }, { "id": "I_kwDOBGu-185qGt6A", "title": "Ensure consistency when using either `Application` or `API` terms", @@ -569,25 +578,6 @@ } ] }, - { - "id": "I_kwDOE8Qh385m6JkV", - "title": "Add runtime testing for C++", - "isAssigned": false, - "resourcePath": "/asyncapi/modelina/issues/1335", - "repo": "asyncapi/modelina", - "author": "jonaslagoni", - "area": "Unknown", - "labels": [ - { - "name": "enhancement", - "color": "a2eeef" - }, - { - "name": "C++ generator", - "color": "1573BB" - } - ] - }, { "id": "I_kwDOE8Qh385m6IlQ", "title": "Add runtime testing for Kotlin", @@ -754,21 +744,6 @@ } ] }, - { - "id": "I_kwDOFi_gUM5hAZlI", - "title": "Better logging for MQTT adapter", - "isAssigned": false, - "resourcePath": "/asyncapi/glee/issues/406", - "repo": "asyncapi/glee", - "author": "KhudaDad414", - "area": "typescript", - "labels": [ - { - "name": "enhancement", - "color": "a2eeef" - } - ] - }, { "id": "I_kwDOFi_gUM5gx6CN", "title": "error when running `npm install` in glee", @@ -956,6 +931,10 @@ "author": "jonaslagoni", "area": "docs", "labels": [ + { + "name": "stale", + "color": "819cd3" + }, { "name": "Hacktoberfest", "color": "FF8AE2" @@ -1066,6 +1045,10 @@ "name": "enhancement", "color": "a2eeef" }, + { + "name": "stale", + "color": "ededed" + }, { "name": "Hacktoberfest", "color": "FF8AE2" diff --git a/lib/browserLanguageDetector.js b/lib/browserLanguageDetector.js new file mode 100644 index 000000000000..d781f80d16ab --- /dev/null +++ b/lib/browserLanguageDetector.js @@ -0,0 +1,36 @@ +const { i18n } = require("./../next-i18next-static-site.config"); + +// Converts languages like 'en-US' to 'en' +const convertLanguageCode = (code) => { + const baseLanguageCode = code.split('-')[0]; + return baseLanguageCode; +}; + +function browserLanguageDetector() { + + // Fetch the language stored inside localStorage + const localStorageLanguage = localStorage.getItem('i18nLang'); + + if (localStorageLanguage) { + return localStorageLanguage; + } + + // Load available languages from i18n object + const availableLanguages = i18n.languages; + + // Load user's default languages from browser settings + const browserDefaultLanguages = navigator.languages; + + const convertedLanguages = browserDefaultLanguages.map((code) => convertLanguageCode(code)); + + // Check if the top priority language is available inside i18n object + for (var i = 0; i < convertedLanguages.length; i++) { + if (availableLanguages.includes(convertedLanguages[i])) { + return convertedLanguages[i]; + } + } + // Default to 'en' in all other cases + return 'en'; +} + +export default browserLanguageDetector; \ No newline at end of file diff --git a/lib/i18n.js b/lib/i18n.js new file mode 100644 index 000000000000..b0ed43514a45 --- /dev/null +++ b/lib/i18n.js @@ -0,0 +1,223 @@ +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import Cookies from "js-cookie"; +import i18next from "i18next"; +import { + initReactI18next, + useTranslation, + withTranslation, + Translation, + Trans +} from "react-i18next"; +import nextI18nextStaticSiteConfig from "../next-i18next-static-site.config"; +var defaultConfig = { + allowHydration: true, + languages: ["en"], + defaultLanguage: "en", + namespaces: ["common"], + defaultNamespace: "common", + cookieName: "lang", + cookieOptions: { expires: 365, path: "/" } +}; +var config = { + ...defaultConfig, + languages: nextI18nextStaticSiteConfig.i18n.languages, + defaultLanguage: nextI18nextStaticSiteConfig.i18n.defaultLanguage, + namespaces: nextI18nextStaticSiteConfig.i18n.namespaces, + defaultNamespace: nextI18nextStaticSiteConfig.i18n.defaultNamespace +}; + +/** + * An array containing the supported language codes. + * @type {string[]} + */ +var languages = config.languages; +/** + * The default language code used for translation when no language is specified or available. + * @type {string} + */ +var defaultLanguage = config.defaultLanguage; +/** + * An array containing the supported namespaces for translation. + * @type {string[]} + */ +var namespaces = config.namespaces; +/** + * The default namespace used for translation when no namespace is specified or available. + * @type {string} + */ +var defaultNamespace = config.defaultNamespace; +/** + * A duplicate of the default namespace used for translation when no namespace is specified or available. + * @type {string} + */ +var defaultNamespace2 = config.defaultNamespace; +/** + * The name of the cookie used to store the user's preferred language. + * @type {string} + */ +var cookieName = config.cookieName; + +/** + * Creates an i18next instance with the provided locales and language. + * @param {Object} locales - The locales object containing translations for different languages and namespaces. + * @param {string} language - The language code representing the desired language. + * @returns {Object} - The initialized i18next instance. + */ +var createI18nextInstance = (locales, language) => { + const plugins = [ + initReactI18next + ]; + const i18nInstance = i18next; + plugins.map((plugin) => i18nInstance.use(plugin)); + i18nInstance.init({ + resources: locales, + cleanCode: true, + lng: language, + supportedLngs: config.languages, + fallbackLng: language ? language : config.defaultLanguage, + ns: config.namespaces, + defaultNS: config.defaultNamespace, + interpolation: { + escapeValue: false + }, + react: { + useSuspense: false + }, + load: "languageOnly" + }); + return i18nInstance; +}; + +/** + * A global i18next instance used for translation. + * @type {?Object} + */ +var globalI18nextInstance = null; + + +/** + * Returns a singleton instance of the i18next object with the specified language and locales. + * If the instance doesn't exist, it creates a new one; otherwise, it changes the language of the existing instance. + * @param {string} language - The language code representing the desired language. + * @param {Object} locales - The locales object containing translations for different languages and namespaces. + * @returns {Object} - The i18next instance. + */ +var i18nextInstance = (language, locales) => { + if (!globalI18nextInstance) { + globalI18nextInstance = createI18nextInstance(locales, language); + return globalI18nextInstance; + } else { + globalI18nextInstance.changeLanguage(language); + return globalI18nextInstance; + } +}; + +/** + * A flag indicating whether the locales have been loaded. + * @type {boolean} + */ +var loaded = false; + + +/** + * A React component that provides i18n functionality to the child components. + * @param {Object} props - The props object containing the i18n options and child components. + * @returns {JSX.Element|null} - The child components wrapped in the i18n provider, or null if hydration is not allowed. + */ +var I18nProvider = (props) => { + var _a; + const [hydration, setHydration] = useState(false); + const options = { ...config, ...props.i18n }; + if (!((_a = props.i18n) == null ? void 0 : _a.locales)) { + throw new Error("locales object was not passed into I18nProvider"); + } + const router = useRouter(); + const { asPath, query } = router; + const slug = asPath.split("/")[1]; + const langSlug = config.languages.includes(slug) && slug; + const language = (query.lang || langSlug || config.defaultLanguage).toString(); + const pathLocale = (query.lang || langSlug).toString(); + if (pathLocale && pathLocale !== "false") { + Cookies.set(config.cookieName, pathLocale, config.cookieOptions); + } + if (!loaded) { + i18nextInstance(language, props.i18n.locales); + } + const { i18n: i18n2 } = useTranslation(); + useEffect(() => { + i18n2.services.resourceStore.data = props.i18n.locales; + i18n2.changeLanguage(language); + }, [i18n2, language, props.i18n.locales]); + useEffect(() => { + loaded = true; + i18n2.changeLanguage(language); + }, [i18n2, language]); + useEffect(() => { + const hasWindow = typeof window !== "undefined"; + if (hasWindow && options.allowHydration) { + setHydration(true); + } + }, [options.allowHydration]); + return hydration ? props.children : null; +}; + +/** + * Retrieves all language slugs for use in Next.js dynamic routing. + * @returns {Object[]} - An array of objects, each containing the "params" property with the "lang" parameter for each language. + */ +function getAllLanguageSlugs() { + return config.languages.map((lang) => { + return { params: { lang } }; + }); +} + +/** + * Retrieves the valid language code based on the provided language. + * If the provided language is not valid, returns the default language. + * @param {string} lang - The language code to check for validity. + * @returns {string} - The valid language code. + */ +function getLanguage(lang) { + return config.languages.includes(lang) ? lang : config.defaultLanguage; +} + +/** + * Detects the user's preferred language based on cookies and browser settings. + * If a preferred language is found, redirects the user to the corresponding language page. + */ +var languageDetection = () => { + const router = useRouter(); + useEffect(() => { + let cookieLocale = Cookies.get(cookieName) || void 0; + let browserLocale = (navigator.languages && navigator.languages.length ? navigator.languages[0] : navigator.language) || void 0; + if (browserLocale) { + browserLocale = browserLocale.slice(0, 2); + } + if (cookieLocale && languages.includes(cookieLocale)) { + router.push("/" + cookieLocale); + } else if (browserLocale && languages.includes(browserLocale)) { + router.push("/" + browserLocale); + } else { + router.push("/" + defaultLanguage); + } + }, [router, defaultLanguage]); + return null; +}; +export { + I18nProvider, + Trans, + Translation, + cookieName, + defaultLanguage, + defaultNamespace, + defaultNamespace2, + getAllLanguageSlugs, + getLanguage, + i18nextInstance, + languageDetection, + languages, + namespaces, + useTranslation, + withTranslation +}; diff --git a/lib/locales.js b/lib/locales.js index fe5067a76758..28320438d605 100644 --- a/lib/locales.js +++ b/lib/locales.js @@ -1,4 +1,4 @@ -import { languages, namespaces } from "next-i18next-static-site"; +import { languages, namespaces } from "../lib/i18n"; function loadLocales() { // Load all locales, required for next-i18n-static-site diff --git a/netlify.toml b/netlify.toml index ebcbcd3b2128..3f3d2beb5351 100644 --- a/netlify.toml +++ b/netlify.toml @@ -23,7 +23,6 @@ [[edge_functions]] function = "serve-definitions" path = "/definitions/*" -cache = "manual" # Used by JSON Schema definitions fetched from schemastore.org [[redirects]] @@ -34,7 +33,6 @@ cache = "manual" [[edge_functions]] function = "serve-definitions" path = "/schema-store/*" -cache = "manual" [[plugins]] package = "@netlify/plugin-nextjs" diff --git a/netlify/edge-functions/serve-definitions.ts b/netlify/edge-functions/serve-definitions.ts index e50747be6437..3197f584478c 100644 --- a/netlify/edge-functions/serve-definitions.ts +++ b/netlify/edge-functions/serve-definitions.ts @@ -19,7 +19,6 @@ const legitimateRequestRegex = /^\/[\w\-]*\/?(?:([\w\-\.]*\/)?([\w\-$%\.]*\.json export default async (request: Request, context: Context) => { let rewriteRequest = buildRewrite(request); - let response: Response; if (rewriteRequest === null) { rewriteRequest = request; @@ -33,6 +32,12 @@ export default async (request: Request, context: Context) => { const isRequestingAFile = request.url.endsWith('.json'); if (isRequestingAFile) { var metricName: string + const metricAttributes = { + 'responseStatus': response.status, + 'responseStatusText': response.statusText, + 'cached': false, + }; + if (response.ok) { // Manually cloning the response so we can modify the headers as they are immutable response = new Response(response.body, response); @@ -43,15 +48,18 @@ export default async (request: Request, context: Context) => { metricName = "asyncapi.jsonschema.download.success"; } else { - // Notifying NR of the error. - metricName = "asyncapi.jsonschema.download.error"; + switch (response.status) { + case 304: + metricName = "asyncapi.jsonschema.download.success"; + metricAttributes["cached"] = true; + break; + default: + // Notifying NR of the error. + metricName = "asyncapi.jsonschema.download.error"; + break; + } } - const metricAttributes = { - "responseStatus": response.status, - "responseStatusText": response.statusText, - }; - // Sending metrics to NR. await sendMetricToNR(context, newNRMetricCount(metricName, request, rewriteRequest, metricAttributes)); } @@ -76,12 +84,11 @@ function buildRewrite(originalRequest: Request): (Request | null) { url = URL_DEST_DEFINITIONS + `/${definitionVersion}${file}`; } + originalRequest.headers.set('Authorization', 'token ' + GITHUB_TOKEN); + return new Request(url, { method: originalRequest.method, - headers: new Headers({ - // Setting GH Token to increase GH rate limit to 5,000 req/h. - 'Authorization': "token " + GITHUB_TOKEN, - }), + headers: originalRequest.headers, }); } diff --git a/next.config.js b/next.config.js index 3795898a6772..ee1363b14a70 100644 --- a/next.config.js +++ b/next.config.js @@ -4,7 +4,6 @@ const gemoji = require('remark-gemoji-to-emoji'); const a11yEmoji = require('@fec/remark-a11y-emoji'); const slug = require('remark-slug'); const headingId = require('remark-heading-id'); -const { i18n } = require("./next-i18next-static-site.config"); const withMDX = require('@next/mdx')({ extension: /\.mdx?$/, @@ -21,9 +20,7 @@ const withMDX = require('@next/mdx')({ }, }); -const withTM = require("next-transpile-modules")(["next-i18next-static-site"]); - -module.exports = withTM(withMDX({ +module.exports = withMDX({ pageExtensions: ['js', 'md'], eslint: { ignoreDuringBuilds: true, @@ -39,7 +36,4 @@ module.exports = withTM(withMDX({ return config; }, - publicRuntimeConfig: { - i18n, - }, -})); +}); diff --git a/package-lock.json b/package-lock.json index 7a9f82c3214b..c68c92943e47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,23 +35,23 @@ "fuse.js": "^6.6.2", "googleapis": "^100.0.0", "gray-matter": "^4.0.2", + "i18next": "^21.10.0", "jgexml": "^0.4.4", + "js-cookie": "^3.0.1", "lodash": "^4.17.21", "markdown-to-txt": "^2.0.1", "markdown-toc": "1.2.0", "mermaid": "9.3.0", "moment": "^2.29.4", "next": "^12.0.0", - "next-i18next-static-site": "^0.3.1", "next-mdx-remote": "^4.4.1", - "next-transpile-modules": "^10.0.0", "node-fetch": "^2.6.7", "postcss": "^8.4.14", "react": "^17.0.2", "react-dom": "^17.0.2", "react-ga": "^3.1.2", "react-gtm-module": "^2.0.11", - "react-i18next": "^13.0.1", + "react-i18next": "^11.18.6", "react-scrollspy": "^3.4.2", "react-syntax-highlighter": "12.2.1", "react-text-truncate": "^0.16.0", @@ -4855,18 +4855,6 @@ "once": "^1.4.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -6003,7 +5991,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/gray-matter": { "version": "4.0.3", @@ -6482,7 +6471,6 @@ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" } ], - "peer": true, "dependencies": { "@babel/runtime": "^7.17.2" } @@ -7245,11 +7233,11 @@ "integrity": "sha512-j0AzSWT7LXy3s3i1cdv5NZxUtscocwiBxgOLiEBfitCehm8STdXVrcOlbAWsJFLCq1elZYpQlGqA9k8Z+n9iJA==" }, "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", "engines": { - "node": ">=14" + "node": ">=12" } }, "node_modules/js-tokens": { @@ -9105,21 +9093,6 @@ } } }, - "node_modules/next-i18next-static-site": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/next-i18next-static-site/-/next-i18next-static-site-0.3.1.tgz", - "integrity": "sha512-rl5kdst++xucZz6kVOQfXNc/ZGYJyjq8sfSkFxthV3qnnP17bWq6C8uLyDOHMV98DbujG28To7MW5yH+//Od+g==", - "dependencies": { - "js-cookie": "^3.0.1" - }, - "peerDependencies": { - "i18next": "^21.10.0", - "js-cookie": "^3.0.1", - "next": "^13.0.0", - "react": "^18.2.0", - "react-i18next": "^11.18.6" - } - }, "node_modules/next-mdx-remote": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", @@ -9155,14 +9128,6 @@ "react": ">=16" } }, - "node_modules/next-transpile-modules": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-10.0.0.tgz", - "integrity": "sha512-FyeJ++Lm2Fq31gbThiRCrJlYpIY9QaI7A3TjuhQLzOix8ChQrvn5ny4MhfIthS5cy6+uK1AhDRvxVdW17y3Xdw==", - "dependencies": { - "enhanced-resolve": "^5.10.0" - } - }, "node_modules/node-abi": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz", @@ -10794,15 +10759,15 @@ "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, "node_modules/react-i18next": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.0.1.tgz", - "integrity": "sha512-gMO6N2GfSfuH7xlHSsZ/mZf+Py9bLm/+EDKIn5fNTuDTjcCcwmMU5UEuGCDk5mdfivbo7ySyYXBN7B9tbGUxiA==", + "version": "11.18.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", + "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", "dependencies": { - "@babel/runtime": "^7.22.5", + "@babel/runtime": "^7.14.5", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { - "i18next": ">= 23.2.3", + "i18next": ">= 19.0.0", "react": ">= 16.8.0" }, "peerDependenciesMeta": { @@ -12146,14 +12111,6 @@ "node": ">= 6" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -16782,15 +16739,6 @@ "once": "^1.4.0" } }, - "enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -17794,7 +17742,8 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "gray-matter": { "version": "4.0.3", @@ -18162,7 +18111,6 @@ "version": "21.10.0", "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", - "peer": true, "requires": { "@babel/runtime": "^7.17.2" } @@ -18812,9 +18760,9 @@ "integrity": "sha512-j0AzSWT7LXy3s3i1cdv5NZxUtscocwiBxgOLiEBfitCehm8STdXVrcOlbAWsJFLCq1elZYpQlGqA9k8Z+n9iJA==" }, "js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" }, "js-tokens": { "version": "4.0.0", @@ -20201,14 +20149,6 @@ "use-sync-external-store": "1.2.0" } }, - "next-i18next-static-site": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/next-i18next-static-site/-/next-i18next-static-site-0.3.1.tgz", - "integrity": "sha512-rl5kdst++xucZz6kVOQfXNc/ZGYJyjq8sfSkFxthV3qnnP17bWq6C8uLyDOHMV98DbujG28To7MW5yH+//Od+g==", - "requires": { - "js-cookie": "^3.0.1" - } - }, "next-mdx-remote": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", @@ -20231,14 +20171,6 @@ } } }, - "next-transpile-modules": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-10.0.0.tgz", - "integrity": "sha512-FyeJ++Lm2Fq31gbThiRCrJlYpIY9QaI7A3TjuhQLzOix8ChQrvn5ny4MhfIthS5cy6+uK1AhDRvxVdW17y3Xdw==", - "requires": { - "enhanced-resolve": "^5.10.0" - } - }, "node-abi": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz", @@ -21499,11 +21431,11 @@ "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, "react-i18next": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.0.1.tgz", - "integrity": "sha512-gMO6N2GfSfuH7xlHSsZ/mZf+Py9bLm/+EDKIn5fNTuDTjcCcwmMU5UEuGCDk5mdfivbo7ySyYXBN7B9tbGUxiA==", + "version": "11.18.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", + "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", "requires": { - "@babel/runtime": "^7.22.5", + "@babel/runtime": "^7.14.5", "html-parse-stringify": "^3.0.1" } }, @@ -22598,11 +22530,6 @@ } } }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" - }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", diff --git a/package.json b/package.json index ddc7761fc156..8f4c9a8dd8e1 100644 --- a/package.json +++ b/package.json @@ -63,23 +63,23 @@ "fuse.js": "^6.6.2", "googleapis": "^100.0.0", "gray-matter": "^4.0.2", + "i18next": "^21.10.0", "jgexml": "^0.4.4", + "js-cookie": "^3.0.1", "lodash": "^4.17.21", "markdown-to-txt": "^2.0.1", "markdown-toc": "1.2.0", "mermaid": "9.3.0", "moment": "^2.29.4", "next": "^12.0.0", - "next-i18next-static-site": "^0.3.1", "next-mdx-remote": "^4.4.1", - "next-transpile-modules": "^10.0.0", "node-fetch": "^2.6.7", "postcss": "^8.4.14", "react": "^17.0.2", "react-dom": "^17.0.2", "react-ga": "^3.1.2", "react-gtm-module": "^2.0.11", - "react-i18next": "^13.0.1", + "react-i18next": "^11.18.6", "react-scrollspy": "^3.4.2", "react-syntax-highlighter": "12.2.1", "react-text-truncate": "^0.16.0", diff --git a/pages/[lang]/index.js b/pages/[lang]/index.js index 36bf2189bda1..0956ecb7dd39 100644 --- a/pages/[lang]/index.js +++ b/pages/[lang]/index.js @@ -28,7 +28,7 @@ import NewsroomSection from '../../components/newsroom/NewsroomSection'; import { getAllLanguageSlugs, getLanguage, -} from "next-i18next-static-site"; +} from "../../lib/i18n"; function HomePage() { return ( diff --git a/pages/_app.js b/pages/_app.js index 3f61b533ff40..4dadaefe3114 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -12,7 +12,7 @@ import { defaultLanguage, namespaces, defaultNamespace, -} from "next-i18next-static-site"; +} from "../lib/i18n"; import loadLocales from "../lib/locales"; import '../styles/globals.css' diff --git a/pages/blog/july-2023.md b/pages/blog/july-2023.md new file mode 100644 index 000000000000..061d6d4c1b25 --- /dev/null +++ b/pages/blog/july-2023.md @@ -0,0 +1,57 @@ +--- +title: "Community Update: July 2023" +date: 2023-08-05T06:00:00+01:00 +type: Communication +tags: + - Project Status +cover: /img/posts/2023-summary/blog-banner-july.webp +authors: + - name: Thulisile Sibanda + photo: /img/avatars/thulieblack.webp + link: https://www.linkedin.com/in/v-thulisile-sibanda/ + byline: AsyncAPI Community Manager +excerpt: 'July Community Update' +featured: true +--- + +Earlier this month, we officially kickstarted the AsyncAPI Mentorship Program. After receiving an overwhelming response of over 90+ applications for the program, we inducted [13 mentees into the AsyncAPI mentorship program](https://github.com/asyncapi/community/tree/master/mentorship/asyncapi-mentorship/2023). We are thrilled to welcome these talented individuals and look forward to seeing them grow and excel in their respective projects. Additionally, we are excited that our [budget of $19,500 for the AsyncAPI Mentorship Program got approved](), which means we can compensate all successful mentees of the program. We are grateful for the support and look forward to a successful program. + + +## AsyncAPI Conf on Tour 2023 (AACoT) + +Tickets for AACoT'23 London event are available for purchase now, and we have some fantastic talks lined up for September 20th that you won't want to miss. [Hurry and get your tickets through Open Collective](https://opencollective.com/asyncapi/events/asyncapi-conference-on-tour-6b3c0aa1/contribute/asyncapi-conference-on-tour-london-61313) because we have limited availability. + +We are also in the process of reviewing talk proposals and will announce our selected speakers soon. + +Be sure to keep an eye out for our August newsletter, as we will be sharing some exciting news there and maybe revealing the next location. + +## Spec x Tooling +The work on the pre-release version of AsyncAPI Studio is now in progress. The implementation will include the support of validating AsyncAPI v3 documents. If you want to follow the development process or contribute, please [check out the ShapeUP dashboard](https://shapeit.app/projects/org/asyncapi/22/cycles/fa1e9a31?issue=I_kwDODou01c5r29cR). + +On the other hand, we have released the initial versions of three protocol bindings. Our gratitude goes out to: +- [Adam Retter](https://github.com/adamretter) for contributing to the [JMS binding](https://github.com/asyncapi/bindings/tree/master/jms), [Richard Coppen](https://github.com/rcoppen), and [Steve Head](https://github.com/SrfHead) for agreeing to maintain it long-term. +- [Ian Cooper](https://github.com/iancooper) and [Dec Kolawski](https://github.com/dpwdec) for contributing and being maintainers to the [SNS binding](https://github.com/asyncapi/bindings/tree/master/sns) and [SQS binding](https://github.com/asyncapi/bindings/tree/master/sqs). + +Thanks to the involvement of various community members in reviewing the changes. + +## Design +Our design contributor community is experiencing significant growth, and we are thrilled to see our onboarding process going smoothly. More talented individuals joining the community will bring fresh ideas and different perspectives and further foster collaboration and creativity in the initiative. Additionally, [Maya](https://github.com/Mayaleeeee) is currently [leading a design for our website](https://www.figma.com/file/NC2FUyFAccF08uP5RbsbAB/AsyncAPI-Design-Audit?type=design&node-id=1113%3A4309&mode=design&t=iKAh2NOduAjQpsty-1), and we're eager to see all the great insights she'll bring to enhance our website even better. + +## Ambassador Program +Do you have a passion for event-driven architectures or message-driven APIs? Would you like to contribute to the AsyncAPI community? You can become an AsyncAPI Ambassador by making at least 4 contributions, either by giving talks, writing articles, or promoting AsyncAPI. If you're interested, [learn more about becoming an AsyncAPI Ambassador today](https://www.asyncapi.com/community/ambassadors)! + +## TSC members + +The [AsyncAPI Technical Steering Committee](https://www.asyncapi.com/community/tsc) is expanding rapidly, and we would like to warmly welcome our two latest members, [Thulisile Sibanda](https://www.linkedin.com/in/v-thulisile-sibanda), and [Aishat Muibudeen](https://www.linkedin.com/in/aishatmuibudeen). We are excited to have you on board. + +## In Case You Missed It + +Did you miss our community session on Open Standards and Private Products? You can catch up by watching the recording. + + + +## Coming in August + +- **AsyncAPI Community Updates Newsletter** - Stay updated on the latest community activities by [subscribing to the AsyncAPI Newsletter](https://www.asyncapi.com/newsletter). + + diff --git a/pages/blog/june-2023.md b/pages/blog/june-2023.md index b7556e1ca90a..c7358b9a775f 100644 --- a/pages/blog/june-2023.md +++ b/pages/blog/june-2023.md @@ -11,7 +11,6 @@ authors: link: https://www.linkedin.com/in/v-thulisile-sibanda/ byline: AsyncAPI Community Manager excerpt: 'June Community Update' -featured: true --- Over the last few months, we have seen a significant surge in people interested in using AsyncAPI to document and define event-driven architectures. We've received feedback on how it has been challenging to reuse objects effectively, like servers, messages, channels, and even author AsyncAPI documents. If you are one of those individuals, we have excellent news; [Fran MΓ©ndez](https://www.linkedin.com/in/fmvilas), [Samir Amzani](https://www.linkedin.com/in/amzani/), and the team have been working on redesigning the AsyncAPI Studio. diff --git a/pages/casestudies/index.js b/pages/casestudies/index.js index 567a154e3ff3..089ccdad575d 100644 --- a/pages/casestudies/index.js +++ b/pages/casestudies/index.js @@ -4,8 +4,6 @@ import Paragraph from '../../components/typography/Paragraph'; import TextLink from '../../components/typography/TextLink'; import Heading from "../../components/typography/Heading"; import CaseStudiesList from "../../config/case-studies.json"; -import { -} from "next-i18next-static-site"; export default function casestudies() { const description = diff --git a/pages/docs/reference/specification/v2.6.0.md b/pages/docs/reference/specification/v2.6.0.md index fb3651e6fd2e..ac73a7092092 100644 --- a/pages/docs/reference/specification/v2.6.0.md +++ b/pages/docs/reference/specification/v2.6.0.md @@ -1,10 +1,10 @@ # AsyncAPI Specification -#### Disclaimer +## Disclaimer Part of this content has been taken from the great work done by the folks at the [OpenAPI Initiative](https://openapis.org). Mainly because **it's a great work** and we want to keep as much compatibility as possible with the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification). -#### Version 2.6.0 +## Version 2.6.0 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). @@ -33,29 +33,37 @@ It means that the [application](#definitionsApplication) allows [consumers](#def ## Definitions -#### Server +### Server + A server MAY be a message broker that is capable of sending and/or receiving between a [producer](#definitionsProducer) and [consumer](#definitionsConsumer). A server MAY be a service with WebSocket API that enables message-driven communication between browser-to-server or server-to-server. -#### Application -An application is any kind of computer program or a group of them. It MUST be a [producer](#definitionsProducer), a [consumer](#definitionsConsumer) or both. An application MAY be a microservice, IoT device (sensor), mainframe process, etc. An application MAY be written in any number of different programming languages as long as they support the selected [protocol](#definitionsProtocol). An application MUST also use a protocol supported by the [server](#definitionsServer) in order to connect and exchange [messages](#definitionsMessage). +### Application + +An application is any kind of computer program or a group of them. It MUST be a [producer](#definitionsProducer), a [consumer](#definitionsConsumer) or both. An application MAY be a microservice, IoT device (sensor), mainframe process, etc. An application MAY be written in any number of different programming languages as long as they support the selected [protocol](#definitionsProtocol). An application MUST also use a protocol supported by the [server](#definitionsServer) in order to connect and exchange [messages](#definitionsMessage). + +### Producer -#### Producer A producer is a type of application, connected to a [server](#definitionsServer), that is creating [messages](#definitionsMessage) and addressing them to [channels](#definitionsChannel). A producer MAY be publishing to multiple channels depending on the [server](#definitionsServer), protocol, and use-case pattern. -#### Consumer +### Consumer + A consumer is a type of application, connected to a [server](#definitionsServer) via a supported [protocol](#definitionsProtocol), that is consuming [messages](#definitionsMessage) from [channels](#definitionsChannel). A consumer MAY be consuming from multiple channels depending on the [server](#definitionsServer), protocol, and the use-case pattern. -#### Message -A message is the mechanism by which information is exchanged via a channel between [servers](#definitionsServer) and applications. A message MUST contain a payload and MAY also contain headers. The headers MAY be subdivided into [protocol](#definitionsProtocol)-defined headers and header properties defined by the application which can act as supporting metadata. The payload contains the data, defined by the application, which MUST be serialized into a format (JSON, XML, Avro, binary, etc.). Since a message is a generic mechanism, it can support multiple interaction patterns such as event, command, request, or response. +### Message + +A message is the mechanism by which information is exchanged via a channel between [servers](#definitionsServer) and applications. A message MUST contain a payload and MAY also contain headers. The headers MAY be subdivided into [protocol](#definitionsProtocol)-defined headers and header properties defined by the application which can act as supporting metadata. The payload contains the data, defined by the application, which MUST be serialized into a format (JSON, XML, Avro, binary, etc.). Since a message is a generic mechanism, it can support multiple interaction patterns such as event, command, request, or response. + +### Channel -#### Channel A channel is an addressable component, made available by the [server](#definitionsServer), for the organization of [messages](#definitionsMessage). [Producer](#definitionsProducer) applications send messages to channels and [consumer](#definitionsConsumer) applications consume messages from channels. [Servers](#definitionsServer) MAY support many channel instances, allowing messages with different content to be addressed to different channels. Depending on the [server](#definitionsServer) implementation, the channel MAY be included in the message via protocol-defined headers. -#### Protocol +### Protocol + A protocol is the mechanism (wireline protocol or API) by which [messages](#definitionsMessage) are exchanged between the application and the [channel](#definitionsChannel). Example protocols include, but are not limited to, AMQP, HTTP, JMS, Kafka, Anypoint MQ, MQTT, Solace, STOMP, Mercure, WebSocket, Google Pub/Sub, Pulsar. -#### Bindings -A "binding" (or "protocol binding") is a mechanism to define protocol-specific information. Therefore, a protocol binding MUST define protocol-specific information only. +### Bindings + +A "binding" (or "protocol binding") is a mechanism to define protocol-specific information. Therefore, a protocol binding MUST define protocol-specific information only. ## Specification @@ -117,7 +125,6 @@ Field Name | Type | Description tags | [Tags Object](#tagsObject) | A list of tags used by the specification with additional metadata. Each tag name in the list MUST be unique. externalDocs | [External Documentation Object](#externalDocumentationObject) | Additional external documentation. - This object MAY be extended with [Specification Extensions](#specificationExtensions). #### AsyncAPI Version String @@ -136,7 +143,7 @@ This field represents a unique universal identifier of the [application](#defini It is RECOMMENDED to use a [URN](https://tools.ietf.org/html/rfc8141) to globally and uniquely identify the application during long periods of time, even after it becomes unavailable or ceases to exist. -###### Examples +##### Examples ```json { @@ -176,7 +183,7 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). -##### Info Object Example: +##### Info Object Example ```json { @@ -224,7 +231,7 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). -##### Contact Object Example: +##### Contact Object Example ```json { @@ -253,7 +260,7 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). -##### License Object Example: +##### License Object Example ```json { @@ -298,7 +305,6 @@ production: protocolVersion: '1.0.0' ``` - #### Server Object An object representing a message broker, a server or any other kind of computer program capable of sending and/or receiving data. This object is used to capture details such as URIs, protocols and security configuration. Variable substitution can be used so that some details, for example usernames and passwords, can be injected by code generation tools. @@ -462,7 +468,6 @@ servers: default: v2 ``` - #### Server Variable Object An object representing a Server Variable for server URL template substitution. @@ -478,10 +483,6 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). - - - - #### Default Content Type A string representing the default content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). This value MUST be used by schema parsers when the [contentType](#messageObjectContentType) property is omitted. @@ -500,11 +501,6 @@ In case a message can't be encoded/decoded using this value, schema parsers MUST defaultContentType: application/json ``` - - - - - #### Channels Object Holds the relative paths to the individual channel and their operations. Channel paths are relative to servers. @@ -538,9 +534,6 @@ user/signedup: $ref: "#/components/messages/userSignedUp" ``` - - - #### Channel Item Object Describes the operations available on a single channel. @@ -549,7 +542,7 @@ Describes the operations available on a single channel. Field Name | Type | Description ---|:---:|--- -$ref | `string` | Allows for a referenced definition of this channel item. The referenced structure MUST be in the form of a [Channel Item Object](#channelItemObject). In case a Channel Item Object field appears both in the defined object and the referenced object, the behavior is *undefined*. Resolution is done as defined by the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03).

**Deprecated:** Usage of the `$ref` property has been deprecated. +$ref | `string` | Allows for a referenced definition of this channel item. The referenced structure MUST be in the form of a [Channel Item Object](#channelItemObject). In case a Channel Item Object field appears both in the defined object and the referenced object, the behavior is _undefined_. Resolution is done as defined by the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03).

**Deprecated:** Usage of the `$ref` property has been deprecated. description | `string` | An optional description of this channel item. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. servers | [`string`] | The servers on which this channel is available, specified as an optional unordered list of names (string keys) of [Server Objects](#serverObject) defined in the [Servers Object](#serversObject) (a map). If `servers` is absent or empty then this channel must be available on all servers defined in the [Servers Object](#serversObject). subscribe | [Operation Object](#operationObject) | A definition of the SUBSCRIBE operation, which defines the messages produced by the application and sent to the channel. @@ -635,7 +628,6 @@ subscribe: - $ref: '#/components/messages/login' ``` - Using explicit by-name references to the servers on which the channel is available: ```json @@ -671,10 +663,6 @@ bindings: is: queue ``` - - - - #### Operation Object Describes a publish or a subscribe operation. This provides a place to document how and why messages are sent and received. @@ -783,9 +771,6 @@ traits: - $ref: "#/components/operationTraits/kafka" ``` - - - #### Operation Trait Object Describes a trait that MAY be applied to an [Operation Object](#operationObject). This object MAY contain any property from the [Operation Object](#operationObject), except `message` and `traits`. @@ -824,9 +809,6 @@ bindings: ack: false ``` - - - #### Parameters Object Describes a map of parameters included in a channel name. @@ -873,10 +855,6 @@ user/{userId}/signup: $ref: "#/components/messages/userSignedUp" ``` - - - - #### Parameter Object Describes a parameter included in a channel name. @@ -927,9 +905,6 @@ user/{userId}/signup: $ref: "#/components/messages/userSignedUp" ``` - - - #### Server Bindings Object Map describing protocol-specific definitions for a server. @@ -960,8 +935,6 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). - - #### Channel Bindings Object Map describing protocol-specific definitions for a channel. @@ -992,8 +965,6 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). - - #### Operation Bindings Object Map describing protocol-specific definitions for an operation. @@ -1024,9 +995,6 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). - - - #### Message Bindings Object Map describing protocol-specific definitions for a message. @@ -1057,12 +1025,6 @@ Field Name | Type | Description This object MAY be extended with [Specification Extensions](#specificationExtensions). - - - - - - #### Message Object Describes a message received on a given channel and operation. @@ -1096,17 +1058,16 @@ The following table contains a set of values that every implementation MUST supp Name | Allowed values | Notes ---|:---:|--- [AsyncAPI 2.6.0 Schema Object](#schemaObject) | `application/vnd.aai.asyncapi;version=2.6.0`, `application/vnd.aai.asyncapi+json;version=2.6.0`, `application/vnd.aai.asyncapi+yaml;version=2.6.0` | This is the default when a `schemaFormat` is not provided. -[JSON Schema Draft 07](https://json-schema.org/specification-links.html#draft-7) | `application/schema+json;version=draft-07`, `application/schema+yaml;version=draft-07` | +[JSON Schema Draft 07](https://json-schema.org/specification-links.html#draft-7) | `application/schema+json;version=draft-07`, `application/schema+yaml;version=draft-07` | The following table contains a set of values that every implementation is RECOMMENDED to support. Name | Allowed values | Notes ---|:---:|--- [Avro 1.9.0 schema](https://avro.apache.org/docs/1.9.0/spec.html#schemas) | `application/vnd.apache.avro;version=1.9.0`, `application/vnd.apache.avro+json;version=1.9.0`, `application/vnd.apache.avro+yaml;version=1.9.0` | -[OpenAPI 3.0.0 Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject) | `application/vnd.oai.openapi;version=3.0.0`, `application/vnd.oai.openapi+json;version=3.0.0`, `application/vnd.oai.openapi+yaml;version=3.0.0` | +[OpenAPI 3.0.0 Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject) | `application/vnd.oai.openapi;version=3.0.0`, `application/vnd.oai.openapi+json;version=3.0.0`, `application/vnd.oai.openapi+yaml;version=3.0.0` | [RAML 1.0 data type](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/) | `application/raml+yaml;version=1.0` | - ##### Message Object Example ```json @@ -1255,12 +1216,6 @@ payload: $ref: 'path/to/user-create.avsc/#UserCreate' ``` - - - - - - #### Message Trait Object Describes a trait that MAY be applied to a [Message Object](#messageObject). This object MAY contain any property from the [Message Object](#messageObject), except `payload` and `traits`. @@ -1303,13 +1258,13 @@ contentType: application/json #### Message Example Object -Message Example Object represents an example of a [Message Object](#messageObject) and MUST contain either **headers** and/or **payload** fields. +Message Example Object represents an example of a [Message Object](#messageObject) and MUST contain either **headers** and/or **payload** fields. ##### Fixed Fields Field Name | Type | Description ---|:---:|--- -headers | `Map[string, any]` | The value of this field MUST validate against the [Message Object's headers](#messageObjectHeaders) field. +headers | `Map[string, any]` | The value of this field MUST validate against the [Message Object's headers](#messageObjectHeaders) field. payload | `any` | The value of this field MUST validate against the [Message Object's payload](#messageObjectPayload) field. name | `string` | A machine-friendly name. summary | `string` | A short summary of what the example is about. @@ -1359,6 +1314,7 @@ A Tags object is a list of Tag Objects. Allows adding meta data to a single tag. ##### Fixed Fields + Field Name | Type | Description ---|:---:|--- name | `string` | **REQUIRED.** The name of the tag. @@ -1371,8 +1327,8 @@ This object MAY be extended with [Specification Extensions](#specificationExtens ```json { - "name": "user", - "description": "User-related messages" + "name": "user", + "description": "User-related messages" } ``` @@ -1381,12 +1337,6 @@ name: user description: User-related messages ``` - - - - - - #### External Documentation Object Allows referencing an external resource for extended documentation. @@ -1423,6 +1373,7 @@ The Reference Object is defined by [JSON Reference](https://tools.ietf.org/html/ For this specification, reference resolution is done as defined by the JSON Reference specification and not by the JSON Schema specification. ##### Fixed Fields + Field Name | Type | Description ---|:---:|--- $ref | `string` | **REQUIRED.** The reference string. @@ -1449,10 +1400,10 @@ All objects defined within the components object will have no effect on the API ##### Fixed Fields Field Name | Type | Description ----|:---|--- +---|:---|--- schemas | Map[`string`, [Schema Object](#schemaObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Schema Objects](#schemaObject). servers | Map[`string`, [Server Object](#serverObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Objects](#serverObject). - serverVariables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Variable Objects](#serverVariableObject). + serverVariables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Variable Objects](#serverVariableObject). channels | Map[`string`, [Channel Item Object](#channelItemObject)] | An object to hold reusable [Channel Item Objects](#channelItemObject). messages | Map[`string`, [Message Object](#messageObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Message Objects](#messageObject). securitySchemes| Map[`string`, [Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Security Scheme Objects](#securitySchemeObject). @@ -1471,7 +1422,7 @@ All the fixed fields declared above are objects that MUST use keys that match th Field Name Examples: -``` +```plaintext User User_1 User_Name @@ -1752,6 +1703,7 @@ Alternatively, any time a Schema Object can be used, a [Reference Object](#refer In addition to the JSON Schema fields, the following AsyncAPI vocabulary fields MAY be used for further schema documentation: ##### Fixed Fields + Field Name | Type | Description ---|:---:|--- discriminator | `string` | Adds support for polymorphism. The discriminator is the schema property name that is used to differentiate between other schema that inherit this schema. The property name used MUST be defined at this schema and it MUST be in the `required` property list. When used, the value MUST be the name of this schema or any schema that inherits it. See [Composition and Inheritance](#schemaComposition) for more details. @@ -1763,18 +1715,18 @@ This object MAY be extended with [Specification Extensions](#specificationExtens ###### Composition and Inheritance (Polymorphism) The AsyncAPI Specification allows combining and extending model definitions using the `allOf` property of JSON Schema, in effect offering model composition. -`allOf` takes in an array of object definitions that are validated *independently* but together compose a single object. +`allOf` takes in an array of object definitions that are validated _independently_ but together compose a single object. While composition offers model extensibility, it does not imply a hierarchy between the models. To support polymorphism, AsyncAPI Specification adds the support of the `discriminator` field. When used, the `discriminator` will be the name of the property used to decide which schema definition is used to validate the structure of the model. As such, the `discriminator` field MUST be a required field. -There are are two ways to define the value of a discriminator for an inheriting instance. +There are two ways to define the value of a discriminator for an inheriting instance. - Use the schema's name. - Override the schema's name by overriding the property with a new value. If exists, this takes precedence over the schema's name. -As such, inline schema definitions, which do not have a given id, *cannot* be used in polymorphism. +As such, inline schema definitions, which do not have a given id, _cannot_ be used in polymorphism. ##### Schema Object Examples @@ -2159,25 +2111,22 @@ schemas: - color ``` - - - - #### Security Scheme Object Defines a security scheme that can be used by the operations. Supported schemes are: -* User/Password. -* API key (either as user or as password). -* X.509 certificate. -* End-to-end encryption (either symmetric or asymmetric). -* HTTP authentication. -* HTTP API key. -* OAuth2's common flows (Implicit, Resource Owner Protected Credentials, Client Credentials and Authorization Code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749). -* [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06). -* SASL (Simple Authentication and Security Layer) as defined in [RFC4422](https://tools.ietf.org/html/rfc4422). +- User/Password. +- API key (either as user or as password). +- X.509 certificate. +- End-to-end encryption (either symmetric or asymmetric). +- HTTP authentication. +- HTTP API key. +- OAuth2's common flows (Implicit, Resource Owner Protected Credentials, Client Credentials and Authorization Code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749). +- [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06). +- SASL (Simple Authentication and Security Layer) as defined in [RFC4422](https://tools.ietf.org/html/rfc4422). ##### Fixed Fields + Field Name | Type | Applies To | Description ---|:---:|---|--- type | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"userPassword"`, `"apiKey"`, `"X509"`, `"symmetricEncryption"`, `"asymmetricEncryption"`, `"httpApiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`, `"plain"`, `"scramSha256"`, `"scramSha512"`, and `"gssapi"`. @@ -2333,6 +2282,7 @@ type: scramSha512 Allows configuration of the supported OAuth Flows. ##### Fixed Fields + Field Name | Type | Description ---|:---:|--- implicit| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Implicit flow. @@ -2347,6 +2297,7 @@ This object MAY be extended with [Specification Extensions](#specificationExtens Configuration details for a supported OAuth Flow ##### Fixed Fields + Field Name | Type | Applies To | Description ---|:---:|---|--- authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of an absolute URL. @@ -2455,11 +2406,11 @@ petstore_auth: ### Correlation ID Object -An object that specifies an identifier at design time that can used for message tracing and correlation. +An object that specifies an identifier at design time that can used for message tracing and correlation. For specifying and computing the location of a Correlation ID, a [runtime expression](#runtimeExpression) is used. -##### Fixed Fields +#### Fixed Fields Field Name | Type | Description ---|:---|--- @@ -2468,7 +2419,7 @@ location | `string` | **REQUIRED.** A [runtime expression](#runtimeExpression) t This object MAY be extended with [Specification Extensions](#specificationExtensions). -##### Examples +#### Examples ```json { @@ -2489,7 +2440,7 @@ This mechanism is used by [Correlation ID Object](#correlationIdObject). The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax: -``` +```plaintext expression = ( "$message" "." source ) source = ( header-reference | payload-reference ) header-reference = "header" ["#" fragment] @@ -2499,7 +2450,7 @@ The runtime expression is defined by the following [ABNF](https://tools.ietf.org The table below provides examples of runtime expressions and examples of their use in a value: -##### Examples +#### Examples Source Location | Example expression | Notes ---|:---|:---| @@ -2531,7 +2482,6 @@ Tools that do not recognize a specific `format` MAY default back to the `type` a The formats defined by the AsyncAPI Specification are: - Common Name | `type` | [`format`](#dataTypeFormat) | Comments ----------- | ------ | -------- | -------- integer | `integer` | `int32` | signed 32 bits diff --git a/pages/docs/tools/cli/context.md b/pages/docs/tools/cli/context.md new file mode 100644 index 000000000000..95fbcc8e0083 --- /dev/null +++ b/pages/docs/tools/cli/context.md @@ -0,0 +1,156 @@ +--- +title: 'Context concept' +weight: 50 +--- + +## Overview + +AsyncAPI CLI provides functionality called `context`. It's purpose is to help to work with AsyncAPI CLI in large projects where you do not have just one service exposing AsyncAPI document, but multiple. + +Event driven architecture involves multiple actors, subscribers and publishers. One time you want to validate document **A** and the other time you want to generate models from document **B**. Every time you do it, you need to provide to AsyncAPI CLI the location of the AsyncAPI document, which might be time consuming. You can workaround it with aliases in bash profiles or with other solutions but it is better to use `context` feature, as you can then store it in your repository and share with other team members. + +In short it means that for example instead of writing `asyncapi validate /some/folder/my-asyncapi.yml` you can create a context called `myasync` that will be an alias for and point to `/some/folder/my-asyncapi.yml`. This way next time you use the CLI you can do `asyncapi validate myasync`. + +## Context File location + +You can have a global context for your workstation, and a project specific context. + +If your use case is that you work with multiple repositories, you might want to use a global context. The `.asyncapi-cli` context file is then located in your home directory. You can also store your custom `.asyncapi-cli` file in your project with custom configuration. This way when you run `asyncapi config context add` inside your project, the new context is added to the context file under your project. + +## How to add context to a project + +### Manually + - Create file `.asyncapi-cli` containing [minimal empty context file](#minimalEmptyContextFile) in: + - current directory + - root of current repository + - user's home directory + +### Using CLI's `init` command + +`asyncapi config context init [CONTEXT-FILE-PATH]` + +Where `[CONTEXT-FILE-PATH]` instructs CLI what directory should the file `.asyncapi-cli` containing [minimal empty context file](#minimalEmptyContextFile) be created in: + - current directory: `asyncapi config context init .` (default) + - root of current repository: `asyncapi config context init ./` + - user's home directory: `asyncapi config context init ~` + +(if `[CONTEXT-FILE-PATH]` is omitted, empty context file is created in current directory) + +Make use of newly created `.asyncapi-cli` by executing command: + +`asyncapi config context add [CONTEXT-NAME] [SPEC-FILE-PATH]` + +### Setup example in a real project + +Below you can see an example of context setup for [Event Driven Flight status notification service](https://github.com/amadeus4dev-examples/amadeus-async-flight-status/tree/ff433b6d320a3a6a2499976cbf0782353bc57c16) of the [Amadeus Airline Platform](https://amadeus.com/en/industries/airlines/airline-platform), with multiple microservices and their AsyncAPI documents. + +```bash +# One-time initialization of '.asyncapi-cli' file +(main)$ asyncapi config context init +Initialized context /amadeus-async-flight-status/.asyncapi-cli + +# Adding first context +(main)$ asyncapi config context add subscriber subscriber/asyncapi.yaml +Added context "subscriber". +You can set it as your current context: asyncapi config context use subscriber +You can use this context when needed by passing subscriber as a parameter: asyncapi validate subscriber + +# Adding more contexts +(main)$ asyncapi config context add notifier notifier/asyncapi.yaml +Added context "notifier". +You can set it as your current context: asyncapi config context use notifier +You can use this context when needed by passing notifier as a parameter: asyncapi validate notifier + +(main)$ asyncapi config context add monitor monitor/asyncapi.yaml +Added context "monitor". +You can set it as your current context: asyncapi config context use monitor +You can use this context when needed by passing monitor as a parameter: asyncapi validate monitor + +# Setting monitor as default context +(main)$ asyncapi config context use monitor +monitor is set as current + +# Now you do not even have to remember the context name, and default 'monitor/asyncapi.yaml' will be validated +(main)$ asyncapi validate +File monitor/asyncapi.yaml is valid but has (itself and/or referenced documents) governance issues. +monitor/asyncapi.yaml + 1:1 warning asyncapi-defaultContentType AsyncAPI document should have "defaultContentType" field. + 1:1 warning asyncapi-id AsyncAPI document should have "id" field. + 1:1 warning asyncapi2-tags AsyncAPI object should have non-empty "tags" array. + 1:11 information asyncapi-latest-version The latest version of AsyncAPi is not used. It is recommended update to the "2.6.0" version. asyncapi + 2:6 warning asyncapi-info-contact Info object should have "contact" object. info + 19:15 warning asyncapi2-operation-operationId Operation should have an "operationId" field defined. channels.flight/update.subscribe + 26:13 warning asyncapi2-operation-operationId Operation should have an "operationId" field defined. channels.flight/queue.publish +βœ– 7 problems (0 errors, 6 warnings, 1 info, 0 hints) + +# You can now use context name when running AsyncAPI commands, no need to remember file location like 'notifier/asyncapi.yaml' +(main)$ asyncapi validate notifier +File notifier/asyncapi.yaml is valid but has (itself and/or referenced documents) governance issues. +notifier/asyncapi.yaml + 1:1 warning asyncapi-defaultContentType AsyncAPI document should have "defaultContentType" field. + 1:1 warning asyncapi-id AsyncAPI document should have "id" field. + 1:1 warning asyncapi2-tags AsyncAPI object should have non-empty "tags" array. + 1:11 information asyncapi-latest-version The latest version of AsyncAPi is not used. It is recommended update to the "2.6.0" version. asyncapi + 2:6 warning asyncapi-info-contact Info object should have "contact" object. info + 18:13 warning asyncapi2-operation-operationId Operation should have an "operationId" field defined. channels.flight/update.publish +βœ– 6 problems (0 errors, 5 warnings, 1 info, 0 hints) + +# Switch default context +(main)$ asyncapi config context use notifier +notifier is set as current + +# List all contexts +(main)$ asyncapi config context list +monitor: monitor/asyncapi.yaml +notifier: notifier/asyncapi.yaml +subscriber: subscriber/asyncapi.yaml +``` + +## Context File structure + +### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +current | `string` | An optional string value representing one of context names, which is used as default in CLI. Default means you can run CLI commands without providing context name, like `asyncapi validate`, and it will run against the default - `current` - context. +store | [Store Object](#storeObject) | **REQUIRED**. Map of filesystem paths to target AsyncAPI documents. + +### Store Object + +Map of filesystem paths to target AsyncAPI documents. + +**Patterned Fields** + +Field Pattern | Type | Description +---|:---:|--- +{contextName} | `string` | An optional string value representing filesystem path to the target AsyncAPI document. + +### Minimal Empty Context File +Raw JSON: +``` +{ + "store": {} +} +``` +Stringified JSON: +``` +{"store":{}} +``` + +### Context File Example + +Example of a context file for [Event Driven Flight status notification service](https://github.com/amadeus4dev-examples/amadeus-async-flight-status/tree/ff433b6d320a3a6a2499976cbf0782353bc57c16) of the [Amadeus Airline Platform](https://amadeus.com/en/industries/airlines/airline-platform), with multiple microservices and their AsyncAPI documents: +``` +{ + "current": "monitor", + "store": { + "monitor": "monitor/asyncapi.yaml", + "notifier": "notifier/asyncapi.yaml", + "subscriber": "subscriber/asyncapi.yaml" + } +} +``` + +## More context related CLI options + +All commands for managing contexts are available under `asyncapi config context` [CLI commands group](usage#asyncapi-config-context). diff --git a/pages/docs/tools/cli/usage.md b/pages/docs/tools/cli/usage.md index 90d7e4962aa4..f363b5ee53fd 100644 --- a/pages/docs/tools/cli/usage.md +++ b/pages/docs/tools/cli/usage.md @@ -29,7 +29,7 @@ $ npm install -g @asyncapi/cli $ asyncapi COMMAND running command... $ asyncapi (--version) -@asyncapi/cli/0.51.6 linux-x64 node-v18.17.0 +@asyncapi/cli/0.52.2 linux-x64 node-v18.17.0 $ asyncapi --help [COMMAND] USAGE $ asyncapi COMMAND @@ -45,6 +45,8 @@ USAGE * [`asyncapi config context`](#asyncapi-config-context) * [`asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH`](#asyncapi-config-context-add-context-name-spec-file-path) * [`asyncapi config context current`](#asyncapi-config-context-current) +* [`asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH`](#asyncapi-config-context-edit-context-name-new-spec-file-path) +* [`asyncapi config context init [CONTEXT-FILE-PATH]`](#asyncapi-config-context-init-context-file-path) * [`asyncapi config context list`](#asyncapi-config-context-list) * [`asyncapi config context remove CONTEXT-NAME`](#asyncapi-config-context-remove-context-name) * [`asyncapi config context use CONTEXT-NAME`](#asyncapi-config-context-use-context-name) @@ -91,7 +93,7 @@ EXAMPLES $ asyncapi bundle ./asyncapi.yaml ./features.yaml --base ./asyncapi.yaml --reference-into-components ``` -_See code: [src/commands/bundle.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/bundle.ts)_ +_See code: [src/commands/bundle.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/bundle.ts)_ ## `asyncapi config` @@ -105,18 +107,23 @@ DESCRIPTION CLI config settings ``` -_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/config/index.ts)_ +_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/config/index.ts)_ ## `asyncapi config context` +Manage short aliases for full paths to AsyncAPI documents + ``` USAGE $ asyncapi config context + +DESCRIPTION + Manage short aliases for full paths to AsyncAPI documents ``` ## `asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH` -Add or modify a context in the store +Add a context to the store ``` USAGE @@ -130,7 +137,7 @@ FLAGS -h, --help Show CLI help. DESCRIPTION - Add or modify a context in the store + Add a context to the store ``` ## `asyncapi config context current` @@ -148,9 +155,49 @@ DESCRIPTION Shows the current context that is being used ``` +## `asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH` + +Edit a context in the store + +``` +USAGE + $ asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH [-h] + +ARGUMENTS + CONTEXT-NAME context name + NEW-SPEC-FILE-PATH new file path of the spec file + +FLAGS + -h, --help Show CLI help. + +DESCRIPTION + Edit a context in the store +``` + +## `asyncapi config context init [CONTEXT-FILE-PATH]` + +Initialize context + +``` +USAGE + $ asyncapi config context init [CONTEXT-FILE-PATH] [-h] + +ARGUMENTS + CONTEXT-FILE-PATH Specify directory in which context file should be created: + - current directory : asyncapi config context init . (default) + - root of current repository : asyncapi config context init ./ + - user's home directory : asyncapi config context init ~ + +FLAGS + -h, --help Show CLI help. + +DESCRIPTION + Initialize context +``` + ## `asyncapi config context list` -List all the stored context in the store +List all the stored contexts in the store ``` USAGE @@ -160,7 +207,7 @@ FLAGS -h, --help Show CLI help. DESCRIPTION - List all the stored context in the store + List all the stored contexts in the store ``` ## `asyncapi config context remove CONTEXT-NAME` @@ -234,7 +281,7 @@ DESCRIPTION Convert asyncapi documents older to newer versions ``` -_See code: [src/commands/convert.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/convert.ts)_ +_See code: [src/commands/convert.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/convert.ts)_ ## `asyncapi diff OLD NEW` @@ -289,7 +336,7 @@ DESCRIPTION Find diff between two asyncapi files ``` -_See code: [src/commands/diff.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/diff.ts)_ +_See code: [src/commands/diff.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/diff.ts)_ ## `asyncapi generate` @@ -303,7 +350,7 @@ DESCRIPTION Generate typed models or other things like clients, applications or docs using AsyncAPI Generator templates. ``` -_See code: [src/commands/generate/index.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/generate/index.ts)_ +_See code: [src/commands/generate/index.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/generate/index.ts)_ ## `asyncapi generate fromTemplate ASYNCAPI TEMPLATE` @@ -432,7 +479,7 @@ DESCRIPTION Creates a new asyncapi file ``` -_See code: [src/commands/new/index.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/new/index.ts)_ +_See code: [src/commands/new/index.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/new/index.ts)_ ## `asyncapi new file` @@ -520,7 +567,7 @@ EXAMPLES $ asyncapi optimize ./asyncapi.yaml --optimization=remove-components,reuse-components,move-to-components --output=terminal --no-tty ``` -_See code: [src/commands/optimize.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/optimize.ts)_ +_See code: [src/commands/optimize.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/optimize.ts)_ ## `asyncapi start` @@ -534,7 +581,7 @@ DESCRIPTION Start asyncapi studio ``` -_See code: [src/commands/start/index.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/start/index.ts)_ +_See code: [src/commands/start/index.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/start/index.ts)_ ## `asyncapi start studio` @@ -578,5 +625,5 @@ DESCRIPTION validate asyncapi file ``` -_See code: [src/commands/validate.ts](https://github.com/asyncapi/cli/blob/v0.51.6/src/commands/validate.ts)_ +_See code: [src/commands/validate.ts](https://github.com/asyncapi/cli/blob/v0.52.2/src/commands/validate.ts)_ diff --git a/pages/index.js b/pages/index.js index 876e6e42566f..67f9185d4923 100644 --- a/pages/index.js +++ b/pages/index.js @@ -24,10 +24,11 @@ import GoogleCalendarButton from '../components/buttons/GoogleCalendarButton'; import ICSFileButton from '../components/buttons/ICSFileButton'; import SubscribeButton from '../components/buttons/SubscribeButton'; import NewsroomSection from '../components/newsroom/NewsroomSection' -import { languageDetection } from "next-i18next-static-site"; +import { languageDetection } from "../lib/i18n"; function HomePage() { - languageDetection(); + //To be enabled in a future PR + //languageDetection(); return ( <> diff --git a/public/img/posts/2023-summary/blog-banner-july.webp b/public/img/posts/2023-summary/blog-banner-july.webp new file mode 100644 index 000000000000..6f1567a09f78 Binary files /dev/null and b/public/img/posts/2023-summary/blog-banner-july.webp differ diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index 2b4b4dac4cfe..073a63db9b1d 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -1,7 +1,7 @@ const { writeFileSync } = require('fs'); const { resolve } = require('path'); const fetch = require('node-fetch') -export async function buildNewsroomVideos() { +async function buildNewsroomVideos() { try { let data; @@ -40,4 +40,5 @@ export async function buildNewsroomVideos() { } } -buildNewsroomVideos() \ No newline at end of file +buildNewsroomVideos() +module.exports={buildNewsroomVideos} \ No newline at end of file