Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@asyncapi/parser
Advanced tools
@asyncapi/parser is a powerful npm package designed to parse AsyncAPI documents. It allows developers to read, validate, and manipulate AsyncAPI specifications programmatically. This is particularly useful for generating documentation, creating mock servers, and integrating with other tools in the API development lifecycle.
Parsing AsyncAPI Documents
This feature allows you to parse an AsyncAPI document from a JSON string. The parsed document can then be used for further processing or validation.
const { Parser } = require('@asyncapi/parser');
const parser = new Parser();
const asyncapiDocument = `{
"asyncapi": "2.0.0",
"info": {
"title": "Streetlights API",
"version": "1.0.0"
},
"channels": {
"light/measured": {
"description": "Channel for light measurement events",
"subscribe": {
"summary": "Receive light measurement events",
"message": {
"$ref": "#/components/messages/LightMeasured"
}
}
}
},
"components": {
"messages": {
"LightMeasured": {
"payload": {
"type": "object",
"properties": {
"lumens": {
"type": "integer"
}
}
}
}
}
}
}`;
parser.parse(asyncapiDocument)
.then(doc => console.log('Parsed document:', doc))
.catch(err => console.error('Error parsing document:', err));
Validating AsyncAPI Documents
This feature allows you to validate an AsyncAPI document after parsing it. It checks for any schema violations or inconsistencies in the document.
const { Parser } = require('@asyncapi/parser');
const parser = new Parser();
const asyncapiDocument = `{
"asyncapi": "2.0.0",
"info": {
"title": "Streetlights API",
"version": "1.0.0"
},
"channels": {
"light/measured": {
"description": "Channel for light measurement events",
"subscribe": {
"summary": "Receive light measurement events",
"message": {
"$ref": "#/components/messages/LightMeasured"
}
}
}
},
"components": {
"messages": {
"LightMeasured": {
"payload": {
"type": "object",
"properties": {
"lumens": {
"type": "integer"
}
}
}
}
}
}
}`;
parser.parse(asyncapiDocument)
.then(doc => {
const validationErrors = doc.validate();
if (validationErrors.length) {
console.error('Validation errors:', validationErrors);
} else {
console.log('Document is valid');
}
})
.catch(err => console.error('Error parsing document:', err));
Accessing Document Components
This feature allows you to access various components of the parsed AsyncAPI document, such as channels and messages. This is useful for generating documentation or creating mock servers.
const { Parser } = require('@asyncapi/parser');
const parser = new Parser();
const asyncapiDocument = `{
"asyncapi": "2.0.0",
"info": {
"title": "Streetlights API",
"version": "1.0.0"
},
"channels": {
"light/measured": {
"description": "Channel for light measurement events",
"subscribe": {
"summary": "Receive light measurement events",
"message": {
"$ref": "#/components/messages/LightMeasured"
}
}
}
},
"components": {
"messages": {
"LightMeasured": {
"payload": {
"type": "object",
"properties": {
"lumens": {
"type": "integer"
}
}
}
}
}
}
}`;
parser.parse(asyncapiDocument)
.then(doc => {
const channels = doc.channels();
console.log('Channels:', channels);
const messages = doc.components().messages();
console.log('Messages:', messages);
})
.catch(err => console.error('Error parsing document:', err));
swagger-parser is a powerful npm package for parsing, validating, and dereferencing Swagger (OpenAPI) documents. It offers similar functionalities to @asyncapi/parser but is focused on the OpenAPI specification. It is widely used for working with RESTful APIs.
openapi-schema-validator is a package designed to validate OpenAPI 3.0 schemas. While it does not offer parsing capabilities, it provides robust validation features similar to those found in @asyncapi/parser.
openapi-types is a TypeScript library that provides type definitions for OpenAPI specifications. It is useful for developers who want to ensure type safety when working with OpenAPI documents, similar to how @asyncapi/parser provides structure for AsyncAPI documents.
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.
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.
Note Read the migration guide from v1 to v2.
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.
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.
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());
}
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
`);
Head over to asyncapi/avro-schema-parser for more information.
Head over to asyncapi/openapi-schema-parser for more information.
Head over to asyncapi/raml-dt-schema-parser for more information.
import { Parser, fromURL } from '@asyncapi/parser';
const parser = new Parser();
const { document, diagnostics } = await fromURL(parser, 'https://example.com/').parse();
import { Parser, fromFile } from '@asyncapi/parser';
const parser = new Parser();
const { document, diagnostics } = await fromFile(parser, './asyncapi.yaml').parse();
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);
}
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 | Spec 3.x |
---|---|---|---|
2.x | 1.x | ✓ | |
3.x | 2.x | ✓ | ✓ |
✓
Fully supported version.-
The AsyncAPI Spec version has features the Parser-JS can't use but the rest are fully supported.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 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.
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.
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:
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',
]
}
}
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);
In AsyncAPI Initiative we support below custom schema parsers. To install them, run below comamnds:
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
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!
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.
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.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:
Check example.
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.
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/"),
}
}
}
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',
},
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
npm run lint
Read CONTRIBUTING guide.
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
FAQs
JavaScript AsyncAPI parser.
We found that @asyncapi/parser demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.