diff --git a/.gitignore b/.gitignore index 02f2bf964620..ed771f133ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules .swc out config/posts.json +config/case-studies.json public/rss.xml .env.local yarn.lock diff --git a/README.md b/README.md index d622fd44056e..d065bc2c107e 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,27 @@ npm run build Generated files of the website go to the `.next` folder. +## Case studies + +### Overview + +A case study is a special document that any end-user company can provide. An end-user company is a company that uses AsyncAPI to solve technical challenges. A case study is not a document where a vendor company can describe how they build their commercial AsyncAPI-based product. On the other hand, it is completely fine if a case study of some end-user mentions some commercial tools that helped them to work with AsyncAPI or event-driven architecture. An example of such a case can be a case study from an end-user where at some point, Confluent Schema Registry is mentioned in an explanation about schemas and runtime message validation. + +### How to add a case study + +A case study is documented in the form of a YAML file. Anyone can open a pull request with a new case study. + +- YAML file must be located in `config/casestudies`. +- To make it easier for you to create such a YAML file you can use: + - [Template YAML with comments explaining every section](scripts/casestudies/casestudy_template.yml) + - [JSON Schema that describes all YAML fields](scripts/casestudies/schema.json) +- All additional files for the case study, like complete AsyncAPI document examples, should be located in the `public/resources/casestudies` directory. +- Company logo and other images that will be rendered in the website should be located in `public/img/casestudies`. + +Once you collect all information and create a case study, open a pull request. It must be authored or at least approved by a representative of the given company. Such a representative is probably already a contact person mentioned in the case study. + +A case study becomes publicly available right after merging and rebuilding the website. + ## JSON Schema definitions All AsyncAPI JSON Schema definition files are being served within the `/definitions/` path. The content is being served from GH, in particular from https://github.com/asyncapi/spec-json-schemas/tree/master/schemas. @@ -119,7 +140,7 @@ This repository has the following structure: └── tailwind.config.js # TailwindCSS configuration file ``` -## Contributors ✨ +## Contributors Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): diff --git a/components/CaseStudyCard.js b/components/CaseStudyCard.js new file mode 100644 index 000000000000..fc741b4c487b --- /dev/null +++ b/components/CaseStudyCard.js @@ -0,0 +1,29 @@ +import Paragraph from './typography/Paragraph'; + +export default function CaseStudyCard({ + studies = [] +}) { + if(studies.length === 0){ + return null; + } + return ( +
+ {studies.map((study, index) => ( + +
+ + {study.company.name} + + + { study.company.description } + +
+
+ ))} +
+ ); +} diff --git a/components/MDX.js b/components/MDX.js index 5fa8d67d8b05..b35c1a2afba3 100644 --- a/components/MDX.js +++ b/components/MDX.js @@ -24,7 +24,7 @@ let mermaidInitialized = false; initializeMermaid(); const mdxComponents = getMDXComponents(); -export default function MDXProvider({ children }) { +export function MDXProvider({ children }) { return ( {children} @@ -32,7 +32,7 @@ export default function MDXProvider({ children }) { ); } -function getMDXComponents() { +export function getMDXComponents() { return { h1: props =>

, h2: props =>

, diff --git a/components/navigation/otherItems.js b/components/navigation/otherItems.js index 8ce757ecae47..6f18e3245105 100644 --- a/components/navigation/otherItems.js +++ b/components/navigation/otherItems.js @@ -1,6 +1,6 @@ export default [ + { text: "Case Studies", href: '/casestudies' }, { text: 'Blog', href: '/blog' }, // { text: 'Shop', href: 'https://asyncapi.threadless.com', target: '_blank' }, { text: "Roadmap", href: '/roadmap', className: 'text-secondary-500 font-bold' }, - { text: "Jobs", href: '/jobs', className: 'text-secondary-500 font-bold' }, ] \ No newline at end of file diff --git a/config/casestudies/adeo.yml b/config/casestudies/adeo.yml new file mode 100644 index 000000000000..f81f6f8fa739 --- /dev/null +++ b/config/casestudies/adeo.yml @@ -0,0 +1,265 @@ +id: adeogroup +company: + name: Adeo Group + description: Adeo owns different brands in retail industry focused on home improvement and DIY markets, like Leroy Merlin. + customers: 500M + industry: Retail + revenue: 25.6B EURO turnover, including 768M EURO online. + website: https://www.adeo.com/ + logo: /img/casestudies/adeo/logo.svg + contact: + - name: Ludovic Dussart + link: https://twitter.com/ldussart +challenges: | + Cost Component Repository product, part of the ADEO tech products, is used to calculate and publish transfer prices between different internal locations globally. Different business units use different information systems. It is hard to learn how each business unit shares information about its systems, API and accuracy. + + The initial solution was a developer portal with a list of all applications and reference to dedicated documentation. Some legacy systems had docs written in MS Excel. + + There was a need for a standart way of describing event-driven architecture. +solution: | + The API is now described with AsyncAPI. The AsyncAPI file, stored with the source code, generates HTML documentation in the same release pipeline for the product. Documentation is exposed internally as part of the product for other company units depending on the API. + + Payloads are described with Avro schema. These schemas generate models and are referenced directly in AsyncAPI files thanks to the `schemaFormat` feature and `$ref`. This way, they make sure the code is aligned with the docs. + + Shift to using AsyncAPI also enables the team to implement more use cases using AsyncAPI files. +technical: + languages: + - Java + frameworks: + - Spring + protocols: + - Kafka + brokers: | + Kafka with Kafka Connect component. There are 15 production brokers with 47 topics. + testing: | + For Kafka, e2e tests are done with [Zerocode](https://github.com/authorjapps/zerocode). Load tests are handled with [JMeter](https://jmeter.apache.org/) with the [kloadgen](https://github.com/corunet/kloadgen) plugin that supports Kafka and Avro. + architecture: | + The following [enterprise integration patterns](https://www.enterpriseintegrationpatterns.com/patterns/messaging) are applied: + - [Request/Reply](https://www.enterpriseintegrationpatterns.com/patterns/messaging/RequestReply.html) + Described with `description` field in AsyncAPI. Reply goes to dedicated reply channel. Example description of response channel: + ``` + description: > + This topic is used to REPLY Costing Requests and is targeted by the + `REPLY_TOPIC` header. + ``` + - [Return Address](https://www.enterpriseintegrationpatterns.com/patterns/messaging/ReturnAddress.html) + Info that needs to be provided by the client so producer knows where to send a response. Information is sent in the message header with the `REPLY_TOPIC` property. The AsyncAPI file documents information as part of the Message Header object. Example of request message header with `REPLY_TOPIC`: + ``` + headers: + type: object + required: + - REPLY_TOPIC + properties: + REPLY_TOPIC: + $ref: "#/components/schemas/ReplyTopic" + ``` + - [Correlation Identifier](https://www.enterpriseintegrationpatterns.com/patterns/messaging/CorrelationIdentifier.html) + This pattern enables the identification of the request given to the sent response. The `REQUEST_ID` property is in the request message header. The `CORRELATION_ID` property is in the response message header. Both headers are described in the AsyncAPI Message Header object and referred to in the AsyncAPI `correlationID` property. + This means that correlation identifier is represented by different property in the message header, depending if it is a request or reply. Example of request message header with `REQUEST_ID`: + ``` + headers: + type: object + required: + - REQUEST_ID + properties: + REQUEST_ID: + $ref: "#/components/schemas/RequestId" + ``` + Example of how `correlationId` points to `REQUEST_ID`: + ``` + correlationId: + description: > + This correlation ID is used for message tracing and messages + correlation. + This correlation ID is generated at runtime based on the `REQUEST_ID` + and sent to the RESPONSE message. + location: $message.header#/REQUEST_ID + ```` + - [DeadLetter Channel](https://www.enterpriseintegrationpatterns.com/patterns/messaging/DeadLetterChannel.html) + Also known as Dead Letter Queue. In Kafka, it is just another channel where undelivered messages are sent. Not part of the AsyncAPI file, as API consumers will not listen to this channel. Consumers know what happens with wrong events. + - [Invalid Message Channel](https://www.enterpriseintegrationpatterns.com/patterns/messaging/InvalidMessageChannel.html) + Invalid messages are routed to the dedicated channel for rejected requests but are not part of the AsyncAPI file, as API consumers will not listen to this channel. Consumers know what happens with wrong events. + + ![Architecture Diagram](/img/casestudies/adeo/architecture.webp) + codegen: | + Java models generation. Avro schemas used as a source. +schemas: + description: Avro 1.9 + storage: Git repository where source code is. During release they are published to Confluent Schema Registry. + registry: Confluent Schema Registry. + versioning: Versioning is based on git tags. The schema version pushed to Confluent Schema Registry matches the git tag version of the product. Every schema has a `version` information that matches with product tag version. + validation: Based on validation using Confluent Schema Registry. +asyncapi: + usecase: | + Document the API of the product, so its users know how it works and how to use it. AsyncAPI was selected as the standard that allows you to generate documentation from a machine-readable document that describes the API. + The goal was to document API in a standardized way, so other internal products could follow to unify how APIs are documented across the company. + versions: + - 2.4.0 + storage: Git repository where source code is. + editing: IntelliJ without any special plugins. Sometimes people use AsyncAPI Studio, but not regularly because of lack of support for references to local drive. + maintainers: Developers + audience: + internal: true + external: false + extensions: | + Extensions are used to describe details about custom security: + ```yml + x-sasl.jaas.config: >- + org.apache.kafka.common.security.plain.PlainLoginModule required + username="" password=""; + x-security.protocol: SASL_SSL + x-ssl.endpoint.identification.algorithm: https + x-sasl.mechanism: PLAIN + ```` + documentation: | + Documentation generated from AsyncAPI is hosted as part of the product on a dedicated endpoint using Spring controller. + Publishing is part of the CI/CD pipeline for the product using GithubActions. + + Related Maven configuration used to trigger docs generation with AsyncAPI Generator industry: + + ``` + + generate-asyncapi-doc + + + + com.github.eirslett + frontend-maven-plugin + + ${frontend-maven-plugin.version} + + v12.18.4 + ${node.installation.path} + ${node.installation.path} + + + + install node and npm + + install-node-and-npm + + generate-resources + + + install @asyncapi/generator globally + + npm + + + install @asyncapi/generator@${asyncapi.generator.version} + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + execute-generation + + exec + + generate-resources + + + + ${node.modules.installation.path}/${ag.binary.name} + + ${project.basedir}/src/docs/asyncapi/asyncapi.yaml @asyncapi/html-template@${asyncapi.htmltemplate.version} -p sidebarOrganization=byTags -p + version=${project.version} -o ${asyncapi.generation.dir} + + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-resources + + generate-resources + + copy-resources + + + ${asyncapi.generation.dir}/assets + + + src/docs/asyncapi/assets + true + + + + + + + + + + ``` + + Critical features of AsyncAPI related to documentation: + - use of `version` parameter in the generator command to display the release version from the `Maven` pom + - `descriptions` that support `CommonMark` (Markdown) as they allow to put detailed structured descriptions and screenshots inside generated docs + - examples and validation information. In this case converted from Avro to JSON Schema to show it in documentation and have examples generated + - `Tags` for tagging operations to categorize them to make it easier to navigate in documentation UI + bindings: | + All Kafka bindings are used. Server, channel, operation and message bindings. + + Example of server bindings: + ``` + bindings: + kafka: + schema.registry.url: >- + https://schema-registry.prod.url/ + ``` + + Example of channel bindings: + ``` + bindings: + kafka: + replicas: 3 + partitions: 3 + cleanup.policy: delete + retention.ms: 7 days + ``` + + Example of operation bindings: + ``` + bindings: + kafka: + groupId: + type: string + description: > + The groupId must be prefixed by your `svc` account, deliver by the + Adeo Kafka team. + This `svc` must have the write access to the topic. + value.subject.name.strategy: + type: string + description: > + We use the RecordNameStrategy to infer the messages schema. + Use + `value.subject.name.strategy=io.confluent.kafka.serializers.subject.RecordNameStrategy` + in your producer configuration. + ``` + + Example of message bindings: + ``` + bindings: + kafka: + key: + $ref: "https://deploy-preview-921--asyncapi-website.netlify.app/resources/casestudies/adeo/CostingResponseKey.avsc" + ``` + + tools: | + * [AsyncAPI Generator](https://github.com/asyncapi/generator): + * [HTML Template](https://github.com/asyncapi/html-template) with parameters like `sidebarOrganization=byTags` and `version`. + * [AsyncAPI JavaScript Parser](https://github.com/asyncapi/parser-js) with [Avro Schema Parser](https://github.com/asyncapi/avro-schema-parser). + fullExample: resources/casestudies/adeo/asyncapi.yaml +additionalResources: Watch [this video presentation about AsyncAPI case study](https://www.youtube.com/watch?v=WwhRbvrf6Rs) from Ludovic Dussart, Ineat & Antoine Delequeuche, Adeo. \ No newline at end of file diff --git a/netlify.toml b/netlify.toml index 1c7c5a8883d6..3f69955de753 100644 --- a/netlify.toml +++ b/netlify.toml @@ -2,6 +2,7 @@ for = "/*" [headers.values] X-Frame-Options = "ALLOW-FROM https://www.youtube.com/" + Access-Control-Allow-Origin = "*" [build] command = "npm run build && npm run export" diff --git a/package-lock.json b/package-lock.json index 8bdc9f29ea88..60c3e797a956 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,10 +40,11 @@ "lodash": "^4.17.21", "markdown-to-txt": "^2.0.1", "markdown-toc": "1.2.0", - "mermaid": "^9.3.0", + "mermaid": "9.3.0", "moment": "^2.29.4", "monaco-editor": "^0.20.0", "next": "^12.0.0", + "next-mdx-remote": "^3.0.0", "node-fetch": "^2.6.7", "postcss": "^8.4.14", "react": "^17.0.2", @@ -361,11 +362,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.19.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", - "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", + "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "dependencies": { - "@babel/types": "^7.19.4", + "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -416,37 +417,37 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.7.tgz", + "integrity": "sha512-FNdu7r67fqMUSVuQpFQGE6BPdhJIhitoxhGzDbAXNcA07uoVG37fOiMk3OSV8rEICuyG6t8LGkd9EE64qIEoIA==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", - "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dependencies": { - "@babel/types": "^7.19.4" + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -480,13 +481,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", - "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", + "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -506,9 +507,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", - "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", + "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -552,11 +553,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", + "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -566,42 +567,39 @@ } }, "node_modules/@babel/runtime": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", - "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", + "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" + "regenerator-runtime": "^0.13.4" } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", - "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.7.tgz", + "integrity": "sha512-xueOL5+ZKX2dJbg8z8o4f4uTRTqGDRjilva9D1hiRlayJbTY8jBRL+Ph67IeRTIE439/VifHk+Z4g0SwRtQE0A==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.4", + "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.4", - "@babel/types": "^7.19.4", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -610,9 +608,9 @@ } }, "node_modules/@babel/types": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", - "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -623,9 +621,9 @@ } }, "node_modules/@braintree/sanitize-url": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", - "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz", + "integrity": "sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==" }, "node_modules/@docsearch/css": { "version": "3.2.1", @@ -870,9 +868,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.16.tgz", - "integrity": "sha512-LCQ+NeThyJ4k1W2d+vIKdxuSt9R3pQSZ4P92m7EakaYuXcVWbHuT5bjNcqLd4Rdgi6xYWYDvBJZJLZSLanjDcA==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -927,6 +925,52 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/@mdx-js/mdx/node_modules/mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "dependencies": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@mdx-js/react": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", @@ -1284,9 +1328,9 @@ } }, "node_modules/@slack/web-api": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-6.8.0.tgz", - "integrity": "sha512-DI0T7pQy2SM14s+zJKlarzkyOqhpu2Qk3rL19g+3m7VDZ+lSMB/dt9nwf3BZIIp49/CoLlBjEmKMoakm69OD4Q==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-6.8.1.tgz", + "integrity": "sha512-eMPk2S99S613gcu7odSw/LV+Qxr8A+RXvBD0GYW510wJuTERiTjP5TgCsH8X09+lxSumbDE88wvWbuFuvGa74g==", "dependencies": { "@slack/logger": "^3.0.0", "@slack/types": "^2.0.0", @@ -1405,20 +1449,46 @@ } }, "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "node_modules/@types/parse5": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "optional": true, + "peer": true + }, + "node_modules/@types/react": { + "version": "17.0.52", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.52.tgz", + "integrity": "sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A==", + "optional": true, + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "optional": true, + "peer": true + }, "node_modules/@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", @@ -2453,14 +2523,11 @@ } }, "node_modules/css-loader/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dependencies": { "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" } }, "node_modules/css-loader/node_modules/loader-utils": { @@ -2658,10 +2725,17 @@ "node": ">=8.0.0" } }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "optional": true, + "peer": true + }, "node_modules/d3": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.0.tgz", - "integrity": "sha512-a5rNemRadWkEfqnY5NsD4RdCP9vn8EIJ4I5Rl14U0uKH1SXqcNmk/h9aGaAF1O98lz6L9M0IeUcuPa9GUYbI5A==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.2.tgz", + "integrity": "sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==", "dependencies": { "d3-array": "3", "d3-axis": "3", @@ -2699,9 +2773,9 @@ } }, "node_modules/d3-array": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", - "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==", "dependencies": { "internmap": "1 - 2" }, @@ -2752,9 +2826,9 @@ } }, "node_modules/d3-contour": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.0.tgz", - "integrity": "sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", "dependencies": { "d3-array": "^3.2.0" }, @@ -2858,9 +2932,9 @@ } }, "node_modules/d3-geo": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", - "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", "dependencies": { "d3-array": "2.5.0 - 3" }, @@ -2888,9 +2962,9 @@ } }, "node_modules/d3-path": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.0.1.tgz", - "integrity": "sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", "engines": { "node": ">=12" } @@ -2955,20 +3029,20 @@ } }, "node_modules/d3-shape": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.1.0.tgz", - "integrity": "sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", "dependencies": { - "d3-path": "1 - 3" + "d3-path": "^3.1.0" }, "engines": { "node": ">=12" } }, "node_modules/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "dependencies": { "d3-array": "2 - 3" }, @@ -3395,6 +3469,15 @@ "is-symbol": "^1.0.2" } }, + "node_modules/esbuild": { + "version": "0.12.29", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.29.tgz", + "integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -4163,6 +4246,9 @@ "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" } }, "node_modules/gtoken": { @@ -4998,9 +5084,9 @@ } }, "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "bin": { "json5": "lib/cli.js" }, @@ -5386,25 +5472,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-hast": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", - "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-to-string": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", @@ -5501,14 +5568,11 @@ } }, "node_modules/mini-css-extract-plugin/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dependencies": { "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" } }, "node_modules/mini-css-extract-plugin/node_modules/loader-utils": { @@ -5584,9 +5648,9 @@ } }, "node_modules/moment-mini": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", - "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz", + "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==" }, "node_modules/monaco-editor": { "version": "0.20.0", @@ -5688,6 +5752,21 @@ } } }, + "node_modules/next-mdx-remote": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-3.0.8.tgz", + "integrity": "sha512-WFSxt0crxG5PN/0WvaunzxzqV3wh3dPBZyhkclxwyQfLSRKzsNSArzot/4gYTOOZ/GtyRfNjbI/HtDsW2S4fqQ==", + "dependencies": { + "@mdx-js/mdx": "^1.6.22", + "@mdx-js/react": "^1.6.22", + "esbuild": "^0.12.9", + "pkg-dir": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.x <=17.x", + "react-dom": ">=16.x <=17.x" + } + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -5990,6 +6069,20 @@ "node": ">=4" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", @@ -6171,6 +6264,68 @@ "node": ">=0.10.0" } }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, "node_modules/point-in-polygon": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz", @@ -6342,14 +6497,11 @@ } }, "node_modules/postcss-loader/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dependencies": { "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" } }, "node_modules/postcss-loader/node_modules/loader-utils": { @@ -7277,9 +7429,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", @@ -7413,7 +7565,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, - "node_modules/remark-parse": { + "node_modules/remark-mdx/node_modules/remark-parse": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", @@ -7670,6 +7822,9 @@ "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" } }, "node_modules/select": { @@ -7930,7 +8085,10 @@ "node_modules/strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/strip-color": { "version": "0.1.0", @@ -8349,22 +8507,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "node_modules/ua-parser-js": { - "version": "0.7.33", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", - "integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "engines": { - "node": "*" - } + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==" }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -8749,6 +8894,17 @@ "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==" }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/z-schema": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.2.tgz", @@ -9047,11 +9203,11 @@ } }, "@babel/generator": { - "version": "7.19.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", - "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", + "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "requires": { - "@babel/types": "^7.19.4", + "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } @@ -9087,31 +9243,31 @@ } }, "@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.7.tgz", + "integrity": "sha512-FNdu7r67fqMUSVuQpFQGE6BPdhJIhitoxhGzDbAXNcA07uoVG37fOiMk3OSV8rEICuyG6t8LGkd9EE64qIEoIA==", "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==" + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==" }, "@babel/helper-simple-access": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", - "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "requires": { - "@babel/types": "^7.19.4" + "@babel/types": "^7.20.2" } }, "@babel/helper-split-export-declaration": { @@ -9133,13 +9289,13 @@ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" }, "@babel/helpers": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", - "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", + "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/highlight": { @@ -9153,9 +9309,9 @@ } }, "@babel/parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", - "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==" + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", + "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==" }, "@babel/plugin-proposal-object-rest-spread": { "version": "7.12.1", @@ -9184,52 +9340,52 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", + "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/runtime": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", - "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", + "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", "requires": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/traverse": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", - "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.7.tgz", + "integrity": "sha512-xueOL5+ZKX2dJbg8z8o4f4uTRTqGDRjilva9D1hiRlayJbTY8jBRL+Ph67IeRTIE439/VifHk+Z4g0SwRtQE0A==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.4", + "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.4", - "@babel/types": "^7.19.4", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", - "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "requires": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -9237,9 +9393,9 @@ } }, "@braintree/sanitize-url": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", - "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz", + "integrity": "sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==" }, "@docsearch/css": { "version": "3.2.1", @@ -9442,9 +9598,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.16.tgz", - "integrity": "sha512-LCQ+NeThyJ4k1W2d+vIKdxuSt9R3pQSZ4P92m7EakaYuXcVWbHuT5bjNcqLd4Rdgi6xYWYDvBJZJLZSLanjDcA==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -9489,6 +9645,46 @@ "unified": "9.2.0", "unist-builder": "2.0.3", "unist-util-visit": "2.0.3" + }, + "dependencies": { + "mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "requires": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "requires": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + } + } } }, "@mdx-js/react": { @@ -9707,9 +9903,9 @@ "integrity": "sha512-ghdfZSF0b4NC9ckBA8QnQgC9DJw2ZceDq0BIjjRSv6XAZBXJdWgxIsYz0TYnWSiqsKZGH2ZXbj9jYABZdH3OSQ==" }, "@slack/web-api": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-6.8.0.tgz", - "integrity": "sha512-DI0T7pQy2SM14s+zJKlarzkyOqhpu2Qk3rL19g+3m7VDZ+lSMB/dt9nwf3BZIIp49/CoLlBjEmKMoakm69OD4Q==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-6.8.1.tgz", + "integrity": "sha512-eMPk2S99S613gcu7odSw/LV+Qxr8A+RXvBD0GYW510wJuTERiTjP5TgCsH8X09+lxSumbDE88wvWbuFuvGa74g==", "requires": { "@slack/logger": "^3.0.0", "@slack/types": "^2.0.0", @@ -9810,20 +10006,46 @@ } }, "@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "@types/parse5": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "optional": true, + "peer": true + }, + "@types/react": { + "version": "17.0.52", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.52.tgz", + "integrity": "sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A==", + "optional": true, + "peer": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, "@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "optional": true, + "peer": true + }, "@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", @@ -10750,9 +10972,9 @@ }, "dependencies": { "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "requires": { "minimist": "^1.2.0" } @@ -10913,10 +11135,17 @@ "css-tree": "^1.1.2" } }, + "csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "optional": true, + "peer": true + }, "d3": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.0.tgz", - "integrity": "sha512-a5rNemRadWkEfqnY5NsD4RdCP9vn8EIJ4I5Rl14U0uKH1SXqcNmk/h9aGaAF1O98lz6L9M0IeUcuPa9GUYbI5A==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.2.tgz", + "integrity": "sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==", "requires": { "d3-array": "3", "d3-axis": "3", @@ -10951,9 +11180,9 @@ } }, "d3-array": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", - "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==", "requires": { "internmap": "1 - 2" } @@ -10989,9 +11218,9 @@ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" }, "d3-contour": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.0.tgz", - "integrity": "sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", "requires": { "d3-array": "^3.2.0" } @@ -11057,9 +11286,9 @@ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" }, "d3-geo": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", - "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", "requires": { "d3-array": "2.5.0 - 3" } @@ -11078,9 +11307,9 @@ } }, "d3-path": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.0.1.tgz", - "integrity": "sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" }, "d3-polygon": { "version": "3.0.1", @@ -11124,17 +11353,17 @@ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" }, "d3-shape": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.1.0.tgz", - "integrity": "sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", "requires": { - "d3-path": "1 - 3" + "d3-path": "^3.1.0" } }, "d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "requires": { "d3-array": "2 - 3" } @@ -11499,6 +11728,11 @@ "is-symbol": "^1.0.2" } }, + "esbuild": { + "version": "0.12.29", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.29.tgz", + "integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==" + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -12962,9 +13196,9 @@ } }, "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsx-ast-utils": { "version": "3.2.1", @@ -13324,21 +13558,6 @@ "unist-util-visit": "^2.0.0" } }, - "mdast-util-to-hast": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", - "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", - "requires": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" - } - }, "mdast-util-to-string": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", @@ -13422,9 +13641,9 @@ }, "dependencies": { "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "requires": { "minimist": "^1.2.0" } @@ -13497,9 +13716,9 @@ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "moment-mini": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", - "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz", + "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==" }, "monaco-editor": { "version": "0.20.0", @@ -13577,6 +13796,17 @@ "use-sync-external-store": "1.2.0" } }, + "next-mdx-remote": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-3.0.8.tgz", + "integrity": "sha512-WFSxt0crxG5PN/0WvaunzxzqV3wh3dPBZyhkclxwyQfLSRKzsNSArzot/4gYTOOZ/GtyRfNjbI/HtDsW2S4fqQ==", + "requires": { + "@mdx-js/mdx": "^1.6.22", + "@mdx-js/react": "^1.6.22", + "esbuild": "^0.12.9", + "pkg-dir": "^5.0.0" + } + }, "no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -13842,6 +14072,14 @@ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", @@ -14002,6 +14240,46 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "requires": { + "find-up": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + } + } + }, "point-in-polygon": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz", @@ -14116,9 +14394,9 @@ }, "dependencies": { "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "requires": { "minimist": "^1.2.0" } @@ -14860,9 +15138,9 @@ } }, "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regexp.prototype.flags": { "version": "1.4.3", @@ -14985,32 +15263,32 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "requires": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + } } } }, - "remark-parse": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", - "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", - "requires": { - "ccount": "^1.0.0", - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^2.0.0", - "vfile-location": "^3.0.0", - "xtend": "^4.0.1" - } - }, "remark-slug": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", @@ -15452,7 +15730,7 @@ "strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==" }, "strip-color": { "version": "0.1.0", @@ -15782,9 +16060,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "ua-parser-js": { - "version": "0.7.33", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", - "integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==" + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==" }, "unbox-primitive": { "version": "1.0.2", @@ -16091,6 +16369,11 @@ "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==" }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, "z-schema": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.2.tgz", diff --git a/package.json b/package.json index 253bbc697fb0..820e37c2a595 100644 --- a/package.json +++ b/package.json @@ -65,10 +65,11 @@ "lodash": "^4.17.21", "markdown-to-txt": "^2.0.1", "markdown-toc": "1.2.0", - "mermaid": "^9.3.0", + "mermaid": "9.3.0", "moment": "^2.29.4", "monaco-editor": "^0.20.0", "next": "^12.0.0", + "next-mdx-remote": "^3.0.0", "node-fetch": "^2.6.7", "postcss": "^8.4.14", "react": "^17.0.2", diff --git a/pages/_app.js b/pages/_app.js index c724c998e9be..db6cc9ab856e 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -3,7 +3,7 @@ import Layout from '../components/layout/Layout' import Banner from '../components/campaigns/Banner' import AppContext from '../context/AppContext' import Footer from "../components/Footer"; -import MDXProvider from '../components/MDX'; +import { MDXProvider } from '../components/MDX'; import AlgoliaSearch from '../components/AlgoliaSearch'; import '../styles/globals.css' diff --git a/pages/casestudies/[id].js b/pages/casestudies/[id].js new file mode 100644 index 000000000000..191b5d7b335f --- /dev/null +++ b/pages/casestudies/[id].js @@ -0,0 +1,296 @@ +import React from 'react'; +import Link from 'next/link'; +import Paragraph from '../../components/typography/Paragraph'; +import GenericLayout from '../../components/layout/GenericLayout'; +import Heading from '../../components/typography/Heading'; +import CaseStudiesList from '../../config/case-studies.json'; +import { MDXRemote } from 'next-mdx-remote'; +import { getMDXComponents } from '../../components/MDX.js'; +import { serialize } from 'next-mdx-remote/serialize' + +export async function getStaticProps({ params }) { + const data = CaseStudiesList.filter((p) => p.id === params.id); + + return { + props: { + casestudy: data[0], + challenges: await serialize(data[0].challenges), + solution: await serialize(data[0].solution), + usecase: await serialize(data[0].asyncapi.usecase), + architecture: await serialize(data[0].technical.architecture), + testing: await serialize(data[0].technical.testing), + codegen: await serialize(data[0].technical.codegen), + schemaStorage: await serialize(data[0].schemas.storage), + registry: await serialize(data[0].schemas.registry), + versioning: await serialize(data[0].schemas.versioning), + validation: await serialize(data[0].schemas.validation), + asyncapiStorage: await serialize(data[0].asyncapi.storage), + asyncapiEditing: await serialize(data[0].asyncapi.editing), + asyncapiExtensions: await serialize(data[0].asyncapi.extensions), + asyncapiDocumentation: await serialize(data[0].asyncapi.documentation), + asyncapiBindings: await serialize(data[0].asyncapi.bindings), + asyncapiTools: await serialize(data[0].asyncapi.tools), + additionalResources: await serialize(data[0].additionalResources), + }, + }; +} + +export async function getStaticPaths() { + const paths = CaseStudiesList.map((study) => ({ + params: { id: study.id }, + })); + return { + paths, + fallback: false, + }; +} + +function Index({ + casestudy, + challenges, + solution, + architecture, + testing, + codegen, + usecase, + schemaStorage, + registry, + versioning, + validation, + asyncapiStorage, + asyncapiEditing, + asyncapiExtensions, + asyncapiDocumentation, + asyncapiBindings, + asyncapiTools, + additionalResources +}) { + const image = '/img/social/website-card.png'; + const allComponents = getMDXComponents(); + return ( + +
+
+
+ + {casestudy.company.name} + +
+ + Industry: {casestudy.company.industry} + + + Customers: {casestudy.company.customers} + + + Revenue: {casestudy.company.revenue} + +
+
+ + {casestudy.company.description} + + + tl;dr just go and have a look at + + + full production-used AsyncAPI document + + + +
+
+
+ {casestudy.company.name} +
+
+
+ + Challenges + + + + +
+
+ + Solution + + + + +
+
+ + Use case + + + + +
+
+ + More details + +
+ + Languages: {casestudy.technical.languages[0]} + + + Frameworks: {casestudy.technical.frameworks[0]} + + + Protocols: {casestudy.technical.protocols[0]} + +
+ + Testing strategy + + + + +
+
+ + Approach to code generation + + + + +
+
+ + Architecture + + + + +
+
+ + More details about AsyncAPI + +
+ + Versions: {casestudy.asyncapi.versions[0]} + + + Who maintains documents: {casestudy.asyncapi.maintainers} + + + Internal users: {casestudy.asyncapi.audience.internal.toString()} + + + External users: {casestudy.asyncapi.audience.external.toString()} + +
+ + How AsyncAPI documents are stored + + + + + + Where maintainers edit AsyncAPI documents + + + + + + What extensions are used + + + + + + How documentation is generated + + + + + + What bindings are used + + + + + + What tools are used + + + + +
+
+ + Schemas + +
+ + Spec: {casestudy.schemas.description} + +
+ + Storage strategy + + + + + + Schema Registry + + + + + + Versioning of schemas + + + + + + Validation of message schemas + + + + + + Additional resources + + + + +
+ +
+
+
+ + Contact points for more details: + + +
+
+
+ ); +} + +export default Index; diff --git a/pages/casestudies/index.js b/pages/casestudies/index.js new file mode 100644 index 000000000000..68cec50047a9 --- /dev/null +++ b/pages/casestudies/index.js @@ -0,0 +1,49 @@ +import GenericLayout from "../../components/layout/GenericLayout"; +import CaseStudyCard from '../../components/CaseStudyCard'; +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"; + +export default function casestudies() { + const description = + "Learn about different case studies based on AsyncAPI spec and related tools."; + const image = "/img/social/meetings.png"; + const title = "Case Studies"; + + return ( + + +
+
+
+ + {title} + + + The best way to learn how to use AsyncAPI is not only through documentation that usually is focused on recommendations and best practices. + It is also good to confront with real-life case studies that explain how people really use AsyncAPI and what are their flows. + + + Feel free to submit your case study. We have a template for you. For more details + + read our FAQ + . + +
+
+
+ +
+
+
+ ); +} + + diff --git a/public/img/casestudies/adeo/architecture.webp b/public/img/casestudies/adeo/architecture.webp new file mode 100644 index 000000000000..5dec80035a51 Binary files /dev/null and b/public/img/casestudies/adeo/architecture.webp differ diff --git a/public/img/casestudies/adeo/logo.svg b/public/img/casestudies/adeo/logo.svg new file mode 100644 index 000000000000..7c45b428b3ed --- /dev/null +++ b/public/img/casestudies/adeo/logo.svg @@ -0,0 +1,65 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/public/resources/casestudies/adeo/CostingRequestPayload.avsc b/public/resources/casestudies/adeo/CostingRequestPayload.avsc new file mode 100644 index 000000000000..612337b907a3 --- /dev/null +++ b/public/resources/casestudies/adeo/CostingRequestPayload.avsc @@ -0,0 +1,126 @@ +{ + "namespace": "com.adeo.casestudy.costingrequest", + "type": "record", + "name": "CostingRequestPayload", + "version": "1.1.0", + "fields": [ + { + "name": "ProductId", + "type": { + "type": "string", + "avro.java.string": "String" + }, + "doc": "Product identifier." + }, + { + "name": "ShortProductDescription", + "type": [ + "null", + { + "type": "string", + "avro.java.string": "String" + } + ], + "doc": "A short product description.", + "example": "BOTTLE RACK, STACKABLE, 2 TIER, 10 BOTTLES" + }, + { + "name": "SupplierCode", + "type": { + "type": "string", + "avro.java.string": "String" + }, + "doc": "Supplier code, used to get parameter values that depend on the supplier.", + "example": "12345678" + }, + { + "name": "SupplierPrice", + "type": "float", + "doc": "Product price (purchasing price)." + }, + { + "name": "Unit", + "doc": "Unit characteristics", + "type": { + "name": "UnitItem", + "namespace": "com.adeo.casestudy.costingrequest", + "type": "record", + "fields": [ + { + "name": "Length", + "type": "float", + "example": 1.11, + "exclusiveMinimum": 0 + }, + { + "name": "Width", + "type": "float", + "example": 1.11, + "exclusiveMinimum": 0 + }, + { + "name": "Height", + "type": "float", + "example": 1.11, + "exclusiveMinimum": 0 + }, + { + "name": "WeightGross", + "type": "float", + "example": 6.68, + "exclusiveMinimum": 0 + }, + { + "name": "WeightNet", + "type": "float", + "example": 6.68, + "exclusiveMinimum": 0, + "doc": "The unit of net weight is the kilogram" + } + ] + } + }, + { + "name": "BusInputs", + "type": { + "type": "array", + "doc": "Business units specific data required to deduce the right BU context.", + "minItems": 1, + "items": { + "name": "CostingRequestBUItem", + "namespace": "com.adeo.casestudy.costingrequest", + "type": "record", + "fields": [ + { + "name": "ClientCode", + "type": { + "type": "string", + "avro.java.string": "String" + }, + "doc": "The client (Business Unit) code.", + "example": "1" + }, + { + "name": "ContainerType", + "type": [ + "null", + { + "type": "enum", + "namespace": "com.adeo.casestudy.model", + "name": "ContainerTypeItems", + "doc": "Container selected for transportation. Required to determinate parameter values that rely on transportation. **Will be deleted (because deduced) in future versions**", + "symbols": [ + "FT20", + "FT40", + "FT40HC", + "TRUCK" + ] + } + ] + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/public/resources/casestudies/adeo/CostingResponseKey.avsc b/public/resources/casestudies/adeo/CostingResponseKey.avsc new file mode 100644 index 000000000000..d1b6c628b0c6 --- /dev/null +++ b/public/resources/casestudies/adeo/CostingResponseKey.avsc @@ -0,0 +1,11 @@ +{ + "namespace": "com.adeo.casestudy.costingresponse", + "type": "record", + "name": "CostingResponseKey", + "version": 1, + "fields": [ + {"name": "RequesterCode", "type": { "type": "string", "avro.java.string": "String" }, "doc": "Requester code"}, + {"name": "ClientCode", "type": { "type": "string", "avro.java.string": "String" }, "doc": "The client (Business Unit) code the response is for.", "example": "1"}, + {"name": "ProductId", "type": { "type": "string", "avro.java.string": "String" }, "doc": "Product Id.", "example": "12345678"} + ] +} diff --git a/public/resources/casestudies/adeo/CostingResponsePayload.avsc b/public/resources/casestudies/adeo/CostingResponsePayload.avsc new file mode 100644 index 000000000000..64ea47b2576b --- /dev/null +++ b/public/resources/casestudies/adeo/CostingResponsePayload.avsc @@ -0,0 +1,79 @@ +{ + "namespace": "com.adeo.casestudy.costingresponse", + "type": "record", + "name": "CostingResponsePayload", + "version": 1, + "fields": [ + {"name": "CostingResult", "type": ["null", + { + "name": "CostingResultItem", + "namespace": "com.adeo.casestudy.costingresponse", + "type": "record", + "doc": "Costing result data", + "fields" : [ + {"name": "CalculationPrice", "type": "float", "doc": "The calculated price.", "example": 1.136}, + {"name": "CalculationCurrency", "doc": "The currency for the calculation price.", "type": + { + "name": "CalculationCurrencyItems", + "namespace": "com.adeo.casestudy.costingresponse", + "type": "enum", + "symbols": ["USD", "EUR", "CNY"], + "default": "EUR" + } + }, + {"name": "CalculationDetails", "type": { + "name": "CostingResultDetailsItems", + "namespace": "com.adeo.casestudy.costingresponse", + "type": "array", + "items": + { + "name": "CostingResultDetailsItem", + "namespace": "com.adeo.casestudy.costingresponse", + "type": "record", + "doc": "Cost Component used during the calculation", + "fields": [ + {"name": "Code", "type": {"type": "string", "avro.java.string": "String"}, "doc": "The Cost Component Code.", "example": "CODE1"}, + {"name": "Formula", "type": {"type": "string", "avro.java.string": "String"}, "doc": "The Cost Component Formula.", "example": "PARAM1 / PARAM2"}, + {"name": "Value", "type": "float", "doc": "Cost component calculated value.", "example": 1.145} + ] + } + } + } + ] + }] + }, + {"name": "CostingErrors", "doc": "Technical or functional errors occurred during calculation", "type": ["null", { + "type": "array", + "name": "CostingErrorItems", + "namespace": "com.adeo.casestudy.costingresponse", + "items": + { + "name": "CostingErrorItem", + "namespace": "com.adeo.casestudy.costingresponse", + "type": "record", + "doc": "Costing errors data", + "fields": [ + {"name": "Type", "type": + { + "name": "CostingErrorTypeItems", + "namespace": "com.adeo.casestudy.costingresponse", + "type": "enum", + "symbols": ["TECHNICAL", "FUNCTIONAL"], + "default": "FUNCTIONAL" + } + }, + { + "name" : "Code", + "type" : { + "type" : "string", + "avro.java.string" : "String" + }, + "doc" : "Error codification" + }, + {"name": "Step", "type": {"type": "string", "avro.java.string": "String"}, "doc": "Costing step where the error occurred"}, + {"name": "Description", "type": {"type": "string", "avro.java.string": "String"}, "doc": "Error description"} + ]} + }] + } + ] +} diff --git a/public/resources/casestudies/adeo/asyncapi.yaml b/public/resources/casestudies/adeo/asyncapi.yaml new file mode 100644 index 000000000000..7779478c8b8c --- /dev/null +++ b/public/resources/casestudies/adeo/asyncapi.yaml @@ -0,0 +1,303 @@ +asyncapi: 2.4.0 +info: + title: Adeo AsyncAPI Case Study + version: "%REPLACED_BY_MAVEN%" + description: > + This Adeo specification illustrates how ADEO uses AsyncAPI to document some of their exchanges. + contact: + name: AsyncAPI Community + email: case-study@asyncapi.com +servers: + production: + url: "prod.url:9092" + protocol: kafka + description: Kafka PRODUCTION cluster + security: + - sasl-ssl: [] + bindings: + kafka: + schema.registry.url: >- + https://schema-registry.prod.url/ + staging: + url: "staging.url:9092" + protocol: kafka + description: Kafka STAGING cluster for `uat` and `preprod` environments + security: + - sasl-ssl: [] + bindings: + kafka: + schema.registry.url: >- + https://schema-registry.staging.url/ + dev: + url: "dev.url:9092" + protocol: kafka + description: Kafka DEV cluster for `dev` and `sit` environments + security: + - sasl-ssl: [] + bindings: + kafka: + schema.registry.url: >- + https://schema-registry.dev.url/ +tags: + - name: costing + description: "Costing channels, used by Costing clients." +channels: + "adeo-{env}-case-study-COSTING-REQUEST-{version}": + description: > + Use this topic to do a Costing Request to Costing product. + We use the + [**RecordNameStrategy**](https://docs.confluent.io/platform/current/schema-registry/serdes-develop/index.html#subject-name-strategy) + to infer the messages schema. + You have to define `value.subject.name.strategy` to + `io.confluent.kafka.serializers.subject.RecordNameStrategy` in your + producer to use the schema we manage. + The schema below illustrates how Costing Request messages are + handled. + ![](https://user-images.githubusercontent.com/5501911/188920831-689cec5f-8dc3-460b-8794-0b54ec8b0ac8.png) + parameters: + env: + $ref: "#/components/parameters/Env" + version: + $ref: "#/components/parameters/Version" + bindings: + kafka: + replicas: 3 + partitions: 3 + cleanup.policy: delete + retention.ms: 7 days + publish: + operationId: requestCosting + summary: | + [COSTING] Request one or more Costing calculation for any product + description: > + You can try a costing request using our [Conduktor producer + template](https://conduktor.url) + tags: + - name: costing + message: + oneOf: + - $ref: "#/components/messages/costingRequestV1" + bindings: + kafka: + groupId: + type: string + description: > + The groupId must be prefixed by your `svc` account, deliver by the + Adeo Kafka team. + This `svc` must have the write access to the topic. + value.subject.name.strategy: + type: string + description: > + We use the RecordNameStrategy to infer the messages schema. + Use + `value.subject.name.strategy=io.confluent.kafka.serializers.subject.RecordNameStrategy` + in your producer configuration. + "adeo-{env}-case-study-COSTING-RESPONSE-{version}": + description: > + This topic is used to REPLY Costing Requests and is targeted by the + `REPLY_TOPIC` header. + **You must grant PUBLISH access to our `svc-ccr-app` service account.**. + We use the + [**RecordNameStrategy**](https://docs.confluent.io/platform/current/schema-registry/serdes-develop/index.html#subject-name-strategy) + to infer the messages schema. + You have to define `key.subject.name.strategy` and + `value.subject.name.strategy` to + `io.confluent.kafka.serializers.subject.RecordNameStrategy` in your + consumer. + The schema below illustrates how Costing Response messages are + handled. + ![](https://user-images.githubusercontent.com/5501911/188920831-689cec5f-8dc3-460b-8794-0b54ec8b0ac8.png) + parameters: + env: + $ref: "#/components/parameters/Env" + version: + $ref: "#/components/parameters/Version" + bindings: + kafka: + groupId: + type: string + description: > + The groupId must be prefixed by your `svc` account, deliver by the + Adeo Kafka team. + This `svc` must have the read access to the topic. + key.subject.name.strategy: + type: string + description: > + We use the RecordNameStrategy to infer the messages schema. + Use + `key.subject.name.strategy=io.confluent.kafka.serializers.subject.RecordNameStrategy` + in your consumer configuration. + value.subject.name.strategy: + type: string + description: > + We use the RecordNameStrategy to infer the messages schema. + Use + `value.subject.name.strategy=io.confluent.kafka.serializers.subject.RecordNameStrategy` + in your consumer configuration. + subscribe: + operationId: getCostingResponse + summary: > + [COSTING] Get the costing responses matching an initial Costing + Request. + tags: + - name: costing + message: + $ref: "#/components/messages/costingResponse" +components: + correlationIds: + costingCorrelationId: + description: > + This correlation ID is used for message tracing and messages + correlation. + This correlation ID is generated at runtime based on the `REQUEST_ID` + and sent to the RESPONSE message. + location: $message.header#/REQUEST_ID + messages: + costingRequestV1: + name: CostingRequestV1 + title: Costing Request V1 + summary: Costing Request V1 inputs. + tags: + - name: costing + schemaFormat: application/vnd.apache.avro;version=1.9.0 + correlationId: + $ref: "#/components/correlationIds/costingCorrelationId" + headers: + type: object + required: + - REQUESTER_ID + - REQUESTER_CODE + - REQUEST_ID + - REPLY_TOPIC + properties: + REQUEST_ID: + $ref: "#/components/schemas/RequestId" + REPLY_TOPIC: + $ref: "#/components/schemas/ReplyTopic" + REQUESTER_ID: + $ref: "#/components/schemas/RequesterId" + REQUESTER_CODE: + $ref: "#/components/schemas/RequesterCode" + payload: + $ref: "https://deploy-preview-921--asyncapi-website.netlify.app/resources/casestudies/adeo/CostingRequestPayload.avsc" + costingResponse: + name: CostingResponse + title: Costing Response + summary: Costing Response ouputs. + tags: + - name: costing + description: > + Please refer to the `CostingResponseKey.avsc` schema, available on [our + github + project](https://github.url/). + schemaFormat: application/vnd.apache.avro;version=1.9.0 + correlationId: + $ref: "#/components/correlationIds/costingCorrelationId" + headers: + type: object + properties: + CALCULATION_ID: + $ref: "#/components/schemas/MessageId" + CORRELATION_ID: + $ref: "#/components/schemas/CorrelationId" + REQUEST_TIMESTAMP: + type: string + format: date-time + description: Timestamp of the costing request + CALCULATION_TIMESTAMP: + type: string + format: date-time + description: Technical timestamp for the costing calculation + bindings: + kafka: + key: + $ref: "https://deploy-preview-921--asyncapi-website.netlify.app/resources/casestudies/adeo/CostingResponseKey.avsc" + payload: + $ref: "https://deploy-preview-921--asyncapi-website.netlify.app/resources/casestudies/adeo/CostingResponsePayload.avsc" + schemas: + RequesterId: + type: string + description: The Costing requester service account used to produce costing request. + example: svc-ecollect-app + RequesterCode: + type: string + description: >- + The Costing requester code (generally the BU Code). The requester code + is useful to get the dedicated context (tenant). + example: 1 + MessageId: + type: string + format: uuid + description: A unique Message ID. + example: 1fa6ef40-8f47-40a8-8cf6-f8607d0066ef + RequestId: + type: string + format: uuid + description: >- + A unique Request ID needed to define a `CORRELATION_ID` for exchanges, + which will be sent back in the Costing Responses. + example: 1fa6ef40-8f47-40a8-8cf6-f8607d0066ef + CorrelationId: + type: string + format: uuid + description: >- + A unique Correlation ID defined from the `REQUEST_ID` or the + `MESSAGE_ID` provided in the Costing Request. + example: 1fa6ef40-8f47-40a8-8cf6-f8607d0066ef + BuCode: + type: string + description: The Business Unit code for which data are applicable. + example: 1 + ReplyTopic: + type: string + description: > + The Kafka topic where to send the Costing Response. This is required for + the [Return Address EIP + pattern](https://www.enterpriseintegrationpatterns.com/patterns/messaging/ReturnAddress.html). + **You must grant WRITE access to our `svc-ccr-app` service account.** + example: adeo-case-study-COSTING-RESPONSE-V1 + ErrorStep: + type: string + description: | + The woker that has thrown the error. + example: EXPOSE_RESULT + ErrorMessage: + type: string + description: | + The error message describing the error. + example: Error message + ErrorCode: + type: string + description: | + The error code. + example: CURRENCY_NOT_FOUND + parameters: + Env: + description: Adeo Kafka Environement for messages publications. + schema: + type: string + enum: + - dev + - sit + - uat1 + - preprod + - prod + Version: + description: the topic version you want to use + schema: + type: string + example: V1 + default: V1 + securitySchemes: + sasl-ssl: + type: plain + x-sasl.jaas.config: >- + org.apache.kafka.common.security.plain.PlainLoginModule required + username="" password=""; + x-security.protocol: SASL_SSL + x-ssl.endpoint.identification.algorithm: https + x-sasl.mechanism: PLAIN + description: > + Use [SASL authentication with SSL + encryption](https://docs.confluent.io/platform/current/security/security_tutorial.html#configure-clients) + to connect to the ADEO Broker. \ No newline at end of file diff --git a/scripts/casestudies/casestudy_template.yml b/scripts/casestudies/casestudy_template.yml new file mode 100644 index 000000000000..e53f58701dce --- /dev/null +++ b/scripts/casestudies/casestudy_template.yml @@ -0,0 +1,64 @@ +id: #Unique id that will be used on website. So in case of id that is "test" people will navigate to /casestudies/test to read about "test" case study. +company: #We need basic information about a company so people know the case study is real and creditable. + name: #Company name. + description: #Shor description of most important things people should know about the company. + customers: #Amount of customers to indicate the impact that the company has. + industry: #Is it retail? software development? put the same value that company has on their LinkedIn page. + revenue: #Specify company earnings to indicate to case study reader how critical online operations are. + website: #Link to main website. + logo: #Link to logo of the company in SVG format. + contact: + #Let us know who we can contact you, some generic email or just a name and link to some social media. We need this to be able to: + #- validate long term if case study is still valid + #- ping you when we know we plan to change some parts of AsyncAPI that you are already using + - name: #Full name of the contact person. + link: #Specify where people can find contact person. +challenges: | + #Describe want challanges company have, that faced them towards AsyncAPI. There is no limit here. Use [CommonMark](https://commonmark.org/). +solution: | + #Describe the solution for the challange and what role AsyncAPI played in it. There is no limit here. Use [CommonMark](https://commonmark.org/) +technical: #We need some more technical information related to case study. + languages: + - #Provide a list of programming lanugages people using AsyncAPI work with. + frameworks: + - #Specify what frameworks they use, maybe Spring in Java or Nest.js in JavaScript. + protocols: + - #What protocols are used by the company in relation to AsyncAPI. + brokers: | + #Provide some details about the broker that is used at the company and what is the setup, size, example cluster size, and a number of topics (in the case of Kafka for example). + testing: | + #Explain how testing of the solution is done. How do you ensure an API works as expected after changes and that users are unaffected? For example, how do you know who will be affected if you stop sending some messages? Provide examples if possible. + architecture: | + #Explain the setup of the EDA architecture. It would be perfect if you could point out what [enterprise integration patterns](https://www.enterpriseintegrationpatterns.com/patterns/messaging) you applied. Provide examples if possible. + codegen: | + #Explain if you use code generation, what you generate and how. Provide examples if possible. +schemas: #It is useful and interesting to learn how teams handle messages schemas. + description: #What spec and version do you use, is it JSON Schema? Avro? What version? + storage: #Where do you store your schemas. + registry: #Are you using schema registry solution? which one? + versioning: #How do you handle versioning of schemas? + validation: #How do you handle events payload validation against schemas? +asyncapi: #More specific details about AsyncAPI itself and how is it used. + usecase: | + #Even though this section might be a kind of replication of what was explained in challenges/solution, please describe in short what specific use case you found for AsyncAPI and how you implement it. + versions: + - #Specify a list of versions of AsyncAPI that you use. It can be a list, some teams might use different versions. + storage: | + #Describe where you store AsyncAPI files and who maintains them on daily basis. + editing: | + #Specify how you edit AsyncAPI files and where you edit them. Be very specific on IDEs and plugin names if used. + maintainers: | + #Share information; who is the primary maintainer of AsyncAPI documents? Developers? Tech writers? Product owners? + audience: #Specify if AsyncAPI audience is internal or external or both. + internal: true + external: false + extensions: | + #Explain if you use spec extension and how. Provide examples if possible. + documentation: | + #Explain processes around documentation generated with AsyncAPI. How do you do it? What AsyncAPI fields are critical for you? Provide examples if possible. + bindings: | + #Specify what bindings are used by their name and provide description on what level you use bindings. Provide examples if possible. + tools: | + #Specify what AsyncAPI tools you use, as detailed as possible. + fullExample: #Should be url to full example of the case study. So later in the UI we can show it as "https://studio.asyncapi.com/?url=https://deploy-preview-921--asyncapi-website.netlify.app/resources/casestudies/adeo/asyncapi.yaml" so the example can be previewed in the AsyncAPI Studio easily. +additionalResources: #Provide some additional resources if there are such. Just block of text with links to articles or videos about the case study. \ No newline at end of file diff --git a/scripts/casestudies/index.js b/scripts/casestudies/index.js new file mode 100644 index 000000000000..6a1a1f20e48c --- /dev/null +++ b/scripts/casestudies/index.js @@ -0,0 +1,26 @@ +const { readdir, writeFile, readFile } = require('fs').promises; +const { convertToJson } = require('../utils'); +const { resolve } = require('path'); + +const dirWithCaseStudy = 'config/casestudies'; + +module.exports = async function buildCaseStudiesList() { + let files = await readdir(dirWithCaseStudy); + let caseStudiesList = []; + try { + for (let file of files) { + const caseStudyFileName = [dirWithCaseStudy, file].join('/'); + const caseStudyContent = await readFile(caseStudyFileName, 'utf-8'); + const jsonContent = convertToJson(caseStudyContent); + + caseStudiesList.push(jsonContent); + await writeFile( + resolve(__dirname, '../../config', 'case-studies.json'), + JSON.stringify(caseStudiesList) + ) + } + } catch (err) { + console.log(err); + throw err + } +}; \ No newline at end of file diff --git a/scripts/casestudies/schema.json b/scripts/casestudies/schema.json new file mode 100644 index 000000000000..883cc20b2da2 --- /dev/null +++ b/scripts/casestudies/schema.json @@ -0,0 +1,61 @@ +{ + "id":"adeogroup", + "company":{ + "name":"Adeo Group", + "description":"Adeo owns different brands in retail industry focused on home improvement and DIY markets, like Leroy Merlin.", + "customers":"500M", + "industry":"Retail", + "revenue":"25.6B EURO turnover, including 768M EURO online.", + "website":"https://www.adeo.com/", + "logo":"/img/casestudies/adeo/logo.svg", + "contact":[ + { + "name":"Ludovic Dussart", + "link":"https://twitter.com/ldussart" + } + ] + }, + "challenges":"Cost Component Repository product, part of the ADEO tech products, is used to calculate and publish transfer prices between different internal locations on the globe. Different business units use different information systems. It is hard to learn how each business unit share information about their systems, their API and accuracy.", + "solution":"The API is now described with AsyncAPI. AsyncAPI file, stored together with the source code, is used to generate HTML documentation in the same release pipeline for the product. Documentation is exposed as part of the product internally for other company units depending on the API.", + "technical":{ + "languages":[ + "Java" + ], + "frameworks":[ + "Spring" + ], + "protocols":[ + "Kafka" + ], + "brokers":"Kafka with Kafka Connect component. There are 15 production brokers with 47 topics.", + "testing":"For Kafka e2e tests are done with [Zerocode](https://github.com/authorjapps/zerocode). Load tests are handled with [JMeter](https://jmeter.apache.org/) with [kloadgen](https://github.com/corunet/kloadgen) plugin that supports Kafka and Avro.", + "architecture":"The following [enterprise integration patterns](https://www.enterpriseintegrationpatterns.com/patterns/messaging) are applied.", + "codegen":"Java models generation. Avro schemas used as a source." + }, + "schemas":{ + "description":"Avro 1.9", + "storage":"Git repository where source code is. During release they are published to Confluent Schema Registry.", + "registry":"Confluent Schema Registry.", + "versioning":"Versioning is based on git tags. Schema version pushed to Confluent Schema Registry match the git tag version of the product. Every schema has a `version` information, that match with product tag version.", + "validation":"Based on validation using Confluent Schema Registry." + }, + "asyncapi":{ + "usecase":"Document the API of the product so its users know how it works and how to use it. AsyncAPI was selected as the standard that allows you to generate documentation from machine-readable document that describes the API.", + "versions":[ + "2.4.0" + ], + "storage":"Git repository where source code is.", + "editing":"IntelliJ without any special plugins. Sometimes people use AsyncAPI Studio, but not regularly because of lack of support for references to local drive.", + "maintainers":"Developers", + "audience":{ + "internal":false, + "external":false + }, + "extensions":"Extensions are used to describe details about custom security.", + "documentation":"Documentation generated from AsyncAPI is hosted as part of the product on dedicated endpoint using Spring controller.", + "bindings":"All Kafka bindings are used. Server, channel, operation and message bindings.", + "tools":"[AsyncAPI Generator](https://github.com/asyncapi/generator) and [HTML Template](https://github.com/asyncapi/html-template) with parameters like `sidebarOrganization=byTags` and `version`.", + "fullExample":"resources/casestudies/adeo/asyncapi.yaml" + }, + "additionalResources":"Watch [this video presentation about AsyncAPI case study](https://www.youtube.com/watch?v=WwhRbvrf6Rs) from Ludovic Dussart, Ineat & Antoine Delequeuche, Adeo. - better for data interchange" +} \ No newline at end of file diff --git a/scripts/index.js b/scripts/index.js index f5a9c72b8b9f..182a0a62eea9 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -1,5 +1,6 @@ const rssFeed = require('./build-rss'); const buildPostList = require('./build-post-list'); +const buildCaseStudiesList = require('./casestudies'); async function start() { await buildPostList(); @@ -15,6 +16,7 @@ async function start() { 'AsyncAPI Initiative Jobs Board', 'jobs/rss.xml' ); + await buildCaseStudiesList(); } start(); diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index eda730424c7f..02c6c2b580cd 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -3,11 +3,11 @@ const axios = require('axios') const Ajv = require("ajv") const addFormats = require("ajv-formats") const Fuse = require("fuse.js") -const yaml = require('yaml'); const { categoryList } = require("./categorylist") const ajv = new Ajv() addFormats(ajv, ["uri"]) const validate = ajv.compile(schema) +const { convertToJson } = require('../utils'); // Config options set for the Fuse object @@ -108,19 +108,4 @@ async function convertTools(data) { } } return finalToolsObject; -} - -async function convertToJson(contentYAMLorJSON) { - - //Axios handles conversion to JSON by default, if data returned for the server allows it - //So if returned content is not string (not YAML) we just return JSON back - if (typeof contentYAMLorJSON !== "string") return contentYAMLorJSON; - - //in some cases json can be passed here as string as it failed parsing to json because of json related error - //instead of passint it to yaml parser, return same stuff that came in so it fails on JSON Schema validation later - if (contentYAMLorJSON.trimLeft().startsWith('{')) return contentYAMLorJSON - - return yaml.parse(contentYAMLorJSON); -} - -module.exports = { convertTools, createToolObject } +} \ No newline at end of file diff --git a/scripts/utils.js b/scripts/utils.js new file mode 100644 index 000000000000..b869aa421fa5 --- /dev/null +++ b/scripts/utils.js @@ -0,0 +1,16 @@ +const yaml = require('yaml'); + +function convertToJson(contentYAMLorJSON) { + + //Axios handles conversion to JSON by default, if data returned for the server allows it + //So if returned content is not string (not YAML) we just return JSON back + if (typeof contentYAMLorJSON !== "string") return contentYAMLorJSON; + + //in some cases json can be passed here as string as it failed parsing to json because of json related error + //instead of passint it to yaml parser, return same stuff that came in so it fails on JSON Schema validation later + if (contentYAMLorJSON.trimLeft().startsWith('{')) return contentYAMLorJSON + + return yaml.parse(contentYAMLorJSON); + } + + module.exports = { convertToJson } \ No newline at end of file