From d42ea8a1532e53fb29d5a23964fd33ede98f5fdd Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Thu, 7 Sep 2023 17:29:40 +0200 Subject: [PATCH] feat!: optionally include Schema parsers when creating a Parser --- package-lock.json | 288 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 4 + src/parse.ts | 62 ++++++---- test/parse.spec.ts | 80 +++++++++---- 4 files changed, 387 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb18358..5f2f534 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,18 @@ { "name": "@smoya/multi-parser", - "version": "0.1.0", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@smoya/multi-parser", - "version": "0.1.0", + "version": "2.0.0", "license": "Apache-2.0", "dependencies": { + "@asyncapi/avro-schema-parser": "^3.0.3", + "@asyncapi/openapi-schema-parser": "^3.0.4", + "@asyncapi/protobuf-schema-parser": "^3.0.0", + "@asyncapi/raml-dt-schema-parser": "^4.0.4", "parserv2": "npm:@asyncapi/parser@^2.1.0", "parserv3": "npm:@asyncapi/parser@^2.2.0-next-major-spec.2" }, @@ -53,6 +57,137 @@ "node": ">=6.0.0" } }, + "node_modules/@asyncapi/avro-schema-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-3.0.3.tgz", + "integrity": "sha512-XprbDYPFJ0nc963hPCjbEmM3iu6ypKg/70EFVl0MZJCLbLw/+gBbPy95uV3Qaofm5UQgSI+aTobGhc8rMre4VA==", + "dependencies": { + "@asyncapi/parser": "^2.1.0", + "@types/json-schema": "^7.0.11", + "avsc": "^5.7.6" + } + }, + "node_modules/@asyncapi/openapi-schema-parser": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.4.tgz", + "integrity": "sha512-nfZbL3dTpIQ3K+/V05FBpgOPi7dDWZkqZG8e7pKwtNhwZ0YLBFWTw6RpocztlBlcieFggxZqLm4BT5I1cQbK+Q==", + "dependencies": { + "@asyncapi/parser": "^2.1.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1" + } + }, + "node_modules/@asyncapi/openapi-schema-parser/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@asyncapi/openapi-schema-parser/node_modules/ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "peerDependencies": { + "ajv": "^8.0.1" + } + }, + "node_modules/@asyncapi/openapi-schema-parser/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@asyncapi/parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.1.0.tgz", + "integrity": "sha512-78jjN3eW4ZmgJEa6Ap15lofzADCeItO4wHcAY2Jod3qLB1xf1zFDZQdtm3VSHYLeLhwoC1A33bAtzEf7M5P2bg==", + "dependencies": { + "@asyncapi/specs": "^5.1.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "@stoplight/json-ref-resolver": "^3.1.5", + "@stoplight/spectral-core": "^1.16.1", + "@stoplight/spectral-functions": "^1.7.2", + "@stoplight/spectral-parsers": "^1.0.2", + "@types/json-schema": "^7.0.11", + "@types/urijs": "^1.19.19", + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1", + "avsc": "^5.7.5", + "js-yaml": "^4.1.0", + "jsonpath-plus": "^7.2.0", + "node-fetch": "2.6.7", + "ramldt2jsonschema": "^1.2.3", + "webapi-parser": "^0.5.0" + } + }, + "node_modules/@asyncapi/parser/node_modules/@asyncapi/specs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.1.0.tgz", + "integrity": "sha512-yffhETqehkim43luMnPKOwzY0D0YtU4bKpORIXIaid6p5Y5kDLrMGJaEPkNieQp03HMjhjFrnUPtT8kvqe0+aQ==", + "dependencies": { + "@types/json-schema": "^7.0.11" + } + }, + "node_modules/@asyncapi/parser/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@asyncapi/parser/node_modules/ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "peerDependencies": { + "ajv": "^8.0.1" + } + }, + "node_modules/@asyncapi/parser/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@asyncapi/protobuf-schema-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/protobuf-schema-parser/-/protobuf-schema-parser-3.0.0.tgz", + "integrity": "sha512-kjoLrll611K+xYC/iBUlSnZsCHbrhL999ItVHZhObUOjUB991XgonqbSAaihiiDXTYgceOLhJKAN5llkV/LOOA==", + "dependencies": { + "@asyncapi/parser": "^2.1.0", + "@types/protocol-buffers-schema": "^3.4.1", + "protocol-buffers-schema": "^3.6.0" + } + }, + "node_modules/@asyncapi/raml-dt-schema-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.4.tgz", + "integrity": "sha512-kKam4jwYYdwqoV5zkEb3YEb8VOrN0785fc4ByazxRd+BT/RnkQTLspjTY/akdDs9DLmU4ChP73Z0vqpek6wojA==", + "dependencies": { + "@asyncapi/parser": "^2.1.0", + "js-yaml": "^4.1.0", + "ramldt2jsonschema": "^1.2.3", + "webapi-parser": "^0.5.0" + } + }, "node_modules/@asyncapi/specs": { "version": "6.0.0-next-major-spec.6", "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.0.0-next-major-spec.6.tgz", @@ -2193,6 +2328,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" }, + "node_modules/@types/protocol-buffers-schema": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@types/protocol-buffers-schema/-/protocol-buffers-schema-3.4.1.tgz", + "integrity": "sha512-CBpqIDa1+/F3Z5EL8Uz/t+1eygIinJiMS37KP8O9TN+n38OlckYQhU+t/vYpsF7XhSDuiZS0zAJyfRrAeDKDUw==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", @@ -7908,6 +8051,11 @@ "node": ">= 6" } }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "node_modules/pure-rand": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", @@ -9594,6 +9742,129 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, + "@asyncapi/avro-schema-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-3.0.3.tgz", + "integrity": "sha512-XprbDYPFJ0nc963hPCjbEmM3iu6ypKg/70EFVl0MZJCLbLw/+gBbPy95uV3Qaofm5UQgSI+aTobGhc8rMre4VA==", + "requires": { + "@asyncapi/parser": "^2.1.0", + "@types/json-schema": "^7.0.11", + "avsc": "^5.7.6" + } + }, + "@asyncapi/openapi-schema-parser": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.4.tgz", + "integrity": "sha512-nfZbL3dTpIQ3K+/V05FBpgOPi7dDWZkqZG8e7pKwtNhwZ0YLBFWTw6RpocztlBlcieFggxZqLm4BT5I1cQbK+Q==", + "requires": { + "@asyncapi/parser": "^2.1.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "requires": {} + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "@asyncapi/parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.1.0.tgz", + "integrity": "sha512-78jjN3eW4ZmgJEa6Ap15lofzADCeItO4wHcAY2Jod3qLB1xf1zFDZQdtm3VSHYLeLhwoC1A33bAtzEf7M5P2bg==", + "requires": { + "@asyncapi/specs": "^5.1.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "@stoplight/json-ref-resolver": "^3.1.5", + "@stoplight/spectral-core": "^1.16.1", + "@stoplight/spectral-functions": "^1.7.2", + "@stoplight/spectral-parsers": "^1.0.2", + "@types/json-schema": "^7.0.11", + "@types/urijs": "^1.19.19", + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1", + "avsc": "^5.7.5", + "js-yaml": "^4.1.0", + "jsonpath-plus": "^7.2.0", + "node-fetch": "2.6.7", + "ramldt2jsonschema": "^1.2.3", + "webapi-parser": "^0.5.0" + }, + "dependencies": { + "@asyncapi/specs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.1.0.tgz", + "integrity": "sha512-yffhETqehkim43luMnPKOwzY0D0YtU4bKpORIXIaid6p5Y5kDLrMGJaEPkNieQp03HMjhjFrnUPtT8kvqe0+aQ==", + "requires": { + "@types/json-schema": "^7.0.11" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "requires": {} + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "@asyncapi/protobuf-schema-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/protobuf-schema-parser/-/protobuf-schema-parser-3.0.0.tgz", + "integrity": "sha512-kjoLrll611K+xYC/iBUlSnZsCHbrhL999ItVHZhObUOjUB991XgonqbSAaihiiDXTYgceOLhJKAN5llkV/LOOA==", + "requires": { + "@asyncapi/parser": "^2.1.0", + "@types/protocol-buffers-schema": "^3.4.1", + "protocol-buffers-schema": "^3.6.0" + } + }, + "@asyncapi/raml-dt-schema-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.4.tgz", + "integrity": "sha512-kKam4jwYYdwqoV5zkEb3YEb8VOrN0785fc4ByazxRd+BT/RnkQTLspjTY/akdDs9DLmU4ChP73Z0vqpek6wojA==", + "requires": { + "@asyncapi/parser": "^2.1.0", + "js-yaml": "^4.1.0", + "ramldt2jsonschema": "^1.2.3", + "webapi-parser": "^0.5.0" + } + }, "@asyncapi/specs": { "version": "6.0.0-next-major-spec.6", "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.0.0-next-major-spec.6.tgz", @@ -11239,6 +11510,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" }, + "@types/protocol-buffers-schema": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@types/protocol-buffers-schema/-/protocol-buffers-schema-3.4.1.tgz", + "integrity": "sha512-CBpqIDa1+/F3Z5EL8Uz/t+1eygIinJiMS37KP8O9TN+n38OlckYQhU+t/vYpsF7XhSDuiZS0zAJyfRrAeDKDUw==", + "requires": { + "@types/node": "*" + } + }, "@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", @@ -15454,6 +15733,11 @@ "sisteransi": "^1.0.5" } }, + "protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "pure-rand": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", diff --git a/package.json b/package.json index 1c2c20e..3f17a55 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,10 @@ "prepublishOnly": "npm run generate:assets" }, "dependencies": { + "@asyncapi/avro-schema-parser": "^3.0.3", + "@asyncapi/openapi-schema-parser": "^3.0.4", + "@asyncapi/protobuf-schema-parser": "^3.0.0", + "@asyncapi/raml-dt-schema-parser": "^4.0.4", "parserv2": "npm:@asyncapi/parser@^2.1.0", "parserv3": "npm:@asyncapi/parser@^2.2.0-next-major-spec.2" }, diff --git a/src/parse.ts b/src/parse.ts index 56d51c6..aa5eda5 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -1,36 +1,54 @@ import { Parser as ParserV2 } from 'parserv2'; import { Parser as ParserV3 } from 'parserv3'; -import type { ParseOptions as ParserOptionsParserV2 } from 'parserv2'; -import type { ParseOptions as ParserOptionsParserV3 } from 'parserv3'; +import { AvroSchemaParser } from '@asyncapi/avro-schema-parser'; +import { OpenAPISchemaParser } from '@asyncapi/openapi-schema-parser'; +import { RamlDTSchemaParser } from '@asyncapi/raml-dt-schema-parser'; +import { ProtoBuffSchemaParser } from '@asyncapi/protobuf-schema-parser'; + +import type { ParserOptions as ParserOptionsParserV2 } from 'parserv2/esm/parser'; +import type { ParserOptions as ParserOptionsParserV3 } from 'parserv3/esm/parser'; import { majorParserAPIVersion } from './utils'; -type Parser = ParserV2 | ParserV3; +export type ParserOptions = ParserOptionsParserV2 | ParserOptionsParserV3; +export type Options = { + includeSchemaParsers?: boolean; + parserOptions?: ParserOptions; +} -// Cache for parsers -const parsers = new Map(); +type Parser = ParserV2 | ParserV3; -export function NewParser(parserAPIVersion: string, options?: ParserOptionsParserV2 | ParserOptionsParserV3): Parser { - const parserAPIMajorVersion = majorParserAPIVersion(parserAPIVersion); - +export function NewParser(parserAPIVersion: string, options?: Options): Parser { + const parserOptions: ParserOptions = options?.parserOptions || {}; + + // This is done globally instead of per version because latest versions of those schema parsers are still compatible with newer versions of the Parser-JS. + // If a breaking change is introduced in the future, then we would need to register the schema parsers compatible with each version of the Parser-JS. + if (options?.includeSchemaParsers) { + const defaultSchemaParsers = [ + AvroSchemaParser(), + OpenAPISchemaParser(), + RamlDTSchemaParser(), + ProtoBuffSchemaParser(), + ]; + + if (!parserOptions.schemaParsers) { + parserOptions.schemaParsers = defaultSchemaParsers; + } else { + // If the user provides a schema parser, use that one instead of the default one. Comparison is done with the mime types. + const givenSchemaParsersMimeTypes = parserOptions.schemaParsers.map((schemaParser) => schemaParser.getMimeTypes()).flat(); + const filteredDefaultSchemas = defaultSchemaParsers.filter((defaultSchemaParser) => !givenSchemaParsersMimeTypes.includes(defaultSchemaParser.getMimeTypes()[0])); + parserOptions.schemaParsers.push(...filteredDefaultSchemas as any); + } + } + + const parserAPIMajorVersion = majorParserAPIVersion(parserAPIVersion); switch (parserAPIMajorVersion) { case 1: - if (options) { - return new ParserV2(options); // Can't use cached because options is not empty - } - - if (!parsers.has(2)) parsers.set(2, new ParserV2()); - return parsers.get(2) as ParserV2; + return new ParserV2(parserOptions as ParserOptionsParserV2); default: case 0: // Using Parser v3 (latest atm) by default case 2: - if (options) { - return new ParserV3(options); // Can't use cached because options is not empty - } - - if (!parsers.has(3)) parsers.set(3, new ParserV3()); - return parsers.get(3) as ParserV3; + return new ParserV3(parserOptions as ParserOptionsParserV3); } -} - +} \ No newline at end of file diff --git a/test/parse.spec.ts b/test/parse.spec.ts index 4e5551d..5a50769 100644 --- a/test/parse.spec.ts +++ b/test/parse.spec.ts @@ -2,57 +2,91 @@ import { Parser as ParserV2 } from 'parserv2'; import { Parser as ParserV3 } from 'parserv3'; +import { AvroSchemaParser } from '@asyncapi/avro-schema-parser'; +import { OpenAPISchemaParser } from '@asyncapi/openapi-schema-parser'; +import { RamlDTSchemaParser } from '@asyncapi/raml-dt-schema-parser'; +import { ProtoBuffSchemaParser } from '@asyncapi/protobuf-schema-parser'; + import { NewParser } from '../src/index'; +import type { Options } from '../src/parse'; + +const fakeSchemaParser = { + validate: jest.fn().mockReturnValue(Promise.resolve(null)), + parse: jest.fn().mockReturnValue(Promise.resolve({})), + getMimeTypes: jest.fn().mockReturnValue(['fake-format']), +}; describe('NewParser()', function() { it('Creates a Parser without options compatible with Parser-API v1 and caches it', async function() { const parser = NewParser('1.0.0'); expect(parser).toBeInstanceOf(ParserV2); - - // Test cached parser is the same as the one we previously created. - expect(NewParser('1.0.0')).toStrictEqual(parser); }); - it('Creates a Parser with options compatible with Parser-API v1 and skips cache', async function() { - const options = { applyTraits: false }; + it('Creates a Parser with options compatible with Parser-API v1', async function() { + const options: Options = { parserOptions: { schemaParsers: [fakeSchemaParser]} }; const parser = NewParser('1.0.0', options); + expect(parser).toBeInstanceOf(ParserV2); + expect(parser.parserRegistry.get('fake-format')).not.toBeUndefined(); + }); - // Test no cached parser is returned - expect(NewParser('1.0.0', options)).not.toStrictEqual(parser); + it('Creates a Parser with options including known Schema Parsers and do not overwrite those with Parser-API v1', async function() { + const knownSchemaParser = AvroSchemaParser(); + const options: Options = { parserOptions: { schemaParsers: [knownSchemaParser]}, includeSchemaParsers: true }; + const parser = NewParser('1.0.0', options); + + expect(parser).toBeInstanceOf(ParserV2); + expect(parser.parserRegistry.get(knownSchemaParser.getMimeTypes()[0])).toStrictEqual(knownSchemaParser); + expect(parser.parserRegistry.get(OpenAPISchemaParser().getMimeTypes()[0])).toEqual(OpenAPISchemaParser()); + expect(parser.parserRegistry.get(RamlDTSchemaParser().getMimeTypes()[0])).toEqual(RamlDTSchemaParser()); + expect(parser.parserRegistry.get(ProtoBuffSchemaParser().getMimeTypes()[0])).toEqual(ProtoBuffSchemaParser()); }); - it('Creates a Parser without options compatible with Parser-API v2 and caches it', async function() { + it('Creates a Parser without options compatible with Parser-API v2', async function() { const parser = NewParser('2.0.0'); expect(parser).toBeInstanceOf(ParserV3); - - // Test cached parser is the same as the one we previously created. - expect(NewParser('2.0.0')).toStrictEqual(parser); }); - it('Creates a Parser with options compatible with Parser-API v2 and skips cache', async function() { - const options = { applyTraits: false }; + it('Creates a Parser with options compatible with Parser-API v2', async function() { + const options: Options = { parserOptions: { schemaParsers: [fakeSchemaParser]} }; const parser = NewParser('2.0.0', options); expect(parser).toBeInstanceOf(ParserV3); + expect(parser.parserRegistry.get('fake-format')).not.toBeUndefined(); + }); - // Test no cached parser is returned - expect(NewParser('2.0.0', options)).not.toStrictEqual(parser); + it('Creates a Parser with options including known Schema Parsers and do not overwrite those with Parser-API v2', async function() { + const knownSchemaParser = AvroSchemaParser(); + const options: Options = { parserOptions: { schemaParsers: [knownSchemaParser]}, includeSchemaParsers: true }; + const parser = NewParser('2.0.0', options); + + expect(parser).toBeInstanceOf(ParserV3); + expect(parser.parserRegistry.get(knownSchemaParser.getMimeTypes()[0])).toStrictEqual(knownSchemaParser); + expect(parser.parserRegistry.get(OpenAPISchemaParser().getMimeTypes()[0])).toEqual(OpenAPISchemaParser()); + expect(parser.parserRegistry.get(RamlDTSchemaParser().getMimeTypes()[0])).toEqual(RamlDTSchemaParser()); + expect(parser.parserRegistry.get(ProtoBuffSchemaParser().getMimeTypes()[0])).toEqual(ProtoBuffSchemaParser()); }); - it('Creates a Parser without options compatible with old Parser API (AKA v0) and caches it', async function() { + it('Creates a Parser without options compatible with old Parser API (AKA v0)', async function() { const parser = NewParser(''); // could be '0.0.0' as well expect(parser).toBeInstanceOf(ParserV3); // Using Parser v3 (latest atm) by default - - // Test cached parser is the same as the one we previously created. - expect(NewParser('')).toStrictEqual(parser); }); - it('Creates a Parser with options compatible with old Parser API (AKA v0) and skips cache', async function() { - const options = { applyTraits: false }; + it('Creates a Parser with options compatible with old Parser API (AKA v0)', async function() { + const options: Options = { parserOptions: { schemaParsers: [fakeSchemaParser]} }; const parser = NewParser('0.0.0', options); // could be empty string as well expect(parser).toBeInstanceOf(ParserV3); + expect(parser.parserRegistry.get('fake-format')).not.toBeUndefined(); + }); - // Test no cached parser is returned - expect(NewParser('0.0.0', options)).not.toStrictEqual(parser); + it('Creates a Parser with options including known Schema Parsers and do not overwrite those with Parser-API v2', async function() { + const knownSchemaParser = AvroSchemaParser(); + const options: Options = { parserOptions: { schemaParsers: [knownSchemaParser]}, includeSchemaParsers: true }; + const parser = NewParser('0.0.0', options); + + expect(parser).toBeInstanceOf(ParserV3); + expect(parser.parserRegistry.get(knownSchemaParser.getMimeTypes()[0])).toStrictEqual(knownSchemaParser); + expect(parser.parserRegistry.get(OpenAPISchemaParser().getMimeTypes()[0])).toEqual(OpenAPISchemaParser()); + expect(parser.parserRegistry.get(RamlDTSchemaParser().getMimeTypes()[0])).toEqual(RamlDTSchemaParser()); + expect(parser.parserRegistry.get(ProtoBuffSchemaParser().getMimeTypes()[0])).toEqual(ProtoBuffSchemaParser()); }); }); \ No newline at end of file