• Stars
    star
    116
  • Rank 302,773 (Top 6 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created over 5 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

AsyncAPI parser for Javascript (browser-compatible too).

AsyncAPI JavaScript Parser

Use this package to validate and parse AsyncAPI documents β€”either YAML or JSONβ€” in your Node.js or browser application.
Validation is powered by Spectral.
Updated bundle for the browser is always attached to the GitHub Release.

npm npm

Warning
This package doesn't support AsyncAPI 1.x anymore. We recommend to upgrade to the latest AsyncAPI version using the AsyncAPI converter. If you need to convert documents on the fly, you may use the Node.js or Go converters.

Warning
This package has rewrote the Model API (old one) to Intent API. If you still need to use the old API, read the Convert to the old API section.

Installation

npm install @asyncapi/parser
yarn add @asyncapi/parser

The parser by default supports AsyncAPI Schema Format and JSON Schema Format for schemas. For additional formats, check Custom schema parsers section.

Usage

The package exposes the main class Parser, which has two main functions:

  • validate() - function that validates the passed AsyncAPI document. Returns array of all possible errors against the validation conditions.
  • parse() - function that validates the passed AsyncAPI document, and then if it's valid, parses the input. It returns an object that contains:
    • document object, which is an parsed AsyncAPI document with AsyncAPIDocumentInterface API. If the schema is invalid against the validation conditions, the field has undefined value.
    • diagnostics array that contains all possible errors against the validation conditions.
  • registerSchemaParser() - function that registers custom schema parsers. For more info, please check Custom schema parsers section.

Natively Parser class does not contain methods that operate on the source (AsyncAPI document) from a file or URL. However, the package exposes utils that make this possible:

import { fromURL, fromFile } from '@asyncapi/parser';

Check out the examples of using the above mentioned functionalities.

Examples

Example with parsing

import { Parser } from '@asyncapi/parser';
const parser = new Parser();
const { document } = await parser.parse(`
  asyncapi: '2.4.0'
  info:
    title: Example AsyncAPI specification
    version: '0.1.0'
  channels:
    example-channel:
      subscribe:
        message:
          payload:
            type: object
            properties:
              exampleField:
                type: string
              exampleNumber:
                type: number
              exampleDate:
                type: string
                format: date-time
`);

if (document) {
  // => Example AsyncAPI specification
  console.log(document.info().title());
}

Example with validation

import { Parser } from '@asyncapi/parser';

const parser = new Parser();

// One of the diagnostics will contain an error regarding an unsupported version of AsyncAPI (2.1.37)
const diagnostics = await parser.validate(`
  asyncapi: '2.1.37'
  info:
    title: Example AsyncAPI specification
    version: '0.1.0'
  channels:
    example-channel:
      subscribe:
        message:
          payload:
            type: object
            properties:
              exampleField:
                type: string
              exampleNumber:
                type: number
              exampleDate:
                type: string
                format: date-time
`);

Example using Avro schemas

Head over to asyncapi/avro-schema-parser for more information.

Example using OpenAPI schemas

Head over to asyncapi/openapi-schema-parser for more information.

Example using RAML data types

Head over to asyncapi/raml-dt-schema-parser for more information.

Example with performing actions on HTTP source

import { Parser, fromURL } from '@asyncapi/parser';

const parser = new Parser();

const { document, diagnostics } = await fromURL(parser, 'https://example.com/').parse();

Example with performing actions on file source

import { Parser, fromFile } from '@asyncapi/parser';

const parser = new Parser();

const { document, diagnostics } = await fromFile(parser, './asyncapi.yaml').parse();

Example with stringify and unstringify parsed document

import { Parser, stringify, unstringify } from '@asyncapi/parser';

const parser = new Parser();

const { document } = await parser.parse(`
  asyncapi: '2.4.0'
  info:
    title: Example AsyncAPI specification
    version: '0.1.0'
  channels:
    example-channel:
      subscribe:
        message:
          payload:
            type: object
            properties:
              exampleField:
                type: string
              exampleNumber:
                type: number
              exampleDate:
                type: string
                format: date-time
`);

if (document) {
  // stringify function returns string type
  const stringifiedDocument = stringify(document);
  // unstringify function returns new AsyncAPIDocument instance
  const unstringifiedDocument = unstringify(stringifiedDocument);
}

API documentation

Parser-JS API implements a global API definition for all AsyncAPI parser implementations known as the Parser-API. This API is designed having in mind developer experience and resiliency to breaking changes.

The following table shows a compatibility matrix between this parser, and the Parser-API, as well as the AsyncAPI spec version supported by each release of this parser.

Parser-JS Parser-API Spec 2.x
2.x 1.x βœ“
  • βœ“ Fully supported version.
  • - The AsyncAPI Spec version has features the Parser-JS can't use but the rest are fully supported.
  • Empty means not supported version.

Additionally to all the methods declared in the Parser-API, this parser might introduce some helper functions like:

  • json() which returns the JSON object of the given object. It is possible to pass as an argument the name of a field in an object and retrieve corresponding value.
  • jsonPath() which returns the JSON Path of the given object.
  • meta() which returns the metadata of a given object, like a parsed AsyncAPI Document.

Spectral rulesets

Spectral powers the validation of AsyncAPI documents within ParserJS. For this reason, it is possible to use your rulesets/rules or overwrite existing ones, passing the ruleset option to the Parser instance:

import { Parser, stringify, unstringify } from '@asyncapi/parser';
const parser = new Parser({
  ruleset: {
    extends: [],
    rules: {
      'asyncapi-defaultContentType': 'off',
      'asyncapi-termsOfService': {
        description: 'Info "termsOfService" should be present and non-empty string.',
        recommended: true,
        given: '$',
        then: {
          field: 'info.termsOfService',
          function: 'truthy',
        },
      },
    }
  }
});
// The returned diagnostics object will include `asyncapi-termsOfService` diagnostic with `warning` (`recommended: true`) severity because `$.info.termsOfService` is not defined in the following AsyncAPI document.
// On the other hand, since we turned it off, we won't see the diagnostics related to the `defaultContentType` field.
const diagnostics = await parser.validate(`
  asyncapi: '2.0.0'
  info:
    title: Example AsyncAPI specification
    version: '0.1.0'
  channels: {}
`);

ParserJS has some built-in Spectral rulesets that validate AsyncAPI documents and inform on good practices.

Using in the browser/SPA applications

The package contains a built-in version of the parser. To use it, you need to import the parser into the HTML file as below:

<script src="https://unpkg.com/@asyncapi/parser@latest/browser/index.js"></script>

<script>
  const parser = new window.AsyncAPIParser();
  const { document, diagnostics } = parser.parse(...);
</script>

Or, if you want to use the parser in a JS SPA-type application where you have a predefined bundler configuration that is difficult to change (e.g. you use create-react-app) then you can import the parser as below:

import Parser from '@asyncapi/parser/browser';

const parser = new Parser();
const { document, diagnostics } = parser.parse(...);

Note
Using the above code, we import the entire bundled parser into application. This may result in a duplicate code in the final application bundle, only if the application uses the same dependencies what the parser. If, on the other hand, you want to have the smallest bundle as possible, we recommend using the following import and properly configure bundler.

Otherwise, if your application is bundled via bundlers like webpack and you can configure it, you can import the parser like a regular package:

import { Parser } from '@asyncapi/parser';

const parser = new Parser();
const { document, diagnostics } = parser.parse(...);

Note
The package uses some native NodeJS modules underneath. If you are building a front-end application you can find more information about the correct configuration for Webpack here.

In case you just want to check out the latest bundle.js without installing the package, we publish one on each GitHub release. You can find it under this link to the latest release.

Custom schema parsers

AsyncAPI doesn't enforce one schema format. The payload of the messages can be described with OpenAPI (3.0.0), Avro, etc. This parser by default parses only AsyncAPI Schema Format (superset of JSON Schema Format). We can extend it by creating a custom parser and registering it within the parser:

  1. Create custom parser module that exports three functions:

    • validate - function that validates (its syntax) used schema.
    • parse - function that parses the given schema to the AsyncAPI Schema Format.
    • getMimeTypes - function that returns the list of mime types that will be used as the schemaFormat property to determine the mime type of a given schema.

    Example:

    export default {
      validate(input) { ... },
      parse(input) { ... },
      getMimeTypes() {
        return [
          'application/vnd.custom.type;version=1.0.0',
          'application/vnd.custom.type+json;version=1.0.0',
        ]
      }
    }
  2. Before parsing/validating an AsyncAPI document with a parser, register the additional custom schema parser:

    import { Parser } from '@asyncapi/parser';
    import myCustomSchemaParser from './my-custom-schema-parser';
    
    const parser = new Parser();
    parser.registerSchemaParser(myCustomSchemaParser);

Official supported custom schema parsers

In AsyncAPI Initiative we support below custom schema parsers. To install them, run below comamnds:

  • Avro schema:

    npm install @asyncapi/avro-schema-parser
    yarn add @asyncapi/avro-schema-parser
  • OpenAPI (3.0.0) Schema Object:

    npm install @asyncapi/openapi-schema-parser
    yarn add @asyncapi/openapi-schema-parser
  • RAML data type:

    npm install @asyncapi/raml-dt-schema-parser
    yarn add @asyncapi/raml-dt-schema-parser

    Note
    That custom parser works only in the NodeJS environment. Do not use it in browser applications!

Custom extensions

The parser uses custom extensions to define additional information about the spec. Each has a different purpose but all of them are there to make it much easier to work with the AsyncAPI document. These extensions are prefixed with x-parser-. The following extensions are used:

  • x-parser-spec-parsed is used to specify if the AsyncAPI document is already parsed by the parser. Property x-parser-spec-parsed is added to the root of the document with the true value.
  • x-parser-api-version is used to specify which version of the Parser-API the parsed AsyncAPI document uses. Property x-parser-api-version is added to the root of the document with the 1 value if the parsed document uses Parser-API in the v1 version or 0 if document uses old parser-js API.
  • x-parser-message-name is used to specify the name of the message if it is not provided. For messages without names, the parser generates anonymous names. Property x-parser-message-name is added to a message object with a value that follows this pattern: <anonymous-message-${number}>. This value is returned by message.id() (message.uid() in the old API) when regular name property is not present.
  • x-parser-original-payload holds the original payload of the message. You can use different formats for payloads with the AsyncAPI documents and the parser converts them to. For example, it converts payload described with Avro schema to AsyncAPI schema. The original payload is preserved in the extension.
  • x-parser-circular.

In addition, the convertToOldAPI() function which converts new API to an old one adds additional extensions:

  • x-parser-message-parsed is used to specify if the message is already parsed by the message parser. Property x-parser-message-parsed is added to the message object with the true value.
  • x-parser-schema-id is used to specify the ID of the schema if it is not provided. For schemas without IDs, the parser generates anonymous names. Property x-parser-schema-id is added to every object of a schema with a value that follows this pattern: <anonymous-schema-${number}>. This value is returned by schema.uid() when regular $id property is not present.
  • x-parser-original-traits is where traits are stored after they are applied on the AsyncAPI document. The reason is because the original traits property is removed.
  • x-parser-original-schema-format holds information about the original schema format of the payload. You can use different schema formats with the AsyncAPI documents and the parser converts them to AsyncAPI schema. This is why different schema format is set, and the original one is preserved in the extension.

Warning
All extensions added by the parser (including all properties) should be retrieved using special functions. Names of extensions and their location may change, and their eventual changes will not be announced.

Circular references

Parser dereferences all circular references by default. In addition, to simplify interactions with the parser, the following is added:

  • x-parser-circular property is added to the root of the AsyncAPI document to indicate that the document contains circular references. In old API the Parser exposes hasCircular() function to check if given AsyncAPI document has circular references.
  • isCircular() function is added to the Schema Model to determine if a given schema is circular with respect to previously occurring schemas in the JSON tree.

Stringify

Converting a parsed document to a string may be necessary when saving the parsed document to a database, or similar situations where you need to parse the document just once and then reuse it, for optimisation cases.

For that, the Parser supports the ability to stringify a parsed AsyncAPI document through the stringify function exposed by package. This method differs from the native JSON.stringify(...json) implementation, in that every reference that occurs (at least twice throughout the document) is converted into a JSON Pointer path with a $ref: prefix:

{
  "foo": "$ref:$.some.path.to.the.bar"
}

To parse a stringified document into an AsyncAPIDocument instance, you must use the unstringify function (also exposed by package). It isn't compatible with the native JSON.parse() method. It replaces the given references pointed by the JSON Pointer path, with an $ref: prefix to the original objects.

A few advantages of this solution:

  • The string remains as small as possible due to the use of JSON Pointers.
  • All references (also circular) are preserved.

Check example.

Convert to the old API

Version 2.0.0 of package introduced a lot of breaking changes, including changing the API of the returned parsed document (parser uses New API). Due to the fact that a large part of the AsyncAPI tooling ecosystem uses a Parser with the old API and rewriting the tool for the new one can be time-consuming and difficult, the package exposes the convertToOldAPI() function to convert new API to old one:

import { Parser, convertToOldAPI } from '@asyncapi/parser';

const parser = new Parser();
const { document } = parser.parse(...);
const oldAsyncAPIDocument = convertToOldAPI(document);

Warning
The old api will be supported only for a certain period of time. The target date for turning off support of the old API is around the end of January 2023.

Notes

Using with Webpack

Versions <5 of Webpack should handle bundling without problems. Due to the fact that Webpack 5 no longer does fallbacks to native NodeJS modules by default we need to install buffer package and add fallbacks:

{
  resolve: {
    fallback: {
      "fs": false,
      "path": false,
      "util": false,
      "buffer": require.resolve("buffer/"),
    }
  }
}

Testing with Jest

Using a Parser in an application that is tested using Jest, there will probably an error like:

Cannot find module 'nimma/legacy' from 'node_modules/@stoplight/spectral-core/dist/runner/runner.js

It's a problem with Jest, which cannot understand NodeJS's package exports. To fix that, should be enabled ESM support in Jest or set an appropriate Jest's moduleNameMapper config:

moduleNameMapper: {
  '^nimma/legacy$': '<rootDir>/node_modules/nimma/dist/legacy/cjs/index.js',
  '^nimma/(.*)': '<rootDir>/node_modules/nimma/dist/cjs/$1',
},

Develop

  1. Make sure you are using Node.js 16 or higher and npm 8 or higher
  2. Write code and tests.
  3. Make sure all tests pass npm test

For Windows environments, some tests might still fail randomly during local development even when you made no changes to the tests. The reason for this from file endings are different than expected and this comes from Git defaulting to an unexpected file ending. If you encounter this issue you can run the following commands to set Git to use the expected one:

git config --global core.autocrlf false
git config --global core.eol lf
  1. Make sure code is well formatted and secure npm run lint

Contributing

Read CONTRIBUTING guide.

Contributors

Thanks goes to these wonderful people (emoji key):

Fran MΓ©ndez
Fran MΓ©ndez

πŸ’¬ πŸ› πŸ’» πŸ“– πŸ€” 🚧 πŸ”Œ πŸ‘€ ⚠️
Lukasz Gornicki
Lukasz Gornicki

πŸ’¬ πŸ› πŸ’» πŸ“– πŸ€” 🚧 πŸ‘€ ⚠️
Jonas Lagoni
Jonas Lagoni

πŸ’¬ πŸ› πŸ’» πŸ€” πŸ‘€
Maciej UrbaΕ„czyk
Maciej UrbaΕ„czyk

πŸ› πŸ’» πŸ‘€
Juan Mellado
Juan Mellado

πŸ’»
James Crowley
James Crowley

πŸ’»
raisel melian
raisel melian

πŸ’»
danielchu
danielchu

πŸš‡ πŸ’»
JΓΌrgen B.
JΓΌrgen B.

πŸ’»
Viacheslav Turovskyi
Viacheslav Turovskyi

⚠️ πŸ’»
Khuda Dad Nomani
Khuda Dad Nomani

πŸ’» πŸ› ⚠️
Aayush Kumar Sahu
Aayush Kumar Sahu

⚠️
Jordan Tucker
Jordan Tucker

⚠️ πŸ’»
vishesh13byte
vishesh13byte

⚠️
Elakya
Elakya

πŸ’»
Dominik Schwank
Dominik Schwank

πŸ› πŸ’»
Ruchi Pakhle
Ruchi Pakhle

πŸ“–

This project follows the all-contributors specification. Contributions of any kind welcome!

More Repositories

1

spec

The AsyncAPI specification allows you to create machine-readable definitions of your asynchronous APIs.
JavaScript
4,133
star
2

generator

Use your AsyncAPI definition to generate literally anything. Markdown documentation, Node.js code, HTML documentation, anything!
JavaScript
758
star
3

website

AsyncAPI specification website
TypeScript
441
star
4

modelina

A library for generating typed models based on inputs such as AsyncAPI, OpenAPI, and JSON Schema documents with high customization
TypeScript
295
star
5

cli

CLI to work with your AsyncAPI files. You can validate them and in the future use a generator and even bootstrap a new file. Contributions are welcomed!
TypeScript
184
star
6

asyncapi-react

React component for rendering documentation from your specification in real-time in the browser. It also provides a WebComponent and bundle for Angular and Vue
TypeScript
174
star
7

studio

Visually design your AsyncAPI files and event-driven architecture.
TypeScript
162
star
8

saunter

Saunter is a code-first AsyncAPI documentation generator for dotnet.
C#
145
star
9

community

AsyncAPI community-related stuff.
96
star
10

glee

Glee β€” The AsyncAPI framework that will make you smile again :)
TypeScript
88
star
11

bindings

AsyncAPI bindings specifications
71
star
12

java-spring-template

Java Spring template for the AsyncAPI Generator
Java
66
star
13

jasyncapi

/jay-sync-api/ is a Java code-first tool for AsyncAPI specification
Kotlin
66
star
14

html-template

HTML template for AsyncAPI Generator. Use it to generate a static docs. It is using AsyncAPI React component under the hood.
JavaScript
63
star
15

parser-go

It parses AsyncAPI documents.
Go
55
star
16

spec-json-schemas

AsyncAPI schema versions
JavaScript
52
star
17

github-action-for-cli

GitHub Action with generator, validator, converter and others - all in one for your AsyncAPI documents with AsyncAPI CLI as backbone
Shell
46
star
18

go-watermill-template

Go template for the AsyncAPI Generator using Watermill module
JavaScript
46
star
19

nodejs-template

This template generates a server using your AsyncAPI document. It supports multiple different protocols, like Kafka or MQTT. It is designed in the way that generated code is a library and with it's API you can start the server, send messages or register a middleware for listening incoming messages. Runtime message validation included.
JavaScript
39
star
20

java-spring-cloud-stream-template

Java Spring Cloud Stream template for the AsyncAPI Generator
JavaScript
31
star
21

avro-schema-parser

An AsyncAPI schema parser for Avro 1.x schemas.
TypeScript
31
star
22

bundler

Combine multiple AsyncAPI specification files into one.
TypeScript
30
star
23

.github

Location of all reusable community health files
29
star
24

vs-asyncapi-preview

VSCode AsyncAPI Preview Extension
TypeScript
28
star
25

server-api

Server API providing official AsyncAPI tools
TypeScript
26
star
26

markdown-template

Markdown template for the AsyncAPI Generator
JavaScript
26
star
27

diff

Diff is a library that compares two AsyncAPI Documents and provides information about the differences by pointing out explicitly information like breaking changes.
TypeScript
26
star
28

python-paho-template

Python Paho template for the AsyncAPI generator
JavaScript
25
star
29

nodejs-ws-template

Node.js WebSockets template for the AsyncAPI Generator. It showcases how from a single AsyncAPI document you can generate a server and a client at the same time.
JavaScript
23
star
30

conference-website

Website for the AsyncAPI online conference
JavaScript
22
star
31

ts-nats-template

Node.js/Typescript template for NATS
JavaScript
21
star
32

converter-go

Convert AsyncAPI documents from older to newer versions with Golang
Go
20
star
33

generator-react-sdk

Generator React SDK enabling the AsyncAPI generator to support React as the rendering engine for templates.
TypeScript
19
star
34

dotnet-nats-template

.NET template for NATS
JavaScript
18
star
35

converter-js

Convert to or migrate between AsyncAPI versions with the converter
TypeScript
18
star
36

template-for-generator-templates

This is a GitHub repository template for generator templates to make it much easier to start writing your own generator template.
JavaScript
18
star
37

simulator

Asynchronous traffic simulation application using async-api
TypeScript
16
star
38

EDAVisualiser

View your system, events, applications through different perspectives
TypeScript
15
star
39

optimizer

AsyncAPI offers many different ways to reuse certain parts of the document like messages or schemas definitions or references to external files, not to even mention the traits. There is a need for a tool that can be plugged into any workflows and optimize documents that are generated from code, but not only.
TypeScript
14
star
40

tck

(WIP) Test Compatibility Suite for AsyncAPI
Java
13
star
41

chatbot

The project's aim is to develop a chatbot that can help people create spec documents without knowing the specification.To get started with, the bot will consume the spec, JSON schema and serves the user as an expert. So based on a set of questions and answers it will generate an AsyncApi spec document according to the use cases.
JavaScript
12
star
42

openapi-schema-parser

An AsyncAPI schema parser for OpenAPI 3.0.x and Swagger 2.x schemas.
TypeScript
12
star
43

extensions-catalog

Catalog of extensions for AsyncAPI specification
11
star
44

shape-up-process

This repo contains pitches and the current cycle bets. More info about the Shape Up process: https://basecamp.com/shapeup
JavaScript
11
star
45

java-template

Java template for the AsyncAPI Generator
JavaScript
10
star
46

jasyncapi-idea-plugin

/jay-sync-api/-idea-plugin is a IDEA plugin for AsyncAPI specification
Kotlin
10
star
47

dotnet-rabbitmq-template

This template is for generating a .NET C# wrapper for the RabbitMQ client based on your AsyncAPI document.
JavaScript
10
star
48

brand

AsyncAPI brand guidelines and strategy
8
star
49

parser-api

Global API definition for all AsyncAPI Parser implementations.
8
star
50

problem

Library that implements the Problem interface. Reference https://www.rfc-editor.org/rfc/rfc7807
TypeScript
7
star
51

php-template

PHP Template for AsyncAPI generator
PHP
7
star
52

training

All about trainings, workshops, courses, etc.
6
star
53

raml-dt-schema-parser

AsyncAPI schema parser for RAML data types
TypeScript
5
star
54

enterprise-patterns

Enterprise patterns using AsyncAPI
4
star
55

protobuf-schema-parser

Schema parser for Protobuf compatible with AsyncAPI JS Parser
TypeScript
4
star
56

template-for-go-projects

This is a repository template for golang projects
Makefile
2
star
57

generator-filters

Library with reusable generator filters that you can use in your templates
JavaScript
2
star
58

generator-hooks

Library with reusable generator hooks that you can use in your templates
JavaScript
1
star