diff --git a/package-lock.json b/package-lock.json index 7157c91b06..602b8f51b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6936,6 +6936,10 @@ "resolved": "packages/apidom-parser-adapter-asyncapi-json-2", "link": true }, + "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-3": { + "resolved": "packages/apidom-parser-adapter-asyncapi-json-3", + "link": true + }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": { "resolved": "packages/apidom-parser-adapter-asyncapi-yaml-2", "link": true @@ -25988,6 +25992,7 @@ "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^1.0.0-rc.3", + "@swagger-api/apidom-parser-adapter-asyncapi-json-3": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-asyncapi-yaml-3": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-json": "^1.0.0-rc.3", @@ -26076,7 +26081,7 @@ }, "packages/apidom-ns-asyncapi-3": { "name": "@swagger-api/apidom-ns-asyncapi-3", - "version": "1.0.0-beta.0", + "version": "1.0.0-rc.3", "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.26.10", @@ -26292,6 +26297,20 @@ "ramda-adjunct": "^5.0.0" } }, + "packages/apidom-parser-adapter-asyncapi-json-3": { + "name": "@swagger-api/apidom-parser-adapter-asyncapi-json-3", + "version": "1.0.0-rc.3", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime-corejs3": "^7.26.10", + "@swagger-api/apidom-core": "^1.0.0-rc.3", + "@swagger-api/apidom-ns-asyncapi-3": "^1.0.0-rc.3", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-rc.3", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" + } + }, "packages/apidom-parser-adapter-asyncapi-yaml-2": { "name": "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2", "version": "1.0.0-rc.3", @@ -26313,7 +26332,7 @@ "dependencies": { "@babel/runtime-corejs3": "^7.26.10", "@swagger-api/apidom-core": "^1.0.0-rc.3", - "@swagger-api/apidom-ns-asyncapi-3": "1.0.0-beta.0", + "@swagger-api/apidom-ns-asyncapi-3": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-rc.3", "@types/ramda": "~0.30.0", "ramda": "~0.30.0", diff --git a/packages/apidom-ls/package.json b/packages/apidom-ls/package.json index 933003d08d..6574fa24b4 100644 --- a/packages/apidom-ls/package.json +++ b/packages/apidom-ls/package.json @@ -106,6 +106,7 @@ "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^1.0.0-rc.3", + "@swagger-api/apidom-parser-adapter-asyncapi-json-3": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-asyncapi-yaml-3": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-json": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-openapi-json-2": "^1.0.0-rc.3", diff --git a/packages/apidom-ls/src/utils/utils.ts b/packages/apidom-ls/src/utils/utils.ts index ecdce4c9c2..da916e4599 100644 --- a/packages/apidom-ls/src/utils/utils.ts +++ b/packages/apidom-ls/src/utils/utils.ts @@ -6,6 +6,7 @@ import * as openapi31xAdapterJson from '@swagger-api/apidom-parser-adapter-opena import * as openapi31xAdapterYaml from '@swagger-api/apidom-parser-adapter-openapi-yaml-3-1'; import * as asyncapi2AdapterJson from '@swagger-api/apidom-parser-adapter-asyncapi-json-2'; import * as asyncapi2AdapterYaml from '@swagger-api/apidom-parser-adapter-asyncapi-yaml-2'; +import * as asyncapi3AdapterJson from '@swagger-api/apidom-parser-adapter-asyncapi-json-3'; import * as asyncapi3AdapterYaml from '@swagger-api/apidom-parser-adapter-asyncapi-yaml-3'; import * as adsAdapterJson from '@swagger-api/apidom-parser-adapter-api-design-systems-json'; import * as adsAdapterYaml from '@swagger-api/apidom-parser-adapter-api-design-systems-yaml'; @@ -836,7 +837,6 @@ export async function findNamespace( mediaType: asyncapi2AdapterYaml.mediaTypes.findBy(version, 'yaml'), }; } - if (await asyncapi3AdapterYaml.detect(text)) { const asyncapi3YamlMatch = text.match(asyncapi3AdapterYaml.detectionRegExp)!; const groups = asyncapi3YamlMatch.groups!; @@ -850,6 +850,19 @@ export async function findNamespace( }; } + if (await asyncapi3AdapterJson.detect(text)) { + const asyncapi3JsonMatch = text.match(asyncapi3AdapterJson.detectionRegExp)!; + const groups = asyncapi3JsonMatch.groups!; + const version = groups.version_json; + + return { + namespace: 'asyncapi', + version, + format: 'JSON', + mediaType: asyncapi3AdapterJson.mediaTypes.findBy(version, 'json'), + }; + } + if (await openapi2AdapterJson.detect(text)) { const openapi2JsonMatch = text.match(openapi2AdapterJson.detectionRegExp)!; const groups = openapi2JsonMatch.groups!; diff --git a/packages/apidom-ns-asyncapi-3/package.json b/packages/apidom-ns-asyncapi-3/package.json index 25a0abbbb6..8e5d9be2f3 100644 --- a/packages/apidom-ns-asyncapi-3/package.json +++ b/packages/apidom-ns-asyncapi-3/package.json @@ -1,6 +1,6 @@ { "name": "@swagger-api/apidom-ns-asyncapi-3", - "version": "1.0.0-beta.0", + "version": "1.0.0-rc.3", "description": "AsyncAPI 3.x.y namespace for ApiDOM.", "publishConfig": { "access": "public", diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/.eslintignore b/packages/apidom-parser-adapter-asyncapi-json-3/.eslintignore new file mode 100644 index 0000000000..23853b909a --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/.eslintignore @@ -0,0 +1,8 @@ +/**/*.js +/**/*.mjs +/**/*.cjs +/dist +/types +/config +/.nyc_output +/node_modules diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/.gitignore b/packages/apidom-parser-adapter-asyncapi-json-3/.gitignore new file mode 100644 index 0000000000..9b4d60ee63 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/.gitignore @@ -0,0 +1,7 @@ +/src/**/*.mjs +/src/**/*.cjs +/test/**/*.mjs +/dist +/types +/NOTICE +/swagger-api-apidom-parser-adapter-asyncapi-json-3-*.tgz diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/.mocharc.json b/packages/apidom-parser-adapter-asyncapi-json-3/.mocharc.json new file mode 100644 index 0000000000..7e6d84b72e --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/.mocharc.json @@ -0,0 +1,8 @@ +{ + "extensions": ["ts"], + "loader": "ts-node/esm", + "recursive": true, + "spec": "test/**/*.mjs", + "file": ["test/mocha-bootstrap.ts"], + "ignore": ["test/perf/**/*.ts"] +} \ No newline at end of file diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/.npmrc b/packages/apidom-parser-adapter-asyncapi-json-3/.npmrc new file mode 100644 index 0000000000..4b82d2e7bb --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/.npmrc @@ -0,0 +1,2 @@ +save-prefix="=" +save=false diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/CHANGELOG.md b/packages/apidom-parser-adapter-asyncapi-json-3/CHANGELOG.md new file mode 100644 index 0000000000..e9fb6ecf59 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. \ No newline at end of file diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/README.md b/packages/apidom-parser-adapter-asyncapi-json-3/README.md new file mode 100644 index 0000000000..e01533bdf1 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/README.md @@ -0,0 +1,93 @@ +# @swagger-api/apidom-parser-adapter-asyncapi-json-3 + +`@swagger-api/apidom-parser-adapter-asyncapi-json-3` is a parser adapter for following AsyncAPI specification versions defined in [JSON format](https://www.json.org/json-en.html): + +- [AsyncAPI 3.0.0 specification](https://github.com/asyncapi/spec/blob/v3.0.0/spec/asyncapi.md) +- [AsyncAPI 3.0.1 specification](https://github.com/asyncapi/spec/blob/v3.0.1/spec/asyncapi.md) + +Under the hood this adapter uses [@swagger-api/apidom-parser-adapter-json](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-json) +to parse a source string into generic ApiDOM in [base ApiDOM namespace](https://github.com/swagger-api/apidom/tree/main/packages/apidom-core#base-namespace) +which is then refracted with [AsyncApi 3.x.y Refractors](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-asyncapi-3#refractors). + +## Installation + +After [prerequisites](https://github.com/swagger-api/apidom/blob/main/README.md#prerequisites) for installing this package are satisfied, you can install it +via [npm CLI](https://docs.npmjs.com/cli) by running the following command: + +```sh + $ npm install @swagger-api/apidom-parser-adapter-asyncapi-json-3 +``` + +## Parser adapter API + +This parser adapter is fully compatible with parser adapter interface required by [@swagger-api/apidom-parser](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser#mounting-parser-adapters) +and implements all required properties. + +### mediaTypes + +Defines list of media types that this parser adapter recognizes. + +```js +[ + 'application/vnd.aai.asyncapi;version=3.0.0', + 'application/vnd.aai.asyncapi+json;version=3.0.0', + 'application/vnd.aai.asyncapi;version=3.0.1', + 'application/vnd.aai.asyncapi+json;version=3.0.1', +] +``` + +### detect + +[Detection](https://github.com/swagger-api/apidom/blob/main/packages/apidom-parser-adapter-asyncapi-json-3/src/adapter.ts#L18) is based on a regular expression matching required AsyncApi 3.0.0 specification symbols in JSON format. + +### namespace + +This adapter exposes an instance of [AsyncApi 3.x.y ApiDOM namespace](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-asyncapi-3#asyncapi-3xy-namespace). + +### parse + +`parse` function consumes various options as a second argument. Here is a list of these options: + +Option | Type | Default | Description +--- | --- | --- | --- +`specObj` | `Object` | [Specification Object](https://github.com/swagger-api/apidom/blob/main/packages/apidom-ns-asyncapi-3/src/refractor/specification.ts) | This specification object drives the JSON AST transformation to AsyncAPI 3.x ApiDOM namespace. +`sourceMap` | `Boolean` | `false` | Indicate whether to generate source maps. +`refractorOpts` | `Object` | `{}` | Refractor options are [passed to refractors](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-asyncapi-3#refractor-plugins) during refracting phase. + +All unrecognized arbitrary options will be ignored. + +## Usage + +This parser adapter can be used directly or indirectly via [@swagger-api/apidom-parser](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser). + +### Direct usage + +During direct usage you don't need to provide `mediaType` as the `parse` function is already pre-bound +with [supported media types](#mediatypes). + +```js +import { parse, detect } from '@swagger-api/apidom-parser-adapter-asyncapi-json-3'; + +// detecting +await detect('{"asyncapi": "3.0.0"}'); // => true +await detect('{"asyncapi": "3.0.1"}'); // => true +await detect('test'); // => false + +// parsing +const parseResult = await parse('{"asyncapi": "3.0.0"}', { sourceMap: true }); +``` + +### Indirect usage + +You can omit the `mediaType` option here, but please read [Word on detect vs mediaTypes](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser#word-on-detect-vs-mediatypes) before you do so. + +```js +import ApiDOMParser from '@swagger-api/apidom-parser'; +import * as asyncApiJsonAdapter from '@swagger-api/apidom-parser-adapter-asyncapi-json-3'; + +const parser = new ApiDOMParser(); + +parser.use(asyncApiJsonAdapter); + +const parseResult = await parser.parse('{"asyncapi": "3.0.1"}', { mediaType: asyncApiJsonAdapter.mediaTypes.latest('json') }); +``` diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/config/api-extractor/api-extractor.json b/packages/apidom-parser-adapter-asyncapi-json-3/config/api-extractor/api-extractor.json new file mode 100644 index 0000000000..40bee5b261 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/config/api-extractor/api-extractor.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "../../../../api-extractor.json", + "mainEntryPointFilePath": "../../types/adapter.d.ts" +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/config/webpack/browser.config.js b/packages/apidom-parser-adapter-asyncapi-json-3/config/webpack/browser.config.js new file mode 100644 index 0000000000..3e21580d6e --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/config/webpack/browser.config.js @@ -0,0 +1,92 @@ +import path from 'node:path'; +import { nonMinimizeTrait, minimizeTrait } from './traits.config.js'; + +const browser = { + mode: 'production', + entry: ['./src/adapter.ts'], + target: 'web', + performance: { + maxEntrypointSize: 2300000, + maxAssetSize: 2300000, + }, + output: { + path: path.resolve('./dist'), + filename: 'apidom-parser-adapter-asyncapi-json-3.browser.js', + libraryTarget: 'umd', + library: 'apidomParserAdapterAsyncApiJson3', + }, + resolve: { + extensions: ['.ts', '.mjs', '.js', '.json'], + fallback: { + fs: false, + path: false, + }, + }, + module: { + rules: [ + { + test: /\.wasm$/, + loader: 'file-loader', + type: 'javascript/auto', + }, + { + test: /\.(ts|js)?$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + babelrc: true, + rootMode: 'upward', + }, + }, + }, + ], + }, + ...nonMinimizeTrait, +}; + +const browserMin = { + mode: 'production', + entry: ['./src/adapter.ts'], + target: 'web', + performance: { + maxEntrypointSize: 350000, + maxAssetSize: 350000, + }, + output: { + path: path.resolve('./dist'), + filename: 'apidom-parser-adapter-asyncapi-json-3.browser.min.js', + libraryTarget: 'umd', + library: 'apidomParserAdapterAsyncApiJson3', + }, + resolve: { + extensions: ['.ts', '.mjs', '.js', '.json'], + fallback: { + fs: false, + path: false, + }, + }, + module: { + rules: [ + { + test: /\.wasm$/, + loader: 'file-loader', + type: 'javascript/auto', + }, + { + test: /\.(ts|js)?$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + babelrc: true, + rootMode: 'upward', + }, + }, + }, + ], + }, + ...minimizeTrait, +}; + +export default [browser, browserMin]; diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/config/webpack/traits.config.js b/packages/apidom-parser-adapter-asyncapi-json-3/config/webpack/traits.config.js new file mode 100644 index 0000000000..9043521175 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/config/webpack/traits.config.js @@ -0,0 +1,32 @@ +import webpack from 'webpack'; +import TerserPlugin from 'terser-webpack-plugin'; + +export const nonMinimizeTrait = { + optimization: { + minimize: false, + usedExports: false, + concatenateModules: false, + }, +}; + +export const minimizeTrait = { + plugins: [ + new webpack.LoaderOptionsPlugin({ + minimize: true, + }), + ], + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + compress: { + warnings: false, + }, + output: { + comments: false, + }, + }, + }), + ], + }, +}; diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/package.json b/packages/apidom-parser-adapter-asyncapi-json-3/package.json new file mode 100644 index 0000000000..4735555777 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/package.json @@ -0,0 +1,63 @@ +{ + "name": "@swagger-api/apidom-parser-adapter-asyncapi-json-3", + "version": "1.0.0-rc.3", + "description": "Parser adapter for parsing JSON documents into AsyncAPI 3.x.y namespace.", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, + "type": "module", + "sideEffects": false, + "unpkg": "./dist/apidom-parser-apdater-asyncapi-json-3.browser.min.js", + "main": "./src/adapter.cjs", + "exports": { + "types": "./types/apidom-parser-adapter-asyncapi-json-3.d.ts", + "import": "./src/adapter.mjs", + "require": "./src/adapter.cjs" + }, + "types": "./types/apidom-parser-adapter-asyncapi-json-3.d.ts", + "scripts": { + "build": "npm run clean && run-p --max-parallel ${CPU_CORES:-2} typescript:declaration build:es build:cjs build:umd:browser", + "build:es": "cross-env BABEL_ENV=es babel src --out-dir src --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward'", + "build:cjs": "cross-env BABEL_ENV=cjs babel src --out-dir src --extensions '.ts' --out-file-extension '.cjs' --root-mode 'upward'", + "build:umd:browser": "cross-env BABEL_ENV=browser webpack --config config/webpack/browser.config.js --progress", + "lint": "eslint ./", + "lint:fix": "eslint ./ --fix", + "clean": "rimraf --glob 'src/**/*.mjs' 'src/**/*.cjs' ./dist ./types", + "typescript:check-types": "tsc --noEmit && tsc -p ./test/tsconfig.json --noEmit", + "typescript:declaration": "tsc -p tsconfig.declaration.json && api-extractor run -l -c ./config/api-extractor/api-extractor.json", + "test": "NODE_ENV=test ts-mocha --exit", + "perf": "cross-env BABEL_ENV=es babel ./test/perf/index.ts --out-file ./test/perf/index.mjs --root-mode 'upward' && cross-env NODE_ENV=test node ./test/perf/index.mjs", + "perf:lexical-analysis": "cross-env BABEL_ENV=es babel ./test/perf/lexical-analysis.ts --out-file ./test/perf/lexical-analysis.mjs --root-mode 'upward' && cross-env NODE_ENV=test node ./test/perf/lexical-analysis.mjs", + "perf:syntactic-analysis": "cross-env BABEL_ENV=es babel ./test/perf/syntactic-analysis.ts --out-file ./test/perf/syntactic-analysis.mjs --root-mode 'upward' && cross-env NODE_ENV=test node ./test/perf/syntactic-analysis.mjs", + "perf:refract": "cross-env BABEL_ENV=es babel ./test/perf/refract.ts --out-file ./test/perf/refract.mjs --root-mode 'upward' && cross-env NODE_ENV=test node ./test/perf/refract.mjs", + "perf:parse": "cross-env BABEL_ENV=es babel ./test/perf/parse.ts --out-file ./test/perf/parse.mjs --root-mode 'upward' && cross-env NODE_ENV=test node ./test/perf/parse.mjs", + "prepack": "copyfiles -u 3 ../../LICENSES/* LICENSES && copyfiles -u 2 ../../NOTICE .", + "postpack": "rimraf NOTICE LICENSES" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/swagger-api/apidom.git" + }, + "author": "Shikha Lakhotia", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime-corejs3": "^7.26.10", + "@swagger-api/apidom-core": "^1.0.0-rc.3", + "@swagger-api/apidom-ns-asyncapi-3": "^1.0.0-rc.3", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-rc.3", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" + }, + "files": [ + "src/**/*.mjs", + "src/**/*.cjs", + "dist/", + "types/apidom-parser-adapter-asyncapi-json-3.d.ts", + "LICENSES", + "NOTICE", + "README.md", + "CHANGELOG.md" + ] +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/src/adapter.ts b/packages/apidom-parser-adapter-asyncapi-json-3/src/adapter.ts new file mode 100644 index 0000000000..dd2d3611d9 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/src/adapter.ts @@ -0,0 +1,45 @@ +import { propOr, omit } from 'ramda'; +import { isNotUndefined } from 'ramda-adjunct'; +import { ParseResultElement, createNamespace } from '@swagger-api/apidom-core'; +import { parse as parseJSON, detect as detectJSON } from '@swagger-api/apidom-parser-adapter-json'; +import asyncApiNamespace, { AsyncApi3Element } from '@swagger-api/apidom-ns-asyncapi-3'; + +export { default as mediaTypes } from './media-types.ts'; + +/** + * @public + */ +export const detectionRegExp = + /"asyncapi"\s*:\s*"(?3\.(?:[1-9]\d*|0)\.(?:[1-9]\d*|0))"/; + +/** + * @public + */ +export const detect = async (source: string): Promise => + detectionRegExp.test(source) && (await detectJSON(source)); + +/** + * @public + */ +export const parse = async ( + source: string, + options: Record = {}, +): Promise => { + const refractorOpts: Record = propOr({}, 'refractorOpts', options); + const parserOpts = omit(['refractorOpts'], options); + const parseResultElement = await parseJSON(source, parserOpts); + const { result } = parseResultElement; + + if (isNotUndefined(result)) { + const asyncApiElement = AsyncApi3Element.refract(result, refractorOpts); + asyncApiElement.classes.push('result'); + parseResultElement.replaceResult(asyncApiElement); + } + + return parseResultElement; +}; + +/** + * @public + */ +export const namespace = createNamespace(asyncApiNamespace); diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/src/media-types.ts b/packages/apidom-parser-adapter-asyncapi-json-3/src/media-types.ts new file mode 100644 index 0000000000..a9e624cf78 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/src/media-types.ts @@ -0,0 +1,11 @@ +import { mediaTypes, AsyncAPIMediaTypes } from '@swagger-api/apidom-ns-asyncapi-3'; + +/** + * @public + */ +const jsonMediaTypes = new AsyncAPIMediaTypes( + ...mediaTypes.filterByFormat('generic'), + ...mediaTypes.filterByFormat('json'), +); + +export default jsonMediaTypes; diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/.eslintrc b/packages/apidom-parser-adapter-asyncapi-json-3/test/.eslintrc new file mode 100644 index 0000000000..c47eea4f48 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/.eslintrc @@ -0,0 +1,55 @@ +{ + "env": { + "mocha": true + }, + "globals": { + "document": true + }, + "plugins": [ + "mocha" + ], + "rules": { + "no-void": 0, + "func-names": 0, + "prefer-arrow-callback": 0, + "no-array-constructor": 0, + "prefer-rest-params": 0, + "no-new-wrappers": 0, + "mocha/no-skipped-tests": 2, + "mocha/handle-done-callback": 2, + "mocha/valid-suite-description": 2, + "mocha/no-mocha-arrows": 2, + "mocha/no-hooks-for-single-case": 2, + "mocha/no-sibling-hooks": 2, + "mocha/no-top-level-hooks": 2, + "mocha/no-identical-title": 2, + "mocha/no-nested-tests": 2, + "mocha/no-exclusive-tests": 2, + "no-underscore-dangle": 0, + "import/no-relative-packages": 0, + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": "variable", + "format": ["camelCase", "PascalCase", "UPPER_CASE"], + "leadingUnderscore": "forbid" + }, + { + "selector": "variable", + "format": null, + "filter": { + "regex": "^__dirname$", + "match": true + } + }, + { + "selector": "variable", + "format": null, + "filter": { + "regex": "^__filename$", + "match": true + } + } + ] + } +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/__snapshots__/adapter.mjs.snap b/packages/apidom-parser-adapter-asyncapi-json-3/test/__snapshots__/adapter.mjs.snap new file mode 100644 index 0000000000..924fb82588 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/__snapshots__/adapter.mjs.snap @@ -0,0 +1,985 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`adapter should parse 1`] = ` +(ParseResultElement + (AsyncApi3Element + (MemberElement + (StringElement) + (AsyncApiVersionElement)) + (MemberElement + (StringElement) + (IdentifierElement)) + (MemberElement + (StringElement) + (InfoElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ContactElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (LicenseElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (TagsElement + (TagElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))))) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ServersElement + (MemberElement + (StringElement) + (ServerElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ServerVariableElement + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement) + (StringElement))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement) + (StringElement))))))) + (MemberElement + (StringElement) + (ArrayElement + (SecuritySchemeElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement)))))))) + (MemberElement + (StringElement) + (ServerBindingsElement + (MemberElement + (StringElement) + (KafkaServerBindingElement)))) + (MemberElement + (StringElement) + (TagsElement + (TagElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))))))) + (MemberElement + (StringElement) + (ServerElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ServerBindingsElement + (MemberElement + (StringElement) + (JmsServerBindingElement)))))))) + (MemberElement + (StringElement) + (DefaultContentTypeElement)) + (MemberElement + (StringElement) + (ChannelsElement + (MemberElement + (StringElement) + (ChannelElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (MessagesElement + (MemberElement + (StringElement) + (MessageElement + (MemberElement + (StringElement) + (SchemaElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (SchemaElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))))) + (MemberElement + (StringElement) + (CorrelationIDElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (TagsElement + (TagElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))))) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (MessageBindingsElement + (MemberElement + (StringElement) + (KafkaMessageBindingElement + (MemberElement + (StringElement) + (SchemaElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ArrayElement + (MessageExampleElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))) + (MemberElement + (StringElement) + (ArrayElement + (MessageTraitElement + (MemberElement + (StringElement) + (SchemaElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (CorrelationIDElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (TagsElement + (TagElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))))) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (MessageBindingsElement + (MemberElement + (StringElement) + (KafkaMessageBindingElement + (MemberElement + (StringElement) + (SchemaElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ArrayElement + (MessageExampleElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))))))))))) + (MemberElement + (StringElement) + (ParametersElement + (MemberElement + (StringElement) + (ParameterElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ArrayElement + (ReferenceElement + (MemberElement + (StringElement) + (StringElement))) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement))))) + (MemberElement + (StringElement) + (ChannelBindingsElement + (MemberElement + (StringElement) + (AmqpChannelBindingElement)))) + (MemberElement + (StringElement) + (TagsElement + (TagElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ComponentsElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (SchemaElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (MultiFormatSchemaElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (SchemaElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (MessageElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (SecuritySchemeElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ParameterElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (CorrelationIDElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (OperationTraitElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (MessageTraitElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ServerBindingsElement + (MemberElement + (StringElement) + (KafkaServerBindingElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ChannelBindingsElement + (MemberElement + (StringElement) + (KafkaChannelBindingElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (OperationBindingsElement + (MemberElement + (StringElement) + (KafkaOperationBindingElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (MessageBindingsElement + (MemberElement + (StringElement) + (KafkaMessageBindingElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ServerElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ServerVariableElement + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement))) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ChannelElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (OperationElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (OperationReplyElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (OperationReplyAddressElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ExternalDocumentationElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (TagElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))))))) + (MemberElement + (StringElement) + (OperationsElement + (MemberElement + (StringElement) + (OperationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (TagsElement + (TagElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))))) + (MemberElement + (StringElement) + (OperationBindingsElement + (MemberElement + (StringElement) + (KafkaOperationBindingElement)))) + (MemberElement + (StringElement) + (ArrayElement + (OperationTraitElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (OperationBindingsElement + (MemberElement + (StringElement) + (KafkaOperationBindingElement)))) + (MemberElement + (StringElement) + (ArrayElement + (SecuritySchemeElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement)))))))) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))))))) + (MemberElement + (StringElement) + (ArrayElement + (SecuritySchemeElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)) + (MemberElement + (StringElement) + (ObjectElement)))) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement)))))))) + (MemberElement + (StringElement) + (ExternalDocumentationElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ArrayElement + (ReferenceElement + (MemberElement + (StringElement) + (StringElement))))) + (MemberElement + (StringElement) + (OperationReplyElement + (MemberElement + (StringElement) + (OperationReplyAddressElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ReferenceElement + (MemberElement + (StringElement) + (StringElement)))) + (MemberElement + (StringElement) + (ArrayElement + (ReferenceElement + (MemberElement + (StringElement) + (StringElement))))))))))))) +`; diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/adapter.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/adapter.ts new file mode 100644 index 0000000000..cf8d73a5c0 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/adapter.ts @@ -0,0 +1,94 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { assert, expect } from 'chai'; +import { isParseResultElement, sexprs } from '@swagger-api/apidom-core'; +import { isAsyncApi3Element } from '@swagger-api/apidom-ns-asyncapi-3'; + +import * as adapter from '../src/adapter.ts'; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); +const jsonSpec = fs.readFileSync(path.join(dirname, 'fixtures', 'sample-api.json')).toString(); +const yamlSpec = fs.readFileSync(path.join(dirname, 'fixtures', 'sample-api.yaml')).toString(); + +describe('adapter', function () { + context('given definition in JSON format', function () { + specify('should detect proper media type', async function () { + assert.isTrue(await adapter.detect(jsonSpec)); + }); + + specify('should detect minor version bump', async function () { + assert.isTrue(await adapter.detect('{"asyncapi": "3.25.0"}')); + }); + + specify('should detect patch version bump', async function () { + assert.isTrue(await adapter.detect('{"asyncapi": "3.6.1"}')); + }); + + specify('should detect minor and patch version bump', async function () { + assert.isTrue(await adapter.detect('{"asyncapi": "3.25.1"}')); + }); + }); + + context('given definition in YAML 1.3 format', function () { + specify('should detect proper media type', async function () { + assert.isFalse(await adapter.detect(yamlSpec)); + }); + }); + + context('given definition of unknown type', function () { + specify('should detect proper media type', async function () { + assert.isFalse(await adapter.detect('"openapi": "2.1.0"')); + }); + }); + + it('should parse', async function () { + const parseResult = await adapter.parse(jsonSpec, { sourceMap: true }); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(isAsyncApi3Element(parseResult.api)); + expect(sexprs(parseResult)).toMatchSnapshot(); + }); + + context('given zero byte empty file', function () { + specify('should return empty parse result', async function () { + const parseResult = await adapter.parse('', { sourceMap: true }); + + assert.isTrue(parseResult.isEmpty); + }); + }); + + context('given non-zero byte empty file', function () { + specify('should return empty parser result', async function () { + const parseResult = await adapter.parse(' ', { sourceMap: true }); + + assert.isTrue(parseResult.isEmpty); + }); + }); + + context('given invalid json file', function () { + specify('should return empty parser result', async function () { + const parseResult = await adapter.parse(' a ', { sourceMap: true }); + + assert.isTrue(parseResult.isEmpty); + }); + }); + + context('detectionRegExp', function () { + specify('should detect version ranges in forward compatible way', function () { + assert.isTrue(adapter.detectionRegExp.test('"asyncapi": "3.0.0"')); + assert.isTrue(adapter.detectionRegExp.test('"asyncapi": "3.0.145"')); + assert.isTrue(adapter.detectionRegExp.test('"asyncapi": "3.0.1"')); + }); + + specify('should reject invalid version ranges', function () { + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "2.0.0"')); + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "2.1.0"')); + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "2.1.1"')); + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "2.5.0"')); + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "2.6.01"')); + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "3.6.01"')); + assert.isFalse(adapter.detectionRegExp.test('"asyncapi": "3.06.0"')); + }); + }); +}); diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/fixtures/sample-api.json b/packages/apidom-parser-adapter-asyncapi-json-3/test/fixtures/sample-api.json new file mode 100644 index 0000000000..f1cbd29430 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/fixtures/sample-api.json @@ -0,0 +1,458 @@ +{ + "asyncapi": "3.0.0", + "id": "urn:com:smartylighting:streetlights:server", + "info": { + "title": "AsyncAPI Sample App", + "version": "1.0.1", + "description": "This is a sample server.", + "termsOfService": "http://asyncapi.org/terms/", + "contact": { + "name": "API Support", + "url": "http://www.asyncapi.org/support", + "email": "support@asyncapi.org" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "tags": [ + { + "name": "topLevelTag", + "description": "topLevelTag description", + "externalDocs": { + "description": "description of topLevelTag external docs", + "url": "https://example.com/topLevelTag" + } + } + ], + "externalDocs": { + "description": "description of this document external docs", + "url": "https://example.com/document" + } + }, + "servers": { + "production": { + "host": "{username}.gigantic-server.com", + "protocol": "kafka", + "protocolVersion": "1.0.0", + "pathname": "/v2", + "description": "Production server description", + "title": "Production server", + "summary": "Production server summary.", + "variables": { + "username": { + "enum": ["demo", "demo1", "demo2"], + "default": "demo", + "description": "This value is assigned by the service provider, in this example `gigantic-server.com`", + "examples": ["demo", "demo1", "demo2"] + } + }, + "security": [ + { + "petstore_auth": { + "type": "apiKey", + "description": "Petstore Auth description", + "name": "Petstore Auth", + "in": "password", + "scheme": "Authorization", + "bearerFormat": "JWT", + "flows": { + "implicit": {}, + "password": {}, + "clientCredentials": {}, + "authorizationCode": {} + }, + "openIdConnectUrl": "security-scheme-openIdConnectUrl", + "scopes": ["write:pets", "read:pets"] + } + } + ], + "bindings": { + "kafka": {} + }, + "tags": [ + { + "name": "serversLevelTag", + "description": "serversLevelTag description", + "externalDocs": { + "description": "description of serversLevelTag external docs", + "url": "https://example.com/serversLevelTag" + } + } + ] + }, + "development": { + "host": "gigantic-server.com", + "protocol": "kafka", + "bindings": { + "jms": {} + } + } + }, + "defaultContentType": "application/json", + "channels": { + "userSignedUp": { + "address": "users.{userId}", + "title": "Users channel", + "description": "This channel is used to exchange messages about user events.", + "summary": "Exchange messages about user events.", + "messages": { + "userSignedUp": { + "headers": { + "type": "object" + }, + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/user" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + }, + "correlationId": { + "description": "correlation id description", + "location": "http://asyncapi.com/" + }, + "contentType": "application/json", + "name": "name of the message", + "title": "title of the message", + "summary": "summary of the message", + "description": "A longer description of the message", + "tags": [ + { + "name": "tag3", + "description": "description of tag3", + "externalDocs": { + "description": "description of tag 3 external docs", + "url": "https://example.com/tag3" + } + } + ], + "externalDocs": { + "description": "description of message 1 external docs", + "url": "https://example.com/message-1-external-docs" + }, + "bindings": { + "kafka": { + "key": { + "type": "integer" + }, + "bindingVersion": "0.1.0" + } + }, + "examples": [ + { + "headers": { "Content-Type": "application/json" }, + "payload": "{\"a\":\"b\"}", + "name": "example name", + "summary": "example summary" + } + ], + "traits": [ + { + "headers": { + "type": "object" + }, + "correlationId": { + "description": "correlation id description", + "location": "http://asyncapi.com/" + }, + "contentType": "application/json", + "name": "name of the message trait", + "title": "title of the message trait", + "summary": "summary of the message trait", + "description": "A longer description of the message trait", + "tags": [ + { + "name": "tag4", + "description": "description of tag4", + "externalDocs": { + "description": "description of tag 4 external docs", + "url": "https://example.com/tag4" + } + } + ], + "externalDocs": { + "description": "description of message 1 trait external docs", + "url": "https://example.com/message-1-trait-external-docs" + }, + "bindings": { + "kafka": { + "key": { + "type": "integer" + }, + "bindingVersion": "0.1.0" + } + }, + "examples": [ + { + "headers": { "Content-Type": "application/json" }, + "payload": "{\"a\":\"b\"}", + "name": "example name", + "summary": "example summary" + } + ] + } + ] + } + }, + "parameters": { + "userId": { + "description": "User identifier" + } + }, + "servers": [ + { "$ref": "#/servers/rabbitmqInProd" }, + { "$ref": "#/servers/rabbitmqInStaging" } + ], + "bindings": { + "amqp": {} + }, + "tags": [ + { + "name": "user", + "description": "User-related messages" + } + ], + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + } + }, + "user/loggedout": { + "$ref": "https://outside.com/#/path/to/channel" + } + }, + "components": { + "schemas": { + "Schema1": { + "type": "object" + }, + "Schema2": { + "$ref": "#/components/schemas/Schema1" + }, + "Schema3": { + "schemaFormat": "application/vnd.aai.asyncapi;version=3.0.0", + "schema": {} + } + }, + "messages": { + "Message1": {}, + "Message2": { + "$ref": "#/components/messages/Message1" + } + }, + "securitySchemes": { + "SecurityScheme1": {}, + "SecurityScheme2": { + "$ref": "#/components/securitySchemes/SecurityScheme1" + } + }, + "parameters": { + "Parameter1": { + "description": "parameter description", + "location": "http://example.com" + }, + "Parameter2": { + "$ref": "#/components/parameters/Parameter1" + } + }, + "correlationIds": { + "CorrelationID1": {}, + "CorrelationID2": { + "$ref": "#/components/correlationIds/CorrelationID1" + } + }, + "operationTraits": { + "OperationTrait1": {}, + "OperationTrait2": { + "$ref": "#/components/operationTraits/OperationTrait1" + } + }, + "messageTraits": { + "MessageTrait1": {}, + "MessageTrait2": { + "$ref": "#/components/messageTraits/MessageTrait1" + } + }, + "serverBindings": { + "ServerBinding1": { + "kafka": {} + }, + "ServerBinding2": { + "$ref": "#/components/serverBindings/ServerBinding1" + } + }, + "channelBindings": { + "ChannelBinding1": { + "kafka": {} + }, + "ChannelBinding2": { + "$ref": "#/components/channelBindings/ChannelBinding1" + } + }, + "operationBindings": { + "OperationBinding1": { + "kafka": {} + }, + "OperationBinding2": { + "$ref": "#/components/operationBindings/OperationBinding1" + } + }, + "messageBindings": { + "MessageBinding1": { + "kafka": {} + }, + "MessageBinding2": { + "$ref": "#/components/messageBindings/MessageBinding1" + } + }, + "servers": { + "server1": {}, + "server2": { + "$ref": "#/components/servers/server1" + } + }, + "serverVariables": { + "port": { + "enum": ["8883", "8884"], + "default": "8883" + }, + "port1": { + "$ref": "#/components/serverVariables/port" + } + }, + "channels": { + "channel1": {}, + "channel2": { + "$ref": "#/components/channels/channel1" + } + }, + "operations": { + "SignUp1": {}, + "SignUp2": { + "$ref": "#/components/operations/SignUp1" + } + }, + "replies": { + "UserReply1": {}, + "UserReply2": { + "$ref": "#/components/replies/UserReply1" + } + }, + "replyAddresses": { + "UserReplyAddress1": {}, + "UserReplyAddress2": { + "$ref": "#/components/replyAddresses/UserReplyAddress1" + } + }, + "externalDocs": { + "ExternalDoc1": {}, + "ExternalDoc2": { + "$ref": "#/components/externalDocs/ExternalDoc1" + } + }, + "tags": { + "UserTag1": {}, + "UserTag2": { + "$ref": "#/components/tags/UserTag1" + } + } + }, + "operations": { + "onUserSignUp": { + "title": "User sign up", + "summary": "Action to sign a user up.", + "description": "A longer description", + "channel": { + "$ref": "#/channels/userSignup" + }, + "action": "send", + "tags": [ + { + "name": "operationTag", + "description": "operationTag description", + "externalDocs": { + "description": "description of operationTag external docs", + "url": "https://example.com/operationTag" + } + } + ], + "bindings": { + "kafka": {} + }, + "traits": [ + { + "title": "Operation trait title", + "description": "Operation trait description", + "summary": "Operation trait summary", + "bindings": { + "kafka": {} + }, + "security": [ + { + "petstore_auth": { + "type": "apiKey", + "description": "Petstore Auth description", + "name": "Petstore Auth", + "in": "password", + "scheme": "Authorization", + "bearerFormat": "JWT", + "flows": { + "implicit": {}, + "password": {}, + "clientCredentials": {}, + "authorizationCode": {} + }, + "openIdConnectUrl": "security-scheme-openIdConnectUrl", + "scopes": ["write:pets", "read:pets"] + } + } + ], + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + } + } + ], + "security": [ + { + "petstore_auth": { + "type": "apiKey", + "description": "Petstore Auth description", + "name": "Petstore Auth", + "in": "password", + "scheme": "Authorization", + "bearerFormat": "JWT", + "flows": { + "implicit": {}, + "password": {}, + "clientCredentials": {}, + "authorizationCode": {} + }, + "openIdConnectUrl": "security-scheme-openIdConnectUrl", + "scopes": ["write:pets", "read:pets"] + } + } + ], + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + }, + "messages": [{ "$ref": "#/components/messages/Message1" }], + "reply": { + "address": { + "description": "Reply address description", + "location": "http://example.com/reply" + }, + "channel": { + "$ref": "#/components/channels/channel1" + }, + "messages": [{ "$ref": "#/components/messages/Message1" }] + } + } + } +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/fixtures/sample-api.yaml b/packages/apidom-parser-adapter-asyncapi-json-3/test/fixtures/sample-api.yaml new file mode 100644 index 0000000000..d13011cce9 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/fixtures/sample-api.yaml @@ -0,0 +1,337 @@ +--- +asyncapi: "3.0.0" +id: "urn:com:smartylighting:streetlights:server" +info: + title: "AsyncAPI Sample App" + version: "1.0.1" + description: "This is a sample server." + termsOfService: "http://asyncapi.org/terms/" + contact: + name: "API Support" + url: "http://www.asyncapi.org/support" + email: "support@asyncapi.org" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" + tags: + - name: "topLevelTag" + description: "topLevelTag description" + externalDocs: + description: "description of topLevelTag external docs" + url: "https://example.com/topLevelTag" + externalDocs: + description: "description of this document external docs" + url: "https://example.com/document" +servers: + production: + host: "{username}.gigantic-server.com" + protocol: "kafka" + protocolVersion: "1.0.0" + pathname: "/v2" + description: "Production server description" + title: "Production server" + summary: "Production server summary." + variables: + username: + enum: + - "demo" + - "demo1" + - "demo2" + default: "demo" + description: "This value is assigned by the service provider, in this example `gigantic-server.com`" + examples: + - "demo" + - "demo1" + - "demo2" + security: + - + petstore_auth: + type: "apiKey" + description: "Petstore Auth description" + name: "Petstore Auth" + in: "password" + scheme: "Authorization" + bearerFormat: "JWT" + flows: + implicit: + password: + clientCredentials: + authorizationCode: + openIdConnectUrl: "security-scheme-openIdConnectUrl" + scopes: + - "write:pets" + - "read:pets" + bindings: + kafka: + tags: + - name: "serversLevelTag" + description: "serversLevelTag description" + externalDocs: + description: "description of serversLevelTag external docs" + url: "https://example.com/serversLevelTag" + development: + host: "gigantic-server.com" + protocol: "kafka" + bindings: + jms: +defaultContentType: "application/json" +channels: + userSignedUp: + address: "users.{userId}" + title: "Users channel" + description: "This channel is used to exchange messages about user events." + summary: "Exchange messages about user events." + messages: + userSignedUp: + headers: + type: "object" + payload: + type: "object" + properties: + user: + $ref: "#/components/schemas/user" + signup: + $ref: "#/components/schemas/signup" + correlationId: + description: "correlation id description" + location: "http://asyncapi.com/" + contentType: "application/json" + name: "name of the message" + title: "title of the message" + summary: "summary of the message" + description: "A longer description of the message" + tags: + - name: "tag3" + description: "description of tag3" + externalDocs: + description: "description of tag 3 external docs" + url: "https://example.com/tag3" + externalDocs: + description: "description of message 1 external docs" + url: "https://example.com/message-1-external-docs" + bindings: + kafka: + key: + type: "integer" + bindingVersion: "0.1.0" + examples: + - + headers: + Content-Type: "application/json" + payload: "{"a":"b"}" + name: "example name" + summary: "example summary" + traits: + - + headers: + type: "object" + correlationId: + description: "correlation id description" + location: "http://asyncapi.com/" + contentType: "application/json" + name: "name of the message trait" + title: "title of the message trait" + summary: "summary of the message trait" + description: "A longer description of the message trait" + tags: + - name: "tag4" + description: "description of tag4" + externalDocs: + description: "description of tag 4 external docs" + url: "https://example.com/tag4" + externalDocs: + description: "description of message 1 trait external docs" + url: "https://example.com/message-1-trait-external-docs" + bindings: + kafka: + key: + type: "integer" + bindingVersion: "0.1.0" + examples: + - + headers: + Content-Type: "application/json" + payload: "{"a":"b"}" + name: "example name" + summary: "example summary" + parameters: + userId: + description: "User identifier" + servers: + - $ref: "#/servers/rabbitmqInProd" + - $ref: "#/servers/rabbitmqInStaging" + bindings: + amqp: + tags: + - name: "user" + description: "User-related messages" + externalDocs: + description: "Find more info here" + url: "https://example.com" + user/loggedout: + $ref: "https://outside.com/#/path/to/channel" +components: + schemas: + Schema1: + type: "object" + Schema2: + $ref: "#/components/schemas/Schema1" + Schema3: + schemaFormat: "application/vnd.aai.asyncapi;version=3.0.0" + schema: + messages: + Message1: + Message2: + $ref: "#/components/messages/Message1" + securitySchemes: + SecurityScheme1: + SecurityScheme2: + $ref: "#/components/securitySchemes/SecurityScheme1" + parameters: + Parameter1: + description: "parameter description" + location: "http://example.com" + Parameter2: + $ref: "#/components/parameters/Parameter1" + correlationIds: + CorrelationID1: + CorrelationID2: + $ref: "#/components/correlationIds/CorrelationID1" + operationTraits: + OperationTrait1: + OperationTrait2: + $ref: "#/components/operationTraits/OperationTrait1" + messageTraits: + MessageTrait1: + MessageTrait2: + $ref: "#/components/messageTraits/MessageTrait1" + serverBindings: + ServerBinding1: + kafka: + ServerBinding2: + $ref: "#/components/serverBindings/ServerBinding1" + channelBindings: + ChannelBinding1: + kafka: + ChannelBinding2: + $ref: "#/components/channelBindings/ChannelBinding1" + operationBindings: + OperationBinding1: + kafka: + OperationBinding2: + $ref: "#/components/operationBindings/OperationBinding1" + messageBindings: + MessageBinding1: + kafka: + MessageBinding2: + $ref: "#/components/messageBindings/MessageBinding1" + servers: + server1: + server2: + $ref: "#/components/servers/server1" + serverVariables: + port: + enum: + - "8883" + - "8884" + default: "8883" + port1: + $ref: "#/components/serverVariables/port" + channels: + channel1: + channel2: + $ref: "#/components/channels/channel1" + operations: + SignUp1: + SignUp2: + $ref: "#/components/operations/SignUp1" + replies: + UserReply1: + UserReply2: + $ref: "#/components/replies/UserReply1" + replyAddresses: + UserReplyAddress1: + UserReplyAddress2: + $ref: "#/components/replyAddresses/UserReplyAddress1" + externalDocs: + ExternalDoc1: + ExternalDoc2: + $ref: "#/components/externalDocs/ExternalDoc1" + tags: + UserTag1: + UserTag2: + $ref: "#/components/tags/UserTag1" +operations: + onUserSignUp: + title: "User sign up" + summary: "Action to sign a user up." + description: "A longer description" + channel: + $ref: "#/channels/userSignup" + action: "send" + tags: + - name: "operationTag" + description: "operationTag description" + externalDocs: + description: "description of operationTag external docs" + url: "https://example.com/operationTag" + bindings: + kafka: + traits: + - title: "Operation trait title" + description: "Operation trait description" + summary: "Operation trait summary" + bindings: + kafka: + security: + - + petstore_auth: + type: "apiKey" + description: "Petstore Auth description" + name: "Petstore Auth" + in: "password" + scheme: "Authorization" + bearerFormat: "JWT" + flows: + implicit: + password: + clientCredentials: + authorizationCode: + openIdConnectUrl: "security-scheme-openIdConnectUrl" + scopes: + - "write:pets" + - "read:pets" + externalDocs: + description: "Find more info here" + url: "https://example.com" + security: + - + petstore_auth: + type: "apiKey" + description: "Petstore Auth description" + name: "Petstore Auth" + in: "password" + scheme: "Authorization" + bearerFormat: "JWT" + flows: + implicit: + password: + clientCredentials: + authorizationCode: + openIdConnectUrl: "security-scheme-openIdConnectUrl" + scopes: + - "write:pets" + - "read:pets" + externalDocs: + description: "Find more info here" + url: "https://example.com" + messages: + - $ref: "#/components/messages/Message1" + reply: + address: + description: "Reply address description" + location: "http://example.com/reply" + channel: + $ref: "#/components/channels/channel1" + messages: + - $ref: "#/components/messages/Message1" \ No newline at end of file diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/media-types.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/media-types.ts new file mode 100644 index 0000000000..08be514354 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/media-types.ts @@ -0,0 +1,16 @@ +import { assert } from 'chai'; +import ApiDOMParser from '@swagger-api/apidom-parser'; + +import * as asyncApiJsonAdapter from '../src/adapter.ts'; + +describe('given adapter is used in parser', function () { + const parser = new ApiDOMParser().use(asyncApiJsonAdapter); + + context('given AsyncAPI 3.0.0 definition in JSON format', function () { + specify('should find appropriate media type', async function () { + const mediaType = await parser.findMediaType('{"asyncapi": "3.0.0"}'); + + assert.strictEqual(mediaType, 'application/vnd.aai.asyncapi+json;version=3.0.0'); + }); + }); +}); diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/mocha-bootstrap.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/mocha-bootstrap.ts new file mode 100644 index 0000000000..aec560d03f --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/mocha-bootstrap.ts @@ -0,0 +1,11 @@ +import * as chai from 'chai'; +import { jestSnapshotPlugin, addSerializer } from 'mocha-chai-jest-snapshot'; + +// @ts-ignore +import * as jestApiDOMSerializer from '../../../scripts/jest-serializer-apidom.mjs'; +// @ts-ignore +import * as jestStringSerializer from '../../../scripts/jest-serializer-string.mjs'; + +chai.use(jestSnapshotPlugin()); +addSerializer(jestApiDOMSerializer); +addSerializer(jestStringSerializer); diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/fixtures/asyncapi.json b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/fixtures/asyncapi.json new file mode 100644 index 0000000000..edede5c280 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/fixtures/asyncapi.json @@ -0,0 +1,137 @@ +{ + "asyncapi": "3.0.0", + "id": "urn:com:smartylighting:streetlights:server", + "info": { + "title": "AsyncAPI Sample App", + "version": "1.0.1" + }, + "servers": { + "production":{ + "url": "{username}.gigantic-server.com:{port}/{basePath}", + "protocol": "secure-mqtt", + "protocolVersion": "1.0.0", + "variables": { + "username": { + "default": "demo", + "description": "This value is assigned by the service provider, in this example `gigantic-server.com`", + "examples": ["value1", "value2"] + }, + "port": { + "enum": [ + "8883", + "8884" + ], + "default": "8883" + }, + "basePath": { + "default": "v2" + } + }, + "security": [ + { + "user_pass": [] + } + ] + } + }, + "channels": { + "user/{userId}/signup": { + "description": "This channel is used to exchange messages about users signing up", + "parameters": { + "userId": { + "description": "Id of the user.", + "schema": { + "type": "string" + } + } + }, + "subscribe": { + "message": { + "description": "A longer description of the message", + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/user" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + } + } + }, + "bindings": { + "amqp": { + "is": "queue", + "queue": { + "exclusive": true + } + } + } + } + }, + "components": { + "x-extension": "value", + "schemas": { + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + } + }, + "messages": { + "userSignUp": { + "summary": "Action to sign a user up.", + "description": "Multiline description of what this action does.\nHere you have another line.\n", + "tags": [ + { + "name": "user" + }, + { + "name": "signup" + } + ], + "headers": { + "type": "object", + "properties": { + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/userCreate" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + } + } + } + } +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/index.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/index.ts new file mode 100644 index 0000000000..94522d856c --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/index.ts @@ -0,0 +1,24 @@ +import Benchmark from 'benchmark'; +import type { Event } from 'benchmark'; + +import lexicalAnalysisBench from './lexical-analysis.ts'; +import syntacticAnalysisBench from './syntactic-analysis.ts'; +import refractBench from './refract.ts'; +import parseBench from './parse.ts'; + +const suite = new Benchmark.Suite(); + +suite + .add(lexicalAnalysisBench) + .add(syntacticAnalysisBench) + .add(refractBench) + .add(parseBench) + // add listeners + .on('cycle', function (event: Event) { + console.info(String(event.target)); + }) + .on('complete', function () { + console.info('\nAll benchmarks have completed'); + }) + // run + .run(); diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/lexical-analysis.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/lexical-analysis.ts new file mode 100644 index 0000000000..a66e7db268 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/lexical-analysis.ts @@ -0,0 +1,37 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import Benchmark from 'benchmark'; +import type { Deferred, Event } from 'benchmark'; +import { lexicalAnalysis } from '@swagger-api/apidom-parser-adapter-json'; +import { fileURLToPath } from 'node:url'; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixturePath = path.join(dirname, 'fixtures/asyncapi.json'); +const source = fs.readFileSync(fixturePath).toString(); + +const options = { + name: 'lexical-analysis', + defer: true, + minSamples: 1400, + expected: '1,294 ops/sec ±1.97% (1473 runs sampled)', + async fn(deferred: Deferred) { + await lexicalAnalysis(source); + deferred.resolve(); + }, +}; + +export default options; + +// we're running as a script +if (import.meta.url === `file://${process.argv[1]}`) { + const bench = new Benchmark({ + ...options, + onComplete(event: Event) { + console.info(String(event.target)); + }, + onError(event: Event) { + console.error(event); + }, + }); + bench.run(); +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/parse.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/parse.ts new file mode 100644 index 0000000000..af07996e30 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/parse.ts @@ -0,0 +1,47 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import Benchmark from 'benchmark'; +import type { Deferred, Event } from 'benchmark'; + +import { parse } from '../../src/adapter.ts'; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixturePath = path.join(dirname, 'fixtures/asyncapi.json'); +const source = fs.readFileSync(fixturePath).toString(); + +const options = { + name: 'parse', + defer: true, + minSamples: 600, + expected: '41.22 ops/sec ±1.71% (658 runs sampled)', + async fn(deferred: Deferred) { + await parse(source); + deferred.resolve(); + }, +}; + +/** + * # Analysis of ApiDOM stages + * + * Parse stage: 14,56 ms + * Lexical Analysis phase: 0,77 ms + * Syntactic Analysis phase: 8,13 ms + * Refract stage: 9,7 ms + */ + +export default options; + +// we're running as a script +if (import.meta.url === `file://${process.argv[1]}`) { + const bench = new Benchmark({ + ...options, + onComplete(event: Event) { + console.info(String(event.target)); + }, + onError(event: Event) { + console.error(event); + }, + }); + bench.run(); +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/refract.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/refract.ts new file mode 100644 index 0000000000..cb50d4d8da --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/refract.ts @@ -0,0 +1,38 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import Benchmark from 'benchmark'; +import type { Event } from 'benchmark'; +import { ObjectElement } from '@swagger-api/apidom-core'; +import { AsyncApi3Element } from '@swagger-api/apidom-ns-asyncapi-3'; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixturePath = path.join(dirname, 'fixtures/asyncapi.json'); +const source = fs.readFileSync(fixturePath).toString(); +const pojo = JSON.parse(source); +const genericObjectElement = new ObjectElement(pojo); + +const options = { + name: 'refract', + minSamples: 600, + expected: '103 ops/sec ±0.92% (668 runs sampled)', + fn() { + AsyncApi3Element.refract(genericObjectElement); + }, +}; + +export default options; + +// we're running as a script +if (import.meta.url === `file://${process.argv[1]}`) { + const bench = new Benchmark({ + ...options, + onComplete(event: Event) { + console.info(String(event.target)); + }, + onError(event: Event) { + console.error(event); + }, + }); + bench.run(); +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/syntactic-analysis.ts b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/syntactic-analysis.ts new file mode 100644 index 0000000000..fed54ae7d2 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/perf/syntactic-analysis.ts @@ -0,0 +1,39 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import Benchmark from 'benchmark'; +import type { Deferred, Event } from 'benchmark'; +import { lexicalAnalysis, syntacticAnalysis } from '@swagger-api/apidom-parser-adapter-json'; +import { fileURLToPath } from 'node:url'; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixturePath = path.join(dirname, 'fixtures/asyncapi.json'); +const source = fs.readFileSync(fixturePath).toString(); +const cstP = lexicalAnalysis(source); + +const options = { + name: 'syntactic-analysis', + defer: true, + minSamples: 600, + expected: '123 ops/sec ±1.38% (676 runs sampled)', + async fn(deferred: Deferred) { + const cst = await cstP; + syntacticAnalysis(cst); + deferred.resolve(); + }, +}; + +export default options; + +// we're running as a script +if (import.meta.url === `file://${process.argv[1]}`) { + const bench = new Benchmark({ + ...options, + onComplete(event: Event) { + console.info(String(event.target)); + }, + onError(event: Event) { + console.error(event); + }, + }); + bench.run(); +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/test/tsconfig.json b/packages/apidom-parser-adapter-asyncapi-json-3/test/tsconfig.json new file mode 100644 index 0000000000..405aae2d2f --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/test/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "module": "esnext", + "moduleResolution": "node" + }, + "include": [ + "." + ] +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/tsconfig.declaration.json b/packages/apidom-parser-adapter-asyncapi-json-3/tsconfig.declaration.json new file mode 100644 index 0000000000..82d128fa80 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/tsconfig.declaration.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "types", + "noEmit": false, + "emitDeclarationOnly": true + } +} diff --git a/packages/apidom-parser-adapter-asyncapi-json-3/tsconfig.json b/packages/apidom-parser-adapter-asyncapi-json-3/tsconfig.json new file mode 100644 index 0000000000..5cc50cd885 --- /dev/null +++ b/packages/apidom-parser-adapter-asyncapi-json-3/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/packages/apidom-parser-adapter-asyncapi-yaml-3/package.json b/packages/apidom-parser-adapter-asyncapi-yaml-3/package.json index 3440c6c0ed..51b02f5d73 100644 --- a/packages/apidom-parser-adapter-asyncapi-yaml-3/package.json +++ b/packages/apidom-parser-adapter-asyncapi-yaml-3/package.json @@ -44,7 +44,7 @@ "dependencies": { "@babel/runtime-corejs3": "^7.26.10", "@swagger-api/apidom-core": "^1.0.0-rc.3", - "@swagger-api/apidom-ns-asyncapi-3": "1.0.0-beta.0", + "@swagger-api/apidom-ns-asyncapi-3": "^1.0.0-rc.3", "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-rc.3", "@types/ramda": "~0.30.0", "ramda": "~0.30.0",