From dbd5e0d3665b3f8c21fd255ccb10d8d24623e9a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84czyk?= Date: Mon, 29 Aug 2022 12:51:24 +0200 Subject: [PATCH] refactor: integrate custom schemas with parser and spectral (#579) --- package-lock.json | 1284 ++++++++++++++--- package.json | 8 +- src/constants.ts | 1 + src/custom-operations/parse-schema.ts | 17 +- src/parse.ts | 5 +- src/parser.ts | 13 +- src/schema-parser/asyncapi-schema-parser.ts | 9 +- src/schema-parser/avro-schema-parser.ts | 62 +- src/schema-parser/index.ts | 14 +- src/schema-parser/openapi-schema-parser.ts | 50 +- src/schema-parser/raml-schema-parser.ts | 38 +- src/schema-parser/spectral-rule-v2.ts | 101 ++ src/spectral.ts | 24 + src/utils.ts | 4 + test/custom-operations/parse-schema.spec.ts | 96 ++ test/parser.spec.ts | 3 +- .../asyncapi-schema-parser.spec.ts | 6 +- .../avro/avro-schema-parser.spec.ts | 49 +- .../openapi/openapi-schema-parser.spec.ts | 13 +- .../raml/raml-schema-parser.spec.ts | 15 +- test/schema-parser/spectral-rule-v2.spec.ts | 305 ++++ 21 files changed, 1746 insertions(+), 371 deletions(-) create mode 100644 src/schema-parser/spectral-rule-v2.ts create mode 100644 src/spectral.ts create mode 100644 test/custom-operations/parse-schema.spec.ts create mode 100644 test/schema-parser/spectral-rule-v2.spec.ts diff --git a/package-lock.json b/package-lock.json index 60175b4e8..81c6ec26b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "dependencies": { "@asyncapi/specs": "^3.1.0", "@openapi-contrib/openapi-schema-to-json-schema": "^3.2.0", - "@stoplight/spectral-core": "^1.10.1", - "@stoplight/spectral-functions": "^1.5.1", - "@stoplight/spectral-parsers": "^1.0.1", - "@stoplight/spectral-rulesets": "^1.4.3", + "@stoplight/spectral-core": "^1.13.1", + "@stoplight/spectral-functions": "^1.7.1", + "@stoplight/spectral-parsers": "^1.0.2", + "@stoplight/spectral-rulesets": "^1.12.0", "ajv": "^8.11.0", "avsc": "^5.7.4", "js-yaml": "^3.14.1", @@ -1393,9 +1393,9 @@ } }, "node_modules/@jsep-plugin/regex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.1.tgz", - "integrity": "sha512-GroTtexnEfdVOvvALjW/JfV+wgRMadZKEA/lf9gE09zJejHhcBl+cqJxk2px9ub8k3gUrPe1j81Z1V4RDaSy8A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.2.tgz", + "integrity": "sha512-Nn/Bcaww8zOebMDqNmGlhAWPWhIr/8S8lGIgaB/fSqev5xaO5uKy5i4qvTh63GpR+VzKqimgxDdcxdcRuCJXSw==", "engines": { "node": ">= 10.16.0" }, @@ -1404,9 +1404,9 @@ } }, "node_modules/@jsep-plugin/ternary": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsep-plugin/ternary/-/ternary-1.1.0.tgz", - "integrity": "sha512-dS+vdBz0y71mRspSsv/c+YUm8xXKiEqgZF7+ERxNLWyycMOOtR9CQjV+MexpTCCh76iBrMHcWul9rzoZdfJm0g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsep-plugin/ternary/-/ternary-1.1.2.tgz", + "integrity": "sha512-gXguJc09uCrqWt1MD7L1+ChO32g4UH4BYGpHPoQRLhyU7pAPPRA7cvKbyjoqhnUlLutiXvLzB5hVVawPKax8jw==", "engines": { "node": ">= 10.16.0" }, @@ -1962,13 +1962,29 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@stoplight/better-ajv-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz", + "integrity": "sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==", + "dependencies": { + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": "^12.20 || >= 14.13" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, "node_modules/@stoplight/json": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.17.2.tgz", - "integrity": "sha512-NwIVzanXRUy291J5BMkncCZRMG1Lx+aq+VidGQgfkJjgo8vh1Y/PSAz7fSU8gVGSZBCcqmOkMI7R4zw7DlfTwA==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", + "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.2", - "@stoplight/types": "^12.3.0", + "@stoplight/ordered-object-literal": "^1.0.3", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", "jsonc-parser": "~2.2.1", "lodash": "^4.17.21", "safe-stable-stringify": "^1.1" @@ -2015,6 +2031,18 @@ "node": ">=8.3.0" } }, + "node_modules/@stoplight/json/node_modules/@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, "node_modules/@stoplight/lifecycle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@stoplight/lifecycle/-/lifecycle-2.3.2.tgz", @@ -2027,9 +2055,9 @@ } }, "node_modules/@stoplight/ordered-object-literal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.2.tgz", - "integrity": "sha512-0ZMS/9sNU3kVo/6RF3eAv7MK9DY8WLjiVJB/tVyfF2lhr2R4kqh534jZ0PlrFB9CRXrdndzn1DbX6ihKZXft2w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.3.tgz", + "integrity": "sha512-cjJ7PPkhgTXNMTkevAlmyrx9xOOCaI3c6rEeYb6VitL1o1WcZtrz9KyFyISmTmUa7yYTiy2IS/ud9S8s2sn3+A==", "engines": { "node": ">=8" } @@ -2043,28 +2071,30 @@ } }, "node_modules/@stoplight/spectral-core": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.11.0.tgz", - "integrity": "sha512-82xWLbQn67cLLKL7lQJsXTFLIHSOlwv4Faq2IxsUFMWqQ84znwd7FxOkfk9K2I0ncR+XuaftWRtN9ySvVSJkAw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.13.1.tgz", + "integrity": "sha512-0az1LZ/A7b6u8HESzBMv65syZXjsYhpQxvtQ2F9D50G7+AvvDsvQa3myk1J3lz4hY4dU1quW2xGgan9mE+XDhA==", "dependencies": { - "@stoplight/better-ajv-errors": "1.0.1", - "@stoplight/json": "~3.17.1", + "@stoplight/better-ajv-errors": "1.0.3", + "@stoplight/json": "~3.20.1", "@stoplight/lifecycle": "2.3.2", "@stoplight/path": "1.3.2", "@stoplight/spectral-parsers": "^1.0.0", "@stoplight/spectral-ref-resolver": "^1.0.0", "@stoplight/spectral-runtime": "^1.0.0", - "@stoplight/types": "12.3.0", + "@stoplight/types": "~13.6.0", + "@types/es-aggregate-error": "^1.0.2", + "@types/json-schema": "^7.0.11", "ajv": "^8.6.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.0", "blueimp-md5": "2.18.0", - "json-schema": "0.4.0", + "es-aggregate-error": "^1.0.7", "jsonpath-plus": "6.0.1", "lodash": "~4.17.21", "lodash.topath": "^4.5.2", - "minimatch": "3.0.4", - "nimma": "0.1.8", + "minimatch": "3.1.2", + "nimma": "0.2.2", "pony-cause": "^1.0.0", "simple-eval": "1.0.0", "tslib": "^2.3.0" @@ -2073,19 +2103,16 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/@stoplight/spectral-core/node_modules/@stoplight/better-ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.1.tgz", - "integrity": "sha512-rgxT+ZMeZbYRiOLNk6Oy6e/Ig1iQKo0IL8v/Y9E/0FewzgtkGs/p5dMeUpIFZXWj3RZaEPmfL9yh0oUEmNXZjg==", + "node_modules/@stoplight/spectral-core/node_modules/@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", "dependencies": { - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" }, "engines": { - "node": "^12.20 || >= 14.13" - }, - "peerDependencies": { - "ajv": ">=8" + "node": "^12.20 || >=14.13" } }, "node_modules/@stoplight/spectral-core/node_modules/ajv-errors": { @@ -2097,9 +2124,9 @@ } }, "node_modules/@stoplight/spectral-formats": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-formats/-/spectral-formats-1.1.0.tgz", - "integrity": "sha512-ZpEHNkS30qfPbxHJAf3OwZ7g0LkSG2UZXhl3/Jsf6WGivVcuQUY+ZK4c1ZJqBNct1JF1ujP3FgF26xDdTrOtDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-formats/-/spectral-formats-1.2.0.tgz", + "integrity": "sha512-idvn7r8fvQjY/KeJpKgXQ5eJhce6N6/KoKWMPSh5yyvYDpn+bkU4pxAD79jOJaDnIyKJd1jjTPEJWnxbS0jj6A==", "dependencies": { "@stoplight/json": "^3.17.0", "@stoplight/spectral-core": "^1.8.0", @@ -2111,16 +2138,15 @@ } }, "node_modules/@stoplight/spectral-functions": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.6.1.tgz", - "integrity": "sha512-f4cFtbI35bQtY0t4fYhKtS+/nMU3UsAeFlqm4tARGGG5WjOv4ieCFNFbgodKNiO3F4O+syMEjVQuXlBNPuY7jw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.7.1.tgz", + "integrity": "sha512-UWeUrxc1pu45ZNYKtK3OloMpkUNTPqwpmjbGUn4oEnbqrLEYu/B2oOg66EtGcadOBEsdOb7f5vaPlhUNNrpEpQ==", "dependencies": { - "@stoplight/better-ajv-errors": "1.0.1", - "@stoplight/json": "~3.17.1", + "@stoplight/better-ajv-errors": "1.0.3", + "@stoplight/json": "^3.17.1", "@stoplight/spectral-core": "^1.7.0", "@stoplight/spectral-formats": "^1.0.0", "@stoplight/spectral-runtime": "^1.1.0", - "@stoplight/types": "12.3.0", "ajv": "^8.6.3", "ajv-draft-04": "~1.0.0", "ajv-errors": "~3.0.0", @@ -2132,21 +2158,6 @@ "node": ">=12" } }, - "node_modules/@stoplight/spectral-functions/node_modules/@stoplight/better-ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.1.tgz", - "integrity": "sha512-rgxT+ZMeZbYRiOLNk6Oy6e/Ig1iQKo0IL8v/Y9E/0FewzgtkGs/p5dMeUpIFZXWj3RZaEPmfL9yh0oUEmNXZjg==", - "dependencies": { - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" - }, - "engines": { - "node": "^12.20 || >= 14.13" - }, - "peerDependencies": { - "ajv": ">=8" - } - }, "node_modules/@stoplight/spectral-functions/node_modules/ajv-draft-04": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", @@ -2169,32 +2180,29 @@ } }, "node_modules/@stoplight/spectral-parsers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-parsers/-/spectral-parsers-1.0.1.tgz", - "integrity": "sha512-JGKlrTxhjUzIGo2FOCf8Qp0WKTWXedoRNPovqYPE8pAp08epqU8DzHwl/i46BGH5yfTmouKMZgBN/PV2+Cr5jw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-parsers/-/spectral-parsers-1.0.2.tgz", + "integrity": "sha512-ZQXknJ+BM5Re4Opj4cgVlHgG2qyOk/wznKJq3Vf1qsBEg2CNzN0pJmSB0deRqW0kArqm44qpb8c+cz3F2rgMtw==", "dependencies": { - "@stoplight/json": "3.17.0", - "@stoplight/types": "12.3.0", - "@stoplight/yaml": "4.2.2", + "@stoplight/json": "~3.20.1", + "@stoplight/types": "^13.6.0", + "@stoplight/yaml": "~4.2.3", "tslib": "^2.3.1" }, "engines": { "node": ">=12" } }, - "node_modules/@stoplight/spectral-parsers/node_modules/@stoplight/json": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.17.0.tgz", - "integrity": "sha512-WW0z2bb0D4t8FTl+zNTCu46J8lEOsrUhBPgwEYQ3Ri2Y0MiRE4U1/9ZV8Ki+pIJznZgY9i42bbFwOBxyZn5/6w==", + "node_modules/@stoplight/spectral-parsers/node_modules/@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.2", - "@stoplight/types": "^12.3.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" }, "engines": { - "node": ">=8.3.0" + "node": "^12.20 || >=14.13" } }, "node_modules/@stoplight/spectral-ref-resolver": { @@ -2213,18 +2221,18 @@ } }, "node_modules/@stoplight/spectral-rulesets": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.6.0.tgz", - "integrity": "sha512-iRfcG5Ucp2OPGszaergiN+shVkD9XO1VKRmFqXlYbLxI8oi0jBAFXQr+tKJGt6ErXBQQoaIx2Liiirgq7kR3Nw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.12.0.tgz", + "integrity": "sha512-ktSO5YPzYzscnGTQffyKJwrzsR2i5cpPUC4yBp0isc6mOeiVec4r9sjMUN1mJt0RVnXi509vd0+YlMthFIZYnw==", "dependencies": { - "@asyncapi/specs": "^2.13.0", - "@stoplight/better-ajv-errors": "1.0.1", + "@asyncapi/specs": "^2.14.0", + "@stoplight/better-ajv-errors": "1.0.3", "@stoplight/json": "^3.17.0", "@stoplight/spectral-core": "^1.8.1", - "@stoplight/spectral-formats": "^1.1.0", + "@stoplight/spectral-formats": "^1.2.0", "@stoplight/spectral-functions": "^1.5.1", "@stoplight/spectral-runtime": "^1.1.1", - "@stoplight/types": "^12.3.0", + "@stoplight/types": "^13.6.0", "@types/json-schema": "^7.0.7", "ajv": "^8.8.2", "ajv-formats": "~2.1.0", @@ -2241,19 +2249,16 @@ "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-2.14.0.tgz", "integrity": "sha512-hHsYF6XsYNIKb1P2rXaooF4H+uKKQ4b/Ljxrk3rZ3riEDiSxMshMEfb1fUlw9Yj4V4OmJhjXwkNvw8W59AXv1A==" }, - "node_modules/@stoplight/spectral-rulesets/node_modules/@stoplight/better-ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.1.tgz", - "integrity": "sha512-rgxT+ZMeZbYRiOLNk6Oy6e/Ig1iQKo0IL8v/Y9E/0FewzgtkGs/p5dMeUpIFZXWj3RZaEPmfL9yh0oUEmNXZjg==", + "node_modules/@stoplight/spectral-rulesets/node_modules/@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", "dependencies": { - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" }, "engines": { - "node": "^12.20 || >= 14.13" - }, - "peerDependencies": { - "ajv": ">=8" + "node": "^12.20 || >=14.13" } }, "node_modules/@stoplight/spectral-rulesets/node_modules/json-schema-traverse": { @@ -2291,12 +2296,12 @@ } }, "node_modules/@stoplight/yaml": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.2.2.tgz", - "integrity": "sha512-N086FU8pmSpjc5TvMBjmlTniZVh3OXzmEh6SYljSLiuv6aMxgjyjf13YrAlUqgu0b4b6pQ5zmkjrfo9i0SiLsw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.2.3.tgz", + "integrity": "sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==", "dependencies": { "@stoplight/ordered-object-literal": "^1.0.1", - "@stoplight/types": "^12.0.0", + "@stoplight/types": "^13.0.0", "@stoplight/yaml-ast-parser": "0.0.48", "tslib": "^2.2.0" }, @@ -2309,6 +2314,18 @@ "resolved": "https://registry.npmjs.org/@stoplight/yaml-ast-parser/-/yaml-ast-parser-0.0.48.tgz", "integrity": "sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==" }, + "node_modules/@stoplight/yaml/node_modules/@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2383,6 +2400,14 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/es-aggregate-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/es-aggregate-error/-/es-aggregate-error-1.0.2.tgz", + "integrity": "sha512-erqUpFXksaeR2kejKnhnjZjbFxUpGZx4Z7ydNL9ie8tEhXPiZTsLeUDJ6aR1F8j5wWUAtOAQWUqkc7givBJbBA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -2446,8 +2471,7 @@ "node_modules/@types/node": { "version": "17.0.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.0", @@ -2789,9 +2813,9 @@ } }, "node_modules/astring": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.1.tgz", - "integrity": "sha512-Aj3mbwVzj7Vve4I/v2JYOPFkCGM2YS7OqQTNSxmUR+LECRpokuPgAYghePgr6SALDo5bD5DlfbSaYjOzGJZOLQ==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.3.tgz", + "integrity": "sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A==", "bin": { "astring": "bin/astring" } @@ -3089,6 +3113,18 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3708,6 +3744,21 @@ "node": ">=0.10.0" } }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3956,6 +4007,78 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-aggregate-error": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.8.tgz", + "integrity": "sha512-AKUb5MKLWMozPlFRHOKqWD7yta5uaEhH21qwtnf6FlKjNjTJOoqFi0/G14+FfSkIQhhu6X68Af4xgRC6y8qG4A==", + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "function-bind": "^1.1.1", + "functions-have-names": "^1.2.3", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.2", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -4782,8 +4905,24 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -4791,6 +4930,14 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4809,6 +4956,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -4830,6 +4990,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -4922,6 +5097,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", @@ -5011,7 +5200,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -5019,6 +5207,14 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -5028,6 +5224,42 @@ "node": ">=4" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hook-std": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz", @@ -5220,6 +5452,19 @@ "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", "dev": true }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/into-stream": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-5.1.1.tgz", @@ -5239,12 +5484,49 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", @@ -5257,6 +5539,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -5305,6 +5601,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5314,6 +5621,20 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -5347,6 +5668,32 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", @@ -5356,6 +5703,34 @@ "node": ">=8" } }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -5374,6 +5749,17 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -7364,11 +7750,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "node_modules/json-schema-migrate": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-0.2.0.tgz", @@ -7465,9 +7846,9 @@ } }, "node_modules/jsonpointer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", - "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", "engines": { "node": ">=0.10.0" } @@ -7700,7 +8081,7 @@ "node_modules/lodash.topath": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", - "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" + "integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==" }, "node_modules/lodash.truncate": { "version": "4.4.2", @@ -8019,9 +8400,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8128,9 +8509,9 @@ "dev": true }, "node_modules/nimma": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/nimma/-/nimma-0.1.8.tgz", - "integrity": "sha512-9gbBqjwngJHJYIIY9OARuCU3eyy/Pl4rRmZAkj1lBMaJVWZZPUOyj90I9jMBe8uNlp4+55J3W2z2CPSJFFar/g==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/nimma/-/nimma-0.2.2.tgz", + "integrity": "sha512-V52MLl7BU+tH2Np9tDrIXK8bql3MVUadnMIl/0/oZSGC9keuro0O9UUv9QKp0aMvtN8HRew4G7byY7H4eWsxaQ==", "dependencies": { "@jsep-plugin/regex": "^1.0.1", "@jsep-plugin/ternary": "^1.0.2", @@ -12858,6 +13239,39 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -13493,6 +13907,22 @@ "esprima": "~4.0.0" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -14013,6 +14443,19 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -14281,6 +14724,32 @@ "node": ">=8" } }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -14817,6 +15286,20 @@ "node": ">=0.8.0" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -15005,6 +15488,21 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wolfy87-eventemitter": { "version": "5.2.9", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", @@ -16220,15 +16718,15 @@ } }, "@jsep-plugin/regex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.1.tgz", - "integrity": "sha512-GroTtexnEfdVOvvALjW/JfV+wgRMadZKEA/lf9gE09zJejHhcBl+cqJxk2px9ub8k3gUrPe1j81Z1V4RDaSy8A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.2.tgz", + "integrity": "sha512-Nn/Bcaww8zOebMDqNmGlhAWPWhIr/8S8lGIgaB/fSqev5xaO5uKy5i4qvTh63GpR+VzKqimgxDdcxdcRuCJXSw==", "requires": {} }, "@jsep-plugin/ternary": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsep-plugin/ternary/-/ternary-1.1.0.tgz", - "integrity": "sha512-dS+vdBz0y71mRspSsv/c+YUm8xXKiEqgZF7+ERxNLWyycMOOtR9CQjV+MexpTCCh76iBrMHcWul9rzoZdfJm0g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsep-plugin/ternary/-/ternary-1.1.2.tgz", + "integrity": "sha512-gXguJc09uCrqWt1MD7L1+ChO32g4UH4BYGpHPoQRLhyU7pAPPRA7cvKbyjoqhnUlLutiXvLzB5hVVawPKax8jw==", "requires": {} }, "@nodelib/fs.scandir": { @@ -16677,16 +17175,37 @@ "@sinonjs/commons": "^1.7.0" } }, + "@stoplight/better-ajv-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz", + "integrity": "sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==", + "requires": { + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, "@stoplight/json": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.17.2.tgz", - "integrity": "sha512-NwIVzanXRUy291J5BMkncCZRMG1Lx+aq+VidGQgfkJjgo8vh1Y/PSAz7fSU8gVGSZBCcqmOkMI7R4zw7DlfTwA==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", + "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", "requires": { - "@stoplight/ordered-object-literal": "^1.0.2", - "@stoplight/types": "^12.3.0", + "@stoplight/ordered-object-literal": "^1.0.3", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", "jsonc-parser": "~2.2.1", "lodash": "^4.17.21", "safe-stable-stringify": "^1.1" + }, + "dependencies": { + "@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", + "requires": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + } + } } }, "@stoplight/json-ref-readers": { @@ -16732,9 +17251,9 @@ } }, "@stoplight/ordered-object-literal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.2.tgz", - "integrity": "sha512-0ZMS/9sNU3kVo/6RF3eAv7MK9DY8WLjiVJB/tVyfF2lhr2R4kqh534jZ0PlrFB9CRXrdndzn1DbX6ihKZXft2w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.3.tgz", + "integrity": "sha512-cjJ7PPkhgTXNMTkevAlmyrx9xOOCaI3c6rEeYb6VitL1o1WcZtrz9KyFyISmTmUa7yYTiy2IS/ud9S8s2sn3+A==" }, "@stoplight/path": { "version": "1.3.2", @@ -16742,40 +17261,42 @@ "integrity": "sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==" }, "@stoplight/spectral-core": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.11.0.tgz", - "integrity": "sha512-82xWLbQn67cLLKL7lQJsXTFLIHSOlwv4Faq2IxsUFMWqQ84znwd7FxOkfk9K2I0ncR+XuaftWRtN9ySvVSJkAw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.13.1.tgz", + "integrity": "sha512-0az1LZ/A7b6u8HESzBMv65syZXjsYhpQxvtQ2F9D50G7+AvvDsvQa3myk1J3lz4hY4dU1quW2xGgan9mE+XDhA==", "requires": { - "@stoplight/better-ajv-errors": "1.0.1", - "@stoplight/json": "~3.17.1", + "@stoplight/better-ajv-errors": "1.0.3", + "@stoplight/json": "~3.20.1", "@stoplight/lifecycle": "2.3.2", "@stoplight/path": "1.3.2", "@stoplight/spectral-parsers": "^1.0.0", "@stoplight/spectral-ref-resolver": "^1.0.0", "@stoplight/spectral-runtime": "^1.0.0", - "@stoplight/types": "12.3.0", + "@stoplight/types": "~13.6.0", + "@types/es-aggregate-error": "^1.0.2", + "@types/json-schema": "^7.0.11", "ajv": "^8.6.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.0", "blueimp-md5": "2.18.0", - "json-schema": "0.4.0", + "es-aggregate-error": "^1.0.7", "jsonpath-plus": "6.0.1", "lodash": "~4.17.21", "lodash.topath": "^4.5.2", - "minimatch": "3.0.4", - "nimma": "0.1.8", + "minimatch": "3.1.2", + "nimma": "0.2.2", "pony-cause": "^1.0.0", "simple-eval": "1.0.0", "tslib": "^2.3.0" }, "dependencies": { - "@stoplight/better-ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.1.tgz", - "integrity": "sha512-rgxT+ZMeZbYRiOLNk6Oy6e/Ig1iQKo0IL8v/Y9E/0FewzgtkGs/p5dMeUpIFZXWj3RZaEPmfL9yh0oUEmNXZjg==", + "@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", "requires": { - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" } }, "ajv-errors": { @@ -16787,9 +17308,9 @@ } }, "@stoplight/spectral-formats": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-formats/-/spectral-formats-1.1.0.tgz", - "integrity": "sha512-ZpEHNkS30qfPbxHJAf3OwZ7g0LkSG2UZXhl3/Jsf6WGivVcuQUY+ZK4c1ZJqBNct1JF1ujP3FgF26xDdTrOtDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-formats/-/spectral-formats-1.2.0.tgz", + "integrity": "sha512-idvn7r8fvQjY/KeJpKgXQ5eJhce6N6/KoKWMPSh5yyvYDpn+bkU4pxAD79jOJaDnIyKJd1jjTPEJWnxbS0jj6A==", "requires": { "@stoplight/json": "^3.17.0", "@stoplight/spectral-core": "^1.8.0", @@ -16798,16 +17319,15 @@ } }, "@stoplight/spectral-functions": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.6.1.tgz", - "integrity": "sha512-f4cFtbI35bQtY0t4fYhKtS+/nMU3UsAeFlqm4tARGGG5WjOv4ieCFNFbgodKNiO3F4O+syMEjVQuXlBNPuY7jw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.7.1.tgz", + "integrity": "sha512-UWeUrxc1pu45ZNYKtK3OloMpkUNTPqwpmjbGUn4oEnbqrLEYu/B2oOg66EtGcadOBEsdOb7f5vaPlhUNNrpEpQ==", "requires": { - "@stoplight/better-ajv-errors": "1.0.1", - "@stoplight/json": "~3.17.1", + "@stoplight/better-ajv-errors": "1.0.3", + "@stoplight/json": "^3.17.1", "@stoplight/spectral-core": "^1.7.0", "@stoplight/spectral-formats": "^1.0.0", "@stoplight/spectral-runtime": "^1.1.0", - "@stoplight/types": "12.3.0", "ajv": "^8.6.3", "ajv-draft-04": "~1.0.0", "ajv-errors": "~3.0.0", @@ -16816,15 +17336,6 @@ "tslib": "^2.3.0" }, "dependencies": { - "@stoplight/better-ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.1.tgz", - "integrity": "sha512-rgxT+ZMeZbYRiOLNk6Oy6e/Ig1iQKo0IL8v/Y9E/0FewzgtkGs/p5dMeUpIFZXWj3RZaEPmfL9yh0oUEmNXZjg==", - "requires": { - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" - } - }, "ajv-draft-04": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", @@ -16840,26 +17351,23 @@ } }, "@stoplight/spectral-parsers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-parsers/-/spectral-parsers-1.0.1.tgz", - "integrity": "sha512-JGKlrTxhjUzIGo2FOCf8Qp0WKTWXedoRNPovqYPE8pAp08epqU8DzHwl/i46BGH5yfTmouKMZgBN/PV2+Cr5jw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-parsers/-/spectral-parsers-1.0.2.tgz", + "integrity": "sha512-ZQXknJ+BM5Re4Opj4cgVlHgG2qyOk/wznKJq3Vf1qsBEg2CNzN0pJmSB0deRqW0kArqm44qpb8c+cz3F2rgMtw==", "requires": { - "@stoplight/json": "3.17.0", - "@stoplight/types": "12.3.0", - "@stoplight/yaml": "4.2.2", + "@stoplight/json": "~3.20.1", + "@stoplight/types": "^13.6.0", + "@stoplight/yaml": "~4.2.3", "tslib": "^2.3.1" }, "dependencies": { - "@stoplight/json": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.17.0.tgz", - "integrity": "sha512-WW0z2bb0D4t8FTl+zNTCu46J8lEOsrUhBPgwEYQ3Ri2Y0MiRE4U1/9ZV8Ki+pIJznZgY9i42bbFwOBxyZn5/6w==", + "@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", "requires": { - "@stoplight/ordered-object-literal": "^1.0.2", - "@stoplight/types": "^12.3.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" } } } @@ -16877,18 +17385,18 @@ } }, "@stoplight/spectral-rulesets": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.6.0.tgz", - "integrity": "sha512-iRfcG5Ucp2OPGszaergiN+shVkD9XO1VKRmFqXlYbLxI8oi0jBAFXQr+tKJGt6ErXBQQoaIx2Liiirgq7kR3Nw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.12.0.tgz", + "integrity": "sha512-ktSO5YPzYzscnGTQffyKJwrzsR2i5cpPUC4yBp0isc6mOeiVec4r9sjMUN1mJt0RVnXi509vd0+YlMthFIZYnw==", "requires": { - "@asyncapi/specs": "^2.13.0", - "@stoplight/better-ajv-errors": "1.0.1", + "@asyncapi/specs": "^2.14.0", + "@stoplight/better-ajv-errors": "1.0.3", "@stoplight/json": "^3.17.0", "@stoplight/spectral-core": "^1.8.1", - "@stoplight/spectral-formats": "^1.1.0", + "@stoplight/spectral-formats": "^1.2.0", "@stoplight/spectral-functions": "^1.5.1", "@stoplight/spectral-runtime": "^1.1.1", - "@stoplight/types": "^12.3.0", + "@stoplight/types": "^13.6.0", "@types/json-schema": "^7.0.7", "ajv": "^8.8.2", "ajv-formats": "~2.1.0", @@ -16902,13 +17410,13 @@ "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-2.14.0.tgz", "integrity": "sha512-hHsYF6XsYNIKb1P2rXaooF4H+uKKQ4b/Ljxrk3rZ3riEDiSxMshMEfb1fUlw9Yj4V4OmJhjXwkNvw8W59AXv1A==" }, - "@stoplight/better-ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.1.tgz", - "integrity": "sha512-rgxT+ZMeZbYRiOLNk6Oy6e/Ig1iQKo0IL8v/Y9E/0FewzgtkGs/p5dMeUpIFZXWj3RZaEPmfL9yh0oUEmNXZjg==", + "@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", "requires": { - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" } }, "json-schema-traverse": { @@ -16942,14 +17450,25 @@ } }, "@stoplight/yaml": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.2.2.tgz", - "integrity": "sha512-N086FU8pmSpjc5TvMBjmlTniZVh3OXzmEh6SYljSLiuv6aMxgjyjf13YrAlUqgu0b4b6pQ5zmkjrfo9i0SiLsw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.2.3.tgz", + "integrity": "sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==", "requires": { "@stoplight/ordered-object-literal": "^1.0.1", - "@stoplight/types": "^12.0.0", + "@stoplight/types": "^13.0.0", "@stoplight/yaml-ast-parser": "0.0.48", "tslib": "^2.2.0" + }, + "dependencies": { + "@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", + "requires": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + } + } } }, "@stoplight/yaml-ast-parser": { @@ -17028,6 +17547,14 @@ "@babel/types": "^7.3.0" } }, + "@types/es-aggregate-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/es-aggregate-error/-/es-aggregate-error-1.0.2.tgz", + "integrity": "sha512-erqUpFXksaeR2kejKnhnjZjbFxUpGZx4Z7ydNL9ie8tEhXPiZTsLeUDJ6aR1F8j5wWUAtOAQWUqkc7givBJbBA==", + "requires": { + "@types/node": "*" + } + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -17091,8 +17618,7 @@ "@types/node": { "version": "17.0.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -17362,9 +17888,9 @@ "dev": true }, "astring": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.1.tgz", - "integrity": "sha512-Aj3mbwVzj7Vve4I/v2JYOPFkCGM2YS7OqQTNSxmUR+LECRpokuPgAYghePgr6SALDo5bD5DlfbSaYjOzGJZOLQ==" + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.3.tgz", + "integrity": "sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A==" }, "asynckit": { "version": "0.4.0", @@ -17597,6 +18123,15 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -18082,6 +18617,15 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -18275,6 +18819,60 @@ "is-arrayish": "^0.2.1" } }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-aggregate-error": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.8.tgz", + "integrity": "sha512-AKUb5MKLWMozPlFRHOKqWD7yta5uaEhH21qwtnf6FlKjNjTJOoqFi0/G14+FfSkIQhhu6X68Af4xgRC6y8qG4A==", + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "function-bind": "^1.1.1", + "functions-have-names": "^1.2.3", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.2", + "has-property-descriptors": "^1.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -18891,8 +19489,18 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } }, "functional-red-black-tree": { "version": "1.0.1", @@ -18900,6 +19508,11 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -18912,6 +19525,16 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -18924,6 +19547,15 @@ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -18999,6 +19631,14 @@ } } }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "requires": { + "define-properties": "^1.1.3" + } + }, "globby": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", @@ -19072,17 +19712,42 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, "hook-std": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz", @@ -19228,6 +19893,16 @@ "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", "dev": true }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, "into-stream": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-5.1.1.tgz", @@ -19244,12 +19919,34 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + }, "is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", @@ -19259,6 +19956,14 @@ "has": "^1.0.3" } }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -19292,12 +19997,25 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -19322,12 +20040,45 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -19343,6 +20094,14 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -20832,11 +21591,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "json-schema-migrate": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-0.2.0.tgz", @@ -20921,9 +21675,9 @@ "integrity": "sha512-EvGovdvau6FyLexFH2OeXfIITlgIbgZoAZe3usiySeaIDm5QS+A10DKNpaPBBqqRSZr2HN6HVNXxtwUAr2apEw==" }, "jsonpointer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", - "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" }, "JSONStream": { "version": "1.3.5", @@ -21122,7 +21876,7 @@ "lodash.topath": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", - "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" + "integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==" }, "lodash.truncate": { "version": "4.4.2", @@ -21363,9 +22117,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -21453,9 +22207,9 @@ "dev": true }, "nimma": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/nimma/-/nimma-0.1.8.tgz", - "integrity": "sha512-9gbBqjwngJHJYIIY9OARuCU3eyy/Pl4rRmZAkj1lBMaJVWZZPUOyj90I9jMBe8uNlp4+55J3W2z2CPSJFFar/g==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/nimma/-/nimma-0.2.2.tgz", + "integrity": "sha512-V52MLl7BU+tH2Np9tDrIXK8bql3MVUadnMIl/0/oZSGC9keuro0O9UUv9QKp0aMvtN8HRew4G7byY7H4eWsxaQ==", "requires": { "@jsep-plugin/regex": "^1.0.1", "@jsep-plugin/ternary": "^1.0.2", @@ -25074,6 +25828,27 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -25548,6 +26323,16 @@ "esprima": "~4.0.0" } }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -25912,6 +26697,16 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -26143,6 +26938,26 @@ "strip-ansi": "^6.0.1" } }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -26518,6 +27333,17 @@ "dev": true, "optional": true }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -26692,6 +27518,18 @@ "webidl-conversions": "^3.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "wolfy87-eventemitter": { "version": "5.2.9", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", diff --git a/package.json b/package.json index 7cf45f2fa..47403a00a 100644 --- a/package.json +++ b/package.json @@ -51,10 +51,10 @@ "dependencies": { "@asyncapi/specs": "^3.1.0", "@openapi-contrib/openapi-schema-to-json-schema": "^3.2.0", - "@stoplight/spectral-core": "^1.10.1", - "@stoplight/spectral-functions": "^1.5.1", - "@stoplight/spectral-parsers": "^1.0.1", - "@stoplight/spectral-rulesets": "^1.4.3", + "@stoplight/spectral-core": "^1.13.1", + "@stoplight/spectral-functions": "^1.7.1", + "@stoplight/spectral-parsers": "^1.0.2", + "@stoplight/spectral-rulesets": "^1.12.0", "ajv": "^8.11.0", "avsc": "^5.7.4", "js-yaml": "^3.14.1", diff --git a/src/constants.ts b/src/constants.ts index ac5f77c51..14c751d8a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,6 +5,7 @@ export const xParserMessageName = 'x-parser-message-name'; export const xParserSchemaId = 'x-parser-schema-id'; export const xParserOriginalSchemaFormat = 'x-parser-original-schema-format'; +export const xParserOriginalPayload = 'x-parser-original-payload'; export const xParserOriginalTraits = 'x-parser-original-traits'; export const xParserCircular = 'x-parser-circular'; diff --git a/src/custom-operations/parse-schema.ts b/src/custom-operations/parse-schema.ts index 0884d5f41..6fb36bb77 100644 --- a/src/custom-operations/parse-schema.ts +++ b/src/custom-operations/parse-schema.ts @@ -1,8 +1,8 @@ import { JSONPath } from 'jsonpath-plus'; import { toPath } from 'lodash'; -import { parseSchema, getDefaultSchemaFormat } from '../schema-parser'; -import { xParserOriginalSchemaFormat } from '../constants'; +import { parseSchema, getSchemaFormat, getDefaultSchemaFormat } from '../schema-parser'; +import { xParserOriginalPayload } from '../constants'; import type { Parser } from '../parser'; import type { ParseSchemaInput } from "../schema-parser"; @@ -14,15 +14,17 @@ interface ToParseItem { } const customSchemasPathsV2 = [ + // operations '$.channels.*.[publish,subscribe].message', '$.channels.*.[publish,subscribe].message.oneOf.*', '$.components.channels.*.[publish,subscribe].message', '$.components.channels.*.[publish,subscribe].message.oneOf.*', + // messages '$.components.messages.*', ]; export async function parseSchemasV2(parser: Parser, detailed: DetailedAsyncAPI) { - const defaultSchemaFormat = getDefaultSchemaFormat(detailed.parsed.asyncapi as string); + const defaultSchemaFormat = getDefaultSchemaFormat(detailed.semver.version); const parseItems: Array = []; const visited: Set = new Set(); @@ -43,13 +45,16 @@ export async function parseSchemasV2(parser: Parser, detailed: DetailedAsyncAPI) return; } + const schemaFormat = getSchemaFormat(value.schemaFormat, detailed.semver.version); parseItems.push({ input: { asyncapi: detailed, data: payload, - meta: undefined, + meta: { + message: value, + }, path: [...toPath(result.path.slice(1)), 'payload'], - schemaFormat: value.schemaFormat || defaultSchemaFormat, + schemaFormat, defaultSchemaFormat, }, value, @@ -62,6 +67,6 @@ export async function parseSchemasV2(parser: Parser, detailed: DetailedAsyncAPI) } async function parseSchemaV2(parser: Parser, item: ToParseItem) { - item.value[xParserOriginalSchemaFormat] = item.input.schemaFormat; + item.value[xParserOriginalPayload] = item.input.data; item.value.payload = await parseSchema(parser, item.input); } diff --git a/src/parse.ts b/src/parse.ts index 80c952e84..fb7d6822a 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -2,7 +2,7 @@ import { AsyncAPIDocumentInterface, newAsyncAPIDocument } from "./models"; import { customOperations } from './custom-operations'; import { validate } from "./lint"; -import { createDetailedAsyncAPI, normalizeInput, toAsyncAPIDocument } from "./utils"; +import { createDetailedAsyncAPI, normalizeInput, toAsyncAPIDocument, unfreezeObject } from "./utils"; import { xParserSpecParsed } from './constants'; @@ -47,7 +47,7 @@ export async function parse(parser: Parser, asyncapi: ParseInput, options?: Pars } // unfreeze the object - Spectral makes resolved document "freezed" - const validatedDoc = JSON.parse(JSON.stringify(validated)); + const validatedDoc = unfreezeObject(validated); validatedDoc[String(xParserSpecParsed)] = true; const detailed = createDetailedAsyncAPI(asyncapi as string | Record, validatedDoc); @@ -67,6 +67,7 @@ export async function parse(parser: Parser, asyncapi: ParseInput, options?: Pars const defaultOptions: ParseOptions = { applyTraits: true, + parseSchemas: true, }; function normalizeOptions(options?: ParseOptions): ParseOptions { if (!options || typeof options !== 'object') { diff --git a/src/parser.ts b/src/parser.ts index 3d106fe50..5681e5047 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,9 +1,10 @@ import { Spectral } from "@stoplight/spectral-core"; -import { asyncapi as aasRuleset } from "@stoplight/spectral-rulesets"; import { parse } from "./parse"; import { lint, validate } from "./lint"; import { registerSchemaParser } from './schema-parser'; +import { AsyncAPISchemaParser } from "./schema-parser/asyncapi-schema-parser"; +import { configureSpectral } from "./spectral"; import type { IConstructorOpts } from "@stoplight/spectral-core"; import type { ParseInput, ParseOptions } from "./parse"; @@ -18,16 +19,18 @@ export class Parser { public readonly parserRegistry = new Map(); public readonly spectral: Spectral; - constructor(options?: ParserOptions) { - const { spectral } = options || {}; + constructor( + private readonly options?: ParserOptions + ) { + const { spectral } = this.options || {}; if (spectral instanceof Spectral) { this.spectral = spectral; } else { this.spectral = new Spectral(spectral); } - // TODO: fix type - this.spectral.setRuleset(aasRuleset as any); + this.registerSchemaParser(AsyncAPISchemaParser()); + configureSpectral(this); } parse(asyncapi: ParseInput, options?: ParseOptions) { diff --git a/src/schema-parser/asyncapi-schema-parser.ts b/src/schema-parser/asyncapi-schema-parser.ts index f6d1a00cf..0e520b040 100644 --- a/src/schema-parser/asyncapi-schema-parser.ts +++ b/src/schema-parser/asyncapi-schema-parser.ts @@ -1,15 +1,16 @@ -import { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; -import Ajv, { ErrorObject, ValidateFunction } from "ajv"; -import type { AsyncAPISchema, SchemaValidateResult } from '../types'; +import Ajv from "ajv"; // @ts-ignore import specs from '@asyncapi/specs'; +import type { ErrorObject, ValidateFunction } from "ajv"; +import type { AsyncAPISchema, SchemaValidateResult } from '../types'; +import type { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; + const ajv = new Ajv({ allErrors: true, strict: false, logger: false, }); - // Only versions compatible with JSON Schema Draf-07 are supported. const specVersions = Object.keys(specs).filter((version: string) => !['1.0.0', '1.1.0', '1.2.0', '2.0.0-rc1', '2.0.0-rc2'].includes(version)); diff --git a/src/schema-parser/avro-schema-parser.ts b/src/schema-parser/avro-schema-parser.ts index 3ca520866..1482f9457 100644 --- a/src/schema-parser/avro-schema-parser.ts +++ b/src/schema-parser/avro-schema-parser.ts @@ -1,7 +1,9 @@ -import avsc, { type Schema} from "avsc"; -import type { AsyncAPISchema, SchemaValidateResult } from "types"; -import { SchemaParser, type ParseSchemaInput, type ValidateSchemaInput } from "../schema-parser"; -import { type JSONSchema7TypeName } from "json-schema"; +import avsc from "avsc"; + +import type { JSONSchema7TypeName } from "json-schema"; +import type { Schema } from "avsc"; +import type { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; +import type { AsyncAPISchema, SchemaValidateResult } from '../types'; type AvroSchema = Schema & { [key: string]: any } & any; @@ -32,29 +34,15 @@ async function validate(input: ValidateSchemaInput): Promise): Promise { const asyncAPISchema = await avroToJsonSchema(input.data as AvroSchema); - const message = (input.meta as any).message // TODO: Should the following modifications to the message object be done in the caller and for all parsers rather than here? // remove that function when https://github.com/asyncapi/spec/issues/622 will be introduced in AsyncAPI spec - async function handleKafkaProtocolKey() { - if (message.bindings && message.bindings.kafka) { - const key = message.bindings.kafka.key; - if (key) { - const bindingsTransformed = await avroToJsonSchema(key); - message['x-parser-original-bindings-kafka-key'] = key; - message.bindings.kafka.key = bindingsTransformed; - } - } - } - - if (message !== undefined) { - // TODO: Should the following modifications to the message object be done in the caller and for all parsers rather than here? - message['x-parser-original-schema-format'] = input.schemaFormat || input.defaultSchemaFormat; - message['x-parser-original-payload'] = input.data; - message.payload = asyncAPISchema; - delete message.schemaFormat; - - await handleKafkaProtocolKey(); + const message = (input.meta as any).message + const key = message?.bindings?.kafka?.key; + if (key) { + const bindingsTransformed = await avroToJsonSchema(key); + message['x-parser-original-bindings-kafka-key'] = key; + message.bindings.kafka.key = bindingsTransformed; } return asyncAPISchema; @@ -94,7 +82,7 @@ const typeMappings: { [key: string]: JSONSchema7TypeName } = { uuid: 'string', }; -const commonAttributesMapping = (avroDefinition: AvroSchema, jsonSchema: AsyncAPISchema, isTopLevel: boolean) => { +function commonAttributesMapping(avroDefinition: AvroSchema, jsonSchema: AsyncAPISchema, isTopLevel: boolean): void { if (avroDefinition.doc) jsonSchema.description = avroDefinition.doc; if (avroDefinition.default !== undefined) jsonSchema.default = avroDefinition.default; @@ -124,7 +112,7 @@ function getFullyQualifiedName(avroDefinition: AvroSchema) { * @param parentJsonSchema the parent json schema which contains the required property to enrich * @param haveDefaultValue we assure that a required field does not have a default value */ -const requiredAttributesMapping = (fieldDefinition: any, parentJsonSchema: AsyncAPISchema, haveDefaultValue: boolean) => { +function requiredAttributesMapping(fieldDefinition: any, parentJsonSchema: AsyncAPISchema, haveDefaultValue: boolean): void { const isUnionWithNull = Array.isArray(fieldDefinition.type) && fieldDefinition.type.includes('null'); // we assume that a union type without null and a field without default value is required @@ -134,7 +122,7 @@ const requiredAttributesMapping = (fieldDefinition: any, parentJsonSchema: Async } }; -function extractNonNullableTypeIfNeeded(typeInput: any, jsonSchemaInput: AsyncAPISchema) { +function extractNonNullableTypeIfNeeded(typeInput: any, jsonSchemaInput: AsyncAPISchema): { type: string, jsonSchema: AsyncAPISchema } { let type = typeInput; let jsonSchema = jsonSchemaInput; // Map example to first non-null type @@ -145,10 +133,10 @@ function extractNonNullableTypeIfNeeded(typeInput: any, jsonSchemaInput: AsyncAP jsonSchema = jsonSchema.oneOf[0] as AsyncAPISchema; } } - return {type, jsonSchema}; + return { type, jsonSchema }; } -const exampleAttributeMapping = (type: any, example: any, jsonSchema: AsyncAPISchema) => { +function exampleAttributeMapping(type: any, example: any, jsonSchema: AsyncAPISchema): void { if (example === undefined || jsonSchema.examples || Array.isArray(type)) return; switch (type) { @@ -163,7 +151,7 @@ const exampleAttributeMapping = (type: any, example: any, jsonSchema: AsyncAPISc } }; -const additionalAttributesMapping = (typeInput: any, avroDefinition: AvroSchema, jsonSchemaInput: AsyncAPISchema) => { +function additionalAttributesMapping(typeInput: any, avroDefinition: AvroSchema, jsonSchemaInput: AsyncAPISchema): void { const __ret = extractNonNullableTypeIfNeeded(typeInput, jsonSchemaInput); const type = __ret.type; const jsonSchema = __ret.jsonSchema; @@ -201,7 +189,7 @@ const additionalAttributesMapping = (typeInput: any, avroDefinition: AvroSchema, } }; -function validateAvroSchema(avroDefinition: AvroSchema) { +function validateAvroSchema(avroDefinition: AvroSchema): void | never { // don't need to use the output from parsing the // avro definition - we're just using this as a // validator as this will throw an exception if @@ -217,13 +205,13 @@ function validateAvroSchema(avroDefinition: AvroSchema) { * @param key String | Undefined - the fully qualified name of an avro record * @param value JsonSchema - The json schema from the avro record */ -function cacheAvroRecordDef(cache: {[key:string]: AsyncAPISchema}, key: string, value: AsyncAPISchema) { +function cacheAvroRecordDef(cache: {[key:string]: AsyncAPISchema}, key: string, value: AsyncAPISchema): void { if (key !== undefined) { cache[key] = value; } } -async function convertAvroToJsonSchema(avroDefinition: AvroSchema , isTopLevel: boolean, recordCache: Map | any = {}) { +async function convertAvroToJsonSchema(avroDefinition: AvroSchema , isTopLevel: boolean, recordCache: Map | any = {}): Promise { const jsonSchema: AsyncAPISchema = {}; const isUnion = Array.isArray(avroDefinition); @@ -287,8 +275,8 @@ async function convertAvroToJsonSchema(avroDefinition: AvroSchema , isTopLevel: * @param jsonSchema the schema for the record. * @returns {Promise>} */ -async function processRecordSchema(avroDefinition: AvroSchema, recordCache: {[key:string]: AsyncAPISchema}, jsonSchema: AsyncAPISchema) { - const propsMap = new Map(); +async function processRecordSchema(avroDefinition: AvroSchema, recordCache: {[key:string]: AsyncAPISchema}, jsonSchema: AsyncAPISchema): Promise> { + const propsMap = new Map(); for (const field of avroDefinition.fields) { // If the type is a sub schema it will have been stored in the cache. if (recordCache[field.type]) { @@ -317,9 +305,9 @@ async function processRecordSchema(avroDefinition: AvroSchema, recordCache: {[ke * @param avroDefinition the avro schema to be processed * @param isTopLevel is this the top level of the schema or is this a sub schema * @param recordCache the cache of previously processed record types - * @returns {Promise} the mutated jsonSchema that was provided to the function + * @returns {Promise} the mutated jsonSchema that was provided to the function */ -async function processUnionSchema(jsonSchema: AsyncAPISchema, avroDefinition: AvroSchema, isTopLevel: boolean, recordCache: {[key:string]: AsyncAPISchema}) { +async function processUnionSchema(jsonSchema: AsyncAPISchema, avroDefinition: AvroSchema, isTopLevel: boolean, recordCache: {[key:string]: AsyncAPISchema}): Promise { jsonSchema.oneOf = []; let nullDef = null; for (const avroDef of avroDefinition) { diff --git a/src/schema-parser/index.ts b/src/schema-parser/index.ts index 89bf2ade6..31b2a0e66 100644 --- a/src/schema-parser/index.ts +++ b/src/schema-parser/index.ts @@ -28,8 +28,7 @@ export interface SchemaParser { export async function validateSchema(parser: Parser, input: ValidateSchemaInput) { const schemaParser = parser.parserRegistry.get(input.schemaFormat); if (schemaParser === undefined) { - // throw appropriate error - throw new Error(); + throw new Error('Unknown schema format'); } return schemaParser.validate(input); } @@ -37,7 +36,7 @@ export async function validateSchema(parser: Parser, input: ValidateSchemaInput) export async function parseSchema(parser: Parser, input: ParseSchemaInput) { const schemaParser = parser.parserRegistry.get(input.schemaFormat); if (schemaParser === undefined) { - return; + throw new Error('Unknown schema format'); } return schemaParser.parse(input); } @@ -49,7 +48,7 @@ export function registerSchemaParser(parser: Parser, schemaParser: SchemaParser) || typeof schemaParser.parse !== 'function' || typeof schemaParser.getMimeTypes !== 'function' ) { - throw new Error('custom parser must have "parse()", "validate()" and "getMimeTypes()" functions.'); + throw new Error('Custom parser must have "parse()", "validate()" and "getMimeTypes()" functions.'); } schemaParser.getMimeTypes().forEach(schemaFormat => { @@ -57,6 +56,13 @@ export function registerSchemaParser(parser: Parser, schemaParser: SchemaParser) }); } +export function getSchemaFormat(schematFormat: string | undefined, asyncapiVersion: string) { + if (typeof schematFormat === 'string') { + return schematFormat; + } + return getDefaultSchemaFormat(asyncapiVersion); +} + export function getDefaultSchemaFormat(asyncapiVersion: string) { return `application/vnd.aai.asyncapi;version=${asyncapiVersion}`; } diff --git a/src/schema-parser/openapi-schema-parser.ts b/src/schema-parser/openapi-schema-parser.ts index 2c1748b18..8a7f81a57 100644 --- a/src/schema-parser/openapi-schema-parser.ts +++ b/src/schema-parser/openapi-schema-parser.ts @@ -1,15 +1,17 @@ -import { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; -import type { AsyncAPISchema, SchemaValidateResult } from '../types'; -import Ajv, { ErrorObject, ValidateFunction } from "ajv"; -import { schemaV3 } from './openapi/schema_v3' +import Ajv from "ajv"; +import { schemaV3 } from './openapi/schema_v3'; + const toJsonSchema = require('@openapi-contrib/openapi-schema-to-json-schema'); +import type { ErrorObject, ValidateFunction } from "ajv"; +import type { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; +import type { AsyncAPISchema, SchemaValidateResult } from '../types'; + const ajv = new Ajv({ allErrors: true, strict: false, logger: false, }); - ajv.addSchema(schemaV3, "openapi"); export function OpenAPISchemaParser(): SchemaParser { @@ -33,29 +35,20 @@ async function validate(input: ValidateSchemaInput): Promise): Promise { - const transformed = toJsonSchema(input.data, { - cloneSchema: true, - keepNotSupported: [ - 'discriminator', - 'readOnly', - 'writeOnly', - 'deprecated', - 'xml', - 'example', - ], - }); + const transformed = toJsonSchema(input.data, { + cloneSchema: true, + keepNotSupported: [ + 'discriminator', + 'readOnly', + 'writeOnly', + 'deprecated', + 'xml', + 'example', + ], + }); - iterateSchema(transformed); - - const message = (input.meta as any).message - if (message !== undefined) { - message['x-parser-original-schema-format'] = input.schemaFormat || input.defaultSchemaFormat; - message['x-parser-original-payload'] = message.payload; - message.payload = transformed; - delete message.schemaFormat; - }; - - return transformed; + iterateSchema(transformed); + return transformed; } function getMimeTypes() { @@ -76,6 +69,7 @@ function ajvToSpectralResult(errors: ErrorObject[]): SchemaValidateResult[] { } as SchemaValidateResult; }); } + function iterateSchema(schema: any) { if (schema.example !== undefined) { const examples = schema.examples || []; @@ -110,4 +104,4 @@ function aliasProps(obj: any) { iterateSchema(obj[key]); } -} \ No newline at end of file +} diff --git a/src/schema-parser/raml-schema-parser.ts b/src/schema-parser/raml-schema-parser.ts index 450de2394..84610a069 100644 --- a/src/schema-parser/raml-schema-parser.ts +++ b/src/schema-parser/raml-schema-parser.ts @@ -1,32 +1,26 @@ -import { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; -import type { AsyncAPISchema, SchemaValidateResult } from '../types'; import yaml from 'js-yaml'; import * as lib from "webapi-parser"; + const wap = lib.WebApiParser; const r2j = require('ramldt2jsonschema'); +import type { SchemaParser, ParseSchemaInput, ValidateSchemaInput } from "../schema-parser"; +import type { AsyncAPISchema, SchemaValidateResult } from '../types'; + export function RamlSchemaParser(): SchemaParser { - return { - validate, - parse, - getMimeTypes, - } + return { + validate, + parse, + getMimeTypes, } +} async function parse(input: ParseSchemaInput): Promise { - const message = (input.meta as any).message; - const payload = formatPayload(input.data); - - // Draft 6 is compatible with 7. - const jsonModel = await r2j.dt2js(payload, 'tmpType', { draft: '06' }); - const convertedType = jsonModel.definitions.tmpType; + const payload = formatPayload(input.data); - message['x-parser-original-schema-format'] = input.schemaFormat || input.defaultSchemaFormat; - message['x-parser-original-payload'] = payload; - message.payload = convertedType; - delete message.schemaFormat; - - return message.payload; + // Draft 6 is compatible with 7. + const jsonModel = await r2j.dt2js(payload, 'tmpType', { draft: '06' }); + return jsonModel.definitions.tmpType; } function getMimeTypes() { @@ -55,11 +49,9 @@ async function validate(input: ValidateSchemaInput): Promise( + { + input: { + type: 'object', + properties: { + schemaFormat: { + type: 'string', + }, + payload: true, // any + } + }, + options: null + }, + async function asyncApi2CustomSchema(targetVal = {}, _, ctx) { + if (!targetVal.payload) { + return []; + } + + const path = [...ctx.path, 'payload']; + const spec = ctx.document.data as { asyncapi: string }; + const schemaFormat = getSchemaFormat(targetVal.schemaFormat, spec.asyncapi); + const defaultSchemaFormat = getDefaultSchemaFormat(spec.asyncapi); + // we don't have a parsed specification yet because we are still executing code in the context of spectral + const asyncapi = createDetailedAsyncAPI(ctx.document.source as string, spec); + + const input: ValidateSchemaInput = { + asyncapi, + data: targetVal.payload, + meta: {}, + path, + schemaFormat, + defaultSchemaFormat, + } + + let result: SchemaValidateResult[] | void; + try { + result = await validateSchema(parser, input); + } catch(err: any) { + if (err instanceof Error) { + if (err.message === 'Unknown schema format') { + path.pop(); // remove 'payload' as last element of path + path.push('schemaFormat'); + return [ + { + message: `Unknown schema format: "${schemaFormat}"`, + path, + } + ] as SchemaValidateResult[]; + } else { + return [ + { + message: `Error thrown during schema validation: name: ${err.name}, message:, ${err.message}, stack: ${err.stack}`, + path, + } + ] as SchemaValidateResult[]; + } + } + } + + return result && result.map(r => ({ + ...r, + path: r.path ? [...path, ...r.path] : path, + })); + } + ) +} diff --git a/src/spectral.ts b/src/spectral.ts new file mode 100644 index 000000000..52a81a508 --- /dev/null +++ b/src/spectral.ts @@ -0,0 +1,24 @@ +import { RulesetDefinition } from "@stoplight/spectral-core"; +import { asyncapi as aasRuleset } from "@stoplight/spectral-rulesets"; + +import { aas2schemaParserRule } from './schema-parser/spectral-rule-v2'; + +import type { Parser } from "./parser"; + +export function configureSpectral(parser: Parser) { + const ruleset = configureRuleset(parser); + parser.spectral.setRuleset(ruleset); +} + +function configureRuleset(parser: Parser): RulesetDefinition { + return { + extends: [aasRuleset], + rules: { + 'asyncapi-schemas-v2': aas2schemaParserRule(parser), + // We do not use these rules from the official ruleset due to the fact + // that the given rules validate only AsyncAPI Schemas and prevent defining schemas in other formats + 'asyncapi-payload-unsupported-schemaFormat': 'off', + 'asyncapi-payload': 'off', + }, + } as RulesetDefinition; +} diff --git a/src/utils.ts b/src/utils.ts index f2ea335d2..48c0cd5f1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -68,6 +68,10 @@ export function normalizeInput(asyncapi: string | MaybeAsyncAPI): string { return JSON.stringify(asyncapi, undefined, 2); }; +export function unfreezeObject(data: unknown) { + return JSON.parse(JSON.stringify(data)) +} + export function hasErrorDiagnostic(diagnostics: ISpectralDiagnostic[]): boolean { return diagnostics.some(diagnostic => diagnostic.severity === DiagnosticSeverity.Error); } diff --git a/test/custom-operations/parse-schema.spec.ts b/test/custom-operations/parse-schema.spec.ts new file mode 100644 index 000000000..08ba25a8a --- /dev/null +++ b/test/custom-operations/parse-schema.spec.ts @@ -0,0 +1,96 @@ +import { AsyncAPIDocumentV2 } from '../../src/models'; +import { Parser } from '../../src/parser'; +import { parse } from '../../src/parse'; +import { xParserOriginalPayload } from '../../src/constants'; + +describe('custom operations - parse schemas', function() { + const parser = new Parser(); + + it('should parse valid schema format', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Valid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + operationId: 'operationId', + message: { + schemaFormat: 'application/vnd.aai.asyncapi;version=2.0.0', + payload: { + type: 'object', + } + } + } + } + } + } + const { parsed, diagnostics } = await parse(parser, document); + + expect(parsed).toBeInstanceOf(AsyncAPIDocumentV2); + expect(diagnostics.length > 0).toEqual(true); + + expect(parsed?.json()['channels']['channel']['publish']['message']['payload']).toEqual({ type: 'object' }); + expect(parsed?.json()['channels']['channel']['publish']['message'][xParserOriginalPayload]).toEqual({ type: 'object' }); + expect(parsed?.json()['channels']['channel']['publish']['message']['payload']).toEqual(parsed?.json()['channels']['channel']['publish']['message'][xParserOriginalPayload]); + }); + + it('should parse valid default schema format', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Valid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + operationId: 'operationId', + message: { + payload: { + type: 'object', + } + } + } + } + } + } + const { parsed, diagnostics } = await parse(parser, document); + + expect(parsed).toBeInstanceOf(AsyncAPIDocumentV2); + expect(diagnostics.length > 0).toEqual(true); + + expect(parsed?.json()['channels']['channel']['publish']['message']['payload']).toEqual({ type: 'object' }); + expect(parsed?.json()['channels']['channel']['publish']['message'][xParserOriginalPayload]).toEqual({ type: 'object' }); + expect(parsed?.json()['channels']['channel']['publish']['message']['payload']).toEqual(parsed?.json()['channels']['channel']['publish']['message'][xParserOriginalPayload]); + }); + + it('should parse invalid schema format', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Valid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + operationId: 'operationId', + message: { + schemaFormat: 'not existing', + payload: { + type: 'object', + } + } + } + } + } + } + const { parsed, diagnostics } = await parse(parser, document); + + expect(parsed).toBeUndefined(); + expect(diagnostics.length > 0).toEqual(true); + }); +}); diff --git a/test/parser.spec.ts b/test/parser.spec.ts index 8f17a0554..b55b22519 100644 --- a/test/parser.spec.ts +++ b/test/parser.spec.ts @@ -22,8 +22,7 @@ describe('Parser class', function() { it('should register schema parser', async function() { const parser = new Parser(); - const schemaParser = AsyncAPISchemaParser(); - parser.registerSchemaParser(schemaParser); + parser.registerSchemaParser(AsyncAPISchemaParser()); expect(parser.parserRegistry.size).toBeGreaterThan(1); }); }); diff --git a/test/schema-parser/asyncapi-schema-parser.spec.ts b/test/schema-parser/asyncapi-schema-parser.spec.ts index a76d99544..ab0ae9197 100644 --- a/test/schema-parser/asyncapi-schema-parser.spec.ts +++ b/test/schema-parser/asyncapi-schema-parser.spec.ts @@ -1,9 +1,9 @@ -import { ParseSchemaInput, ValidateSchemaInput } from '../../src/schema-parser/index'; import { AsyncAPISchemaParser } from '../../src/schema-parser/asyncapi-schema-parser'; -import { SchemaValidateResult } from '../../src/types'; -describe('AsyncAPISchemaParser', function () { +import type { ParseSchemaInput, ValidateSchemaInput } from '../../src/schema-parser'; +import type { SchemaValidateResult } from '../../src/types'; +describe('AsyncAPISchemaParser', function () { const validSchema = { asyncapi: { semver: { diff --git a/test/schema-parser/avro/avro-schema-parser.spec.ts b/test/schema-parser/avro/avro-schema-parser.spec.ts index 921f4a648..5d1b48257 100644 --- a/test/schema-parser/avro/avro-schema-parser.spec.ts +++ b/test/schema-parser/avro/avro-schema-parser.spec.ts @@ -1,32 +1,35 @@ -import { ParseSchemaInput } from '../../../src/schema-parser/index'; import { AvroSchemaParser, avroToJsonSchema } from '../../../src/schema-parser/avro-schema-parser'; -import { type Schema as AvroSchema} from "avsc"; import * as fs from 'fs'; import * as path from 'path'; +import type { Schema as AvroSchema } from "avsc"; +import type { ParseSchemaInput } from '../../../src/schema-parser'; + const inputWithAvro182 = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-1.8.2.json'), 'utf8')); -const outputWithAvro182 = '{"payload":{"type":"object","required":["name","favoriteProgrammingLanguage","address"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"]},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}}}},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.8.2","x-parser-original-payload":{"type":"record","fields":[{"name":"name","type":"string","example":"Donkey"},{"name":"age","type":["null","int"],"default":null},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"]}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003}]}}]}}'; +const outputWithAvro182 = '{"type":"object","required":["name","favoriteProgrammingLanguage","address"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"]},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}}}}'; const inputWithAvro190 = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-1.9.0.json'), 'utf8')); -const outputWithAvro190 = '{"payload":{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"Person"},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":{"name":"Person","type":"record","fields":[{"name":"name","type":"string","example":"Donkey"},{"name":"age","type":["null","int"],"default":null,"example":123},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"],"default":"JS"}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003}]}},{"name":"someid","type":"string","logicalType":"uuid"}]}}'; +const outputWithAvro190 = '{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"Person"}'; const inputWithAvro190WithNamespace = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-1.9.0-namespace.json'), 'utf8')); -const outputWithAvro190WithNamespace = '{"payload":{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":{"name":"Person","namespace":"com.company","type":"record","fields":[{"name":"name","type":"string","example":"Donkey"},{"name":"age","type":["null","int"],"default":null,"example":123},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"],"default":"JS"}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003}]}},{"name":"someid","type":"string","logicalType":"uuid"}]}}'; +const outputWithAvro190WithNamespace = '{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"}'; const inputWithAvro190WithBindings = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-1.9.0-bindings.json'), 'utf8')); -const outputWithAvro190WithBindings = '{"payload":{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"},"bindings":{"kafka":{"key":{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"}},"mqtt":{"x-test":{"type":"string"}}},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":{"name":"Person","namespace":"com.company","type":"record","fields":[{"name":"name","type":"string","example":"Donkey"},{"name":"age","type":["null","int"],"default":null,"example":123},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"],"default":"JS"}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003}]}},{"name":"someid","type":"string","logicalType":"uuid"}]},"x-parser-original-bindings-kafka-key":{"name":"Person","namespace":"com.company","type":"record","fields":[{"name":"name","type":"string","example":"Donkey"},{"name":"age","type":["null","int"],"default":null,"example":123},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"],"default":"JS"}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003}]}},{"name":"someid","type":"string","logicalType":"uuid"}]}}'; +const outputWithAvro190WithBindings = '{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"}'; +const outputWithAvro190WithBindingsKafkaKeyTransformed = '{"type":"object","required":["name","favoriteProgrammingLanguage","address","someid"],"properties":{"name":{"type":"string","examples":["Donkey"]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123]},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]}}},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"}'; +const outputWithAvro190WithBindingsKafkaKeyOriginal = '{"name":"Person","namespace":"com.company","type":"record","fields":[{"name":"name","type":"string","example":"Donkey"},{"name":"age","type":["null","int"],"default":null,"example":123},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"],"default":"JS"}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003}]}},{"name":"someid","type":"string","logicalType":"uuid"}]}'; const inputWithAvroAdditionalAttributes = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-1.9.0-additional-attributes.json'), 'utf8')); -const outputWithAvroAdditionalAttributes = '{"payload":{"type":"object","required":["name","serialNo","favoriteProgrammingLanguage","certifications","address","weight","height","someid"],"properties":{"name":{"type":"string","examples":["Donkey"],"minLength":0},"serialNo":{"type":"string","minLength":0,"maxLength":50},"email":{"oneOf":[{"type":"string","examples":["donkey@asyncapi.com"],"pattern":"^[\\\\w-\\\\.]+@([\\\\w-]+\\\\.)+[\\\\w-]{2,4}$"},{"type":"null"}]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123],"exclusiveMinimum":0,"exclusiveMaximum":200},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"certifications":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":500,"uniqueItems":true},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]},"country":{"oneOf":[{"type":"string"},{"type":"null"}]}}},"weight":{"type":"number","format":"float","examples":[65.1],"minimum":0,"maximum":500},"height":{"type":"number","format":"double","examples":[1.85],"minimum":0,"maximum":3},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":{"name":"Person","namespace":"com.company","type":"record","fields":[{"name":"name","type":"string","example":"Donkey","minLength":0},{"name":"serialNo","type":"string","minLength":0,"maxLength":50},{"name":"email","type":["null","string"],"example":"donkey@asyncapi.com","pattern":"^[\\\\w-\\\\.]+@([\\\\w-]+\\\\.)+[\\\\w-]{2,4}$"},{"name":"age","type":["null","int"],"default":null,"example":123,"exclusiveMinimum":0,"exclusiveMaximum":200},{"name":"favoriteProgrammingLanguage","type":{"name":"ProgrammingLanguage","type":"enum","symbols":["JS","Java","Go","Rust","C"],"default":"JS"}},{"name":"certifications","type":{"type":"array","items":"string","minItems":1,"maxItems":500,"uniqueItems":true}},{"name":"address","type":{"name":"Address","type":"record","fields":[{"name":"zipcode","type":"int","example":53003},{"name":"country","type":["null","string"]}]}},{"name":"weight","type":"float","example":65.1,"minimum":0,"maximum":500},{"name":"height","type":"double","example":1.85,"minimum":0,"maximum":3},{"name":"someid","type":"string","logicalType":"uuid"}]}}'; +const outputWithAvroAdditionalAttributes = '{"type":"object","required":["name","serialNo","favoriteProgrammingLanguage","certifications","address","weight","height","someid"],"properties":{"name":{"type":"string","examples":["Donkey"],"minLength":0},"serialNo":{"type":"string","minLength":0,"maxLength":50},"email":{"oneOf":[{"type":"string","examples":["donkey@asyncapi.com"],"pattern":"^[\\\\w-\\\\.]+@([\\\\w-]+\\\\.)+[\\\\w-]{2,4}$"},{"type":"null"}]},"age":{"oneOf":[{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[123],"exclusiveMinimum":0,"exclusiveMaximum":200},{"type":"null"}],"default":null},"favoriteProgrammingLanguage":{"type":"string","enum":["JS","Java","Go","Rust","C"],"default":"JS"},"certifications":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":500,"uniqueItems":true},"address":{"type":"object","required":["zipcode"],"properties":{"zipcode":{"type":"integer","minimum":-2147483648,"maximum":2147483647,"examples":[53003]},"country":{"oneOf":[{"type":"string"},{"type":"null"}]}}},"weight":{"type":"number","format":"float","examples":[65.1],"minimum":0,"maximum":500},"height":{"type":"number","format":"double","examples":[1.85],"minimum":0,"maximum":3},"someid":{"type":"string","format":"uuid"}},"x-parser-schema-id":"com.company.Person"}'; const inputWithInvalidAvro = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-invalid.json'), 'utf8')); const inputWithBrokenAvro = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-broken.json'), 'utf8')); const inputWithSubAvro190 = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-111-1.9.0.json'), 'utf8')); -const outputWithSubAvro190 = '{"payload":{"type":"object","required":["metadata","auth_code","triggered_by"],"properties":{"metadata":{"type":"object","required":["id","timestamp"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for this specific event"},"timestamp":{"type":"integer","minimum":-9223372036854776000,"maximum":9223372036854776000,"description":"Instant the event took place (not necessary when it was published)"},"correlation_id":{"oneOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"id of the event that resulted in this\\nevent being published (optional)","default":null},"publisher_context":{"oneOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"null"}],"description":"optional set of key-value pairs of context to be echoed back\\nin any resulting message (like a richer\\ncorrelationId.\\n\\nThese values are likely only meaningful to the publisher\\nof the correlated event","default":null}},"description":"Metadata to be associated with every published event"},"auth_code":{"type":"object","required":["value","nonce","key"],"properties":{"value":{"type":"string","description":"A sequence of bytes that has been AES encrypted in CTR mode."},"nonce":{"type":"string","description":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret."},"key":{"type":"string","description":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA."}},"description":"Encrypted auth_code received when user authorizes the app."},"refresh_token":{"type":"object","required":["value","nonce","key"],"properties":{"value":{"type":"string","description":"A sequence of bytes that has been AES encrypted in CTR mode."},"nonce":{"type":"string","description":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret."},"key":{"type":"string","description":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA."}},"description":"Encrypted auth_code received when user authorizes the app."},"triggered_by":{"type":"string","format":"uuid","description":"ID of the user who triggered this event."}},"description":"An example schema to illustrate the issue","x-parser-schema-id":"com.foo.connections.ConnectionRequested"},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":{"type":"record","name":"ConnectionRequested","namespace":"com.foo.connections","doc":"An example schema to illustrate the issue","fields":[{"name":"metadata","type":{"type":"record","name":"EventMetadata","namespace":"com.foo","doc":"Metadata to be associated with every published event","fields":[{"name":"id","type":{"type":"string","logicalType":"uuid"},"doc":"Unique identifier for this specific event"},{"name":"timestamp","type":{"type":"long","logicalType":"timestamp-millis"},"doc":"Instant the event took place (not necessary when it was published)"},{"name":"correlation_id","type":["null",{"type":"string","logicalType":"uuid"}],"doc":"id of the event that resulted in this\\nevent being published (optional)","default":null},{"name":"publisher_context","type":["null",{"type":"map","values":{"type":"string","avro.java.string":"String"},"avro.java.string":"String"}],"doc":"optional set of key-value pairs of context to be echoed back\\nin any resulting message (like a richer\\ncorrelationId.\\n\\nThese values are likely only meaningful to the publisher\\nof the correlated event","default":null}]}},{"name":"auth_code","type":{"type":"record","name":"EncryptedString","namespace":"com.foo","doc":"A string that was encrypted with AES (using CTR mode), its key encrypted with RSA, and the nonce used for the encryption.","fields":[{"name":"value","type":"string","doc":"A sequence of bytes that has been AES encrypted in CTR mode."},{"name":"nonce","type":"string","doc":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret."},{"name":"key","type":"string","doc":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA."}]},"doc":"Encrypted auth_code received when user authorizes the app."},{"name":"refresh_token","type":"com.foo.EncryptedString","doc":"Encrypted refresh_token generated by using clientId and clientSecret."},{"name":"triggered_by","type":{"type":"string","logicalType":"uuid"},"doc":"ID of the user who triggered this event."}]}}'; +const outputWithSubAvro190 = '{"type":"object","required":["metadata","auth_code","triggered_by"],"properties":{"metadata":{"type":"object","required":["id","timestamp"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for this specific event"},"timestamp":{"type":"integer","minimum":-9223372036854776000,"maximum":9223372036854776000,"description":"Instant the event took place (not necessary when it was published)"},"correlation_id":{"oneOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"id of the event that resulted in this\\nevent being published (optional)","default":null},"publisher_context":{"oneOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"null"}],"description":"optional set of key-value pairs of context to be echoed back\\nin any resulting message (like a richer\\ncorrelationId.\\n\\nThese values are likely only meaningful to the publisher\\nof the correlated event","default":null}},"description":"Metadata to be associated with every published event"},"auth_code":{"type":"object","required":["value","nonce","key"],"properties":{"value":{"type":"string","description":"A sequence of bytes that has been AES encrypted in CTR mode."},"nonce":{"type":"string","description":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret."},"key":{"type":"string","description":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA."}},"description":"Encrypted auth_code received when user authorizes the app."},"refresh_token":{"type":"object","required":["value","nonce","key"],"properties":{"value":{"type":"string","description":"A sequence of bytes that has been AES encrypted in CTR mode."},"nonce":{"type":"string","description":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret."},"key":{"type":"string","description":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA."}},"description":"Encrypted auth_code received when user authorizes the app."},"triggered_by":{"type":"string","format":"uuid","description":"ID of the user who triggered this event."}},"description":"An example schema to illustrate the issue","x-parser-schema-id":"com.foo.connections.ConnectionRequested"}'; const inputWithOneOfReferenceAvro190 = toParseInput(fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-113-1.9.0.json'), 'utf8')); -const outputWithOneOfReferenceAvro190 = '{"payload":{"oneOf":[{"type":"object","required":["streetaddress","city"],"properties":{"streetaddress":{"type":"string"},"city":{"type":"string"}},"x-parser-schema-id":"com.example.Address"},{"type":"object","required":["firstname","lastname"],"properties":{"firstname":{"type":"string"},"lastname":{"type":"string"},"address":{"type":"object","required":["streetaddress","city"],"properties":{"streetaddress":{"type":"string"},"city":{"type":"string"}},"x-parser-schema-id":"com.example.Address"}},"x-parser-schema-id":"com.example.Person"}]},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":[{"type":"record","name":"Address","namespace":"com.example","fields":[{"name":"streetaddress","type":"string"},{"name":"city","type":"string"}]},{"type":"record","name":"Person","namespace":"com.example","fields":[{"name":"firstname","type":"string"},{"name":"lastname","type":"string"},{"name":"address","type":"com.example.Address"}]}]}'; +const outputWithOneOfReferenceAvro190 = '{"oneOf":[{"type":"object","required":["streetaddress","city"],"properties":{"streetaddress":{"type":"string"},"city":{"type":"string"}},"x-parser-schema-id":"com.example.Address"},{"type":"object","required":["firstname","lastname"],"properties":{"firstname":{"type":"string"},"lastname":{"type":"string"},"address":{"type":"object","required":["streetaddress","city"],"properties":{"streetaddress":{"type":"string"},"city":{"type":"string"}},"x-parser-schema-id":"com.example.Address"}},"x-parser-schema-id":"com.example.Person"}]}'; describe('AvroSchemaParser', function () { const parser = AvroSchemaParser(); @@ -34,9 +37,11 @@ describe('AvroSchemaParser', function () { it('should return Mime Types', async function () { expect(parser.getMimeTypes()).not.toEqual([]); }); + it('should parse Avro schema 1.8.2', async function() { await doTest(inputWithAvro182, outputWithAvro182); }); + it('should parse Avro schema 1.9.0', async function() { await doTest(inputWithAvro190, outputWithAvro190); }); @@ -44,27 +49,43 @@ describe('AvroSchemaParser', function () { it('should parse Avro schema 1.9.0 with a namespace', async function() { await doTest(inputWithAvro190WithNamespace, outputWithAvro190WithNamespace); }); + it('should parse Avro schema in kafka bindings', async function() { - await doTest(inputWithAvro190WithBindings, outputWithAvro190WithBindings); + const input = {...inputWithAvro190WithBindings}; + const result = await parser.parse(input); + + // Check that the return value of parse() is the expected JSON Schema. + expect(result).toEqual(JSON.parse(outputWithAvro190WithBindings)); + + // Check that the message got modified, i.e. adding extensions, setting the payload, etc. + const message = (input.meta as any).message; + expect(JSON.stringify(message.bindings.kafka.key)).toEqual(outputWithAvro190WithBindingsKafkaKeyTransformed); + expect(JSON.stringify(message['x-parser-original-bindings-kafka-key'])).toEqual(outputWithAvro190WithBindingsKafkaKeyOriginal); }); + it('should handle additional Avro attributes like', async function() { await doTest(inputWithAvroAdditionalAttributes, outputWithAvroAdditionalAttributes); }); + it('should validate invalid Avro schemas as invalid', async function() { const result = await parser.validate(inputWithInvalidAvro); expect(result).toEqual([{"message": "unknown type: undefined", "path": []}]); }); + it('should validate valid Avro schemas', async function() { const result = await parser.validate(inputWithAvro182); expect(result).toHaveLength(0); }); + it('should identify bugs in Avro schemas', async function() { const result = await parser.validate(inputWithBrokenAvro); expect(result).toEqual([{"message": "undefined type name: notAValidAvroType", "path": []}]); }); + it('Issue #111 should handle pre defined records in schemas', async function() { await doTest(inputWithSubAvro190, outputWithSubAvro190); }); + it('Issue #113 should handle pre defined records in top level oneOf schema', async function() { await doTest(inputWithOneOfReferenceAvro190, outputWithOneOfReferenceAvro190); }); @@ -74,11 +95,11 @@ describe('AvroSchemaParser', function () { const result = await parser.parse(input); // Check that the return value of parse() is the expected JSON Schema. - expect(result).toEqual(JSON.parse(expectedOutput).payload); + expect(result).toEqual(JSON.parse(expectedOutput)); - // Check that the message got modified, i.e. adding extensions, setting the payload, etc. - const message = (input.meta as any).message; - expect(JSON.stringify(message)).toEqual(expectedOutput); + // // Check that the message got modified, i.e. adding extensions, setting the payload, etc. + // const message = (input.meta as any).message; + // expect(JSON.stringify(message)).toEqual(expectedOutput); } }); diff --git a/test/schema-parser/openapi/openapi-schema-parser.spec.ts b/test/schema-parser/openapi/openapi-schema-parser.spec.ts index 9076f2163..62101227f 100644 --- a/test/schema-parser/openapi/openapi-schema-parser.spec.ts +++ b/test/schema-parser/openapi/openapi-schema-parser.spec.ts @@ -1,10 +1,11 @@ -import { ParseSchemaInput, ValidateSchemaInput } from '../../../src/schema-parser/index'; import { OpenAPISchemaParser } from '../../../src/schema-parser/openapi-schema-parser'; import * as fs from 'fs'; import * as path from 'path'; +import type { ParseSchemaInput, ValidateSchemaInput } from '../../../src/schema-parser'; + const inputWithValidOpenApi3 = toParseInput(fs.readFileSync(path.resolve(__dirname, './valid.json'), 'utf8')); -const outputWithValidOpenApi3 = '{"payload":{"type":["object","null"],"properties":{"name":{"type":"string"},"discriminatorTest":{"discriminator":{"propertyName":"objectType"},"oneOf":[{"type":"object","properties":{"objectType":{"type":"string"},"prop1":{"type":"string"}}},{"type":"object","properties":{"objectType":{"type":"string"},"prop2":{"type":"string"}}}]},"test":{"type":"object","properties":{"testing":{"type":"string"}}}},"examples":[{"name":"Fran"}]},"x-parser-original-schema-format":"application/vnd.oai.openapi;version=3.0.0","x-parser-original-payload":{"type":"object","nullable":true,"example":{"name":"Fran"},"properties":{"name":{"type":"string"},"discriminatorTest":{"discriminator":{"propertyName":"objectType"},"oneOf":[{"type":"object","properties":{"objectType":{"type":"string"},"prop1":{"type":"string"}}},{"type":"object","properties":{"objectType":{"type":"string"},"prop2":{"type":"string"}}}]},"test":{"type":"object","properties":{"testing":{"type":"string"}}}}}}'; +const outputWithValidOpenApi3 = '{"type":["object","null"],"properties":{"name":{"type":"string"},"discriminatorTest":{"discriminator":{"propertyName":"objectType"},"oneOf":[{"type":"object","properties":{"objectType":{"type":"string"},"prop1":{"type":"string"}}},{"type":"object","properties":{"objectType":{"type":"string"},"prop2":{"type":"string"}}}]},"test":{"type":"object","properties":{"testing":{"type":"string"}}}},"examples":[{"name":"Fran"}]}'; const inputWithInvalidOpenApi3 = toParseInput(fs.readFileSync(path.resolve(__dirname, './invalid.json'), 'utf8')); @@ -14,9 +15,11 @@ describe('OpenAPISchemaParser', function () { it('should return Mime Types', async function () { expect(parser.getMimeTypes()).not.toEqual([]); }); + it('should parse OpenAPI 3', async function() { await doParseTest(inputWithValidOpenApi3, outputWithValidOpenApi3); }); + it('should validate valid OpenAPI 3', async function() { const result = await parser.validate(inputWithValidOpenApi3); expect(result).toHaveLength(0); @@ -58,11 +61,7 @@ describe('OpenAPISchemaParser', function () { const result = await parser.parse(input); // Check that the return value of parse() is the expected JSON Schema. - expect(result).toEqual(JSON.parse(expectedOutput).payload); - - // Check that the message got modified, i.e. adding extensions, setting the payload, etc. - const message = (input.meta as any).message; - expect(JSON.stringify(message)).toEqual(expectedOutput); + expect(result).toEqual(JSON.parse(expectedOutput)); } }); diff --git a/test/schema-parser/raml/raml-schema-parser.spec.ts b/test/schema-parser/raml/raml-schema-parser.spec.ts index 5afabbb11..9479129a2 100644 --- a/test/schema-parser/raml/raml-schema-parser.spec.ts +++ b/test/schema-parser/raml/raml-schema-parser.spec.ts @@ -1,14 +1,15 @@ -import { ParseSchemaInput, ValidateSchemaInput } from '../../../src/schema-parser/index'; import { RamlSchemaParser } from '../../../src/schema-parser/raml-schema-parser'; -import { SchemaValidateResult } from '../../../src/types'; import * as fs from 'fs'; import * as path from 'path'; +import type { ParseSchemaInput, ValidateSchemaInput } from '../../../src/schema-parser'; +import type { SchemaValidateResult } from '../../../src/types'; + const inputWithSimpleRAML = toInput(fs.readFileSync(path.resolve(__dirname, './simple.json'), 'utf8')); -const outputWithSimpleRAML = '{"payload":{"type":"object","examples":[{"title":"A book","author":"An author"}],"additionalProperties":true,"required":["title","author"],"properties":{"title":{"type":"string"},"author":{"type":"string","examples":["Eva"]}}},"x-parser-original-schema-format":"application/raml+yaml;version=1.0","x-parser-original-payload":"#%RAML 1.0 Library\\ntypes:\\n tmpType:\\n type: object\\n properties:\\n title: string\\n author:\\n type: string\\n examples:\\n anExample: Eva\\n examples:\\n exampleOne:\\n title: A book\\n author: An author\\n"}'; +const outputWithSimpleRAML = '{"type":"object","examples":[{"title":"A book","author":"An author"}],"additionalProperties":true,"required":["title","author"],"properties":{"title":{"type":"string"},"author":{"type":"string","examples":["Eva"]}}}'; const inputWithComplexRAML = toInput(fs.readFileSync(path.resolve(__dirname, './complex.json'), 'utf8')); -const outputWithComplexRAML = `{"payload":{"minProperties":1,"maxProperties":50,"additionalProperties":false,"discriminator":"breed","discriminatorValue":"CatOne","type":"object","required":["proscons","name","breed","age","rating","year_of_birth","time_of_birth","addition_date","removal_date","photo","description","character","siblings","parents","ratingHistory","additionalData"],"properties":{"proscons":{"anyOf":[true,true]},"name":true,"breed":true,"age":true,"rating":{"type":"integer","multipleOf":5,"example":{"displayName":"Cat's rating","description":"Rating of cat's awesomeness","strict":false,"value":50}},"year_of_birth":{"type":"string","format":"date"},"time_of_birth":{"type":"string","format":"time"},"dt_of_birth":{"type":"string","format":"date-time-only"},"addition_date":{"type":"string","format":"rfc2616"},"removal_date":{"type":"string","format":"date-time"},"photo":{"type":"string","minLength":1,"maxLength":307200},"description":{"type":"null"},"habits":{"type":"string"},"character":{"anyOf":[{"type":"null"},{"type":"string"}]},"siblings":{"type":"array","items":{"type":"string"}},"parents":{"type":"array","items":true},"ratingHistory":{"type":"array","items":{"anyOf":[{"type":"integer"},{"type":"number"}]}},"additionalData":{"type":"object","additionalProperties":true,"required":["weight"],"properties":{"weight":{"type":"number"}}}}},"x-parser-original-schema-format":"application/raml+yaml;version=1.0","x-parser-original-payload":"#%RAML 1.0 Library\\ntypes:\\n tmpType:\\n type:\\n - CatWithAddress\\n - CatWithCity\\n minProperties: 1\\n maxProperties: 50\\n additionalProperties: false\\n discriminator: breed\\n discriminatorValue: CatOne\\n properties:\\n proscons:\\n type: CatPros | CatCons\\n required: true\\n name:\\n type: CatName\\n amazing: true\\n breed:\\n type: CatBreed\\n age: CatAge\\n rating:\\n type: integer\\n multipleOf: 5\\n example:\\n displayName: Cat's rating\\n description: Rating of cat's awesomeness\\n strict: false\\n value: 50\\n year_of_birth: date-only\\n time_of_birth: time-only\\n dt_of_birth:\\n type: datetime-only\\n required: false\\n addition_date:\\n type: datetime\\n format: rfc2616\\n removal_date:\\n type: datetime\\n photo:\\n type: file\\n fileTypes:\\n - image/jpeg\\n - image/png\\n minLength: 1\\n maxLength: 307200\\n description: nil\\n habits?: string\\n character: nil | string\\n siblings: 'string[]'\\n parents: 'CatName[]'\\n ratingHistory: '(integer | number)[]'\\n additionalData:\\n type:\\n type: object\\n properties:\\n weight: number\\n"}`; +const outputWithComplexRAML = `{"minProperties":1,"maxProperties":50,"additionalProperties":false,"discriminator":"breed","discriminatorValue":"CatOne","type":"object","required":["proscons","name","breed","age","rating","year_of_birth","time_of_birth","addition_date","removal_date","photo","description","character","siblings","parents","ratingHistory","additionalData"],"properties":{"proscons":{"anyOf":[true,true]},"name":true,"breed":true,"age":true,"rating":{"type":"integer","multipleOf":5,"example":{"displayName":"Cat's rating","description":"Rating of cat's awesomeness","strict":false,"value":50}},"year_of_birth":{"type":"string","format":"date"},"time_of_birth":{"type":"string","format":"time"},"dt_of_birth":{"type":"string","format":"date-time-only"},"addition_date":{"type":"string","format":"rfc2616"},"removal_date":{"type":"string","format":"date-time"},"photo":{"type":"string","minLength":1,"maxLength":307200},"description":{"type":"null"},"habits":{"type":"string"},"character":{"anyOf":[{"type":"null"},{"type":"string"}]},"siblings":{"type":"array","items":{"type":"string"}},"parents":{"type":"array","items":true},"ratingHistory":{"type":"array","items":{"anyOf":[{"type":"integer"},{"type":"number"}]}},"additionalData":{"type":"object","additionalProperties":true,"required":["weight"],"properties":{"weight":{"type":"number"}}}}}`; const inputWithInvalidRAML = toInput(fs.readFileSync(path.resolve(__dirname, './invalid.json'), 'utf8')); @@ -28,11 +29,7 @@ describe('parse()', function() { const result = await parser.parse(input); // Check that the return value of parse() is the expected JSON Schema. - expect(result).toEqual(JSON.parse(expectedOutput).payload); - - // Check that the message got modified, i.e. adding extensions, setting the payload, etc. - const message = (input.meta as any).message; - expect(JSON.stringify(message)).toEqual(expectedOutput); + expect(result).toEqual(JSON.parse(expectedOutput)); } }); diff --git a/test/schema-parser/spectral-rule-v2.spec.ts b/test/schema-parser/spectral-rule-v2.spec.ts new file mode 100644 index 000000000..26208a348 --- /dev/null +++ b/test/schema-parser/spectral-rule-v2.spec.ts @@ -0,0 +1,305 @@ +import { Parser } from '../../src/parser'; +import { validate } from '../../src/lint'; + +import type { ISpectralDiagnostic } from '@stoplight/spectral-core'; +import type { SchemaValidateResult } from '../../src/types'; + +describe('aas2schemaParserRule', function() { + const parser = new Parser(); + + it('should validate AsyncAPI Schema with valid schema', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Valid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + message: { + payload: { + type: 'object', + } + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + expect(filteredDiagnostics).toHaveLength(0); + }); + + it('should validate AsyncAPI Schema with invalid schema', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Invalid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + message: { + payload: { + oneOf: "this should be an array", + properties: { + name: { + if: "this should be an if" + } + } + } + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + + const expectedResult: SchemaValidateResult[] = [ + { + message: 'must be array', + path: ['channels', 'channel', 'publish', 'message', 'payload', 'oneOf'] + }, + { + message: 'must be object,boolean', + path: ['channels', 'channel', 'publish', 'message', 'payload', 'properties', 'name', 'if'] + } + ]; + + expect(filteredDiagnostics).toEqual(expectedResult.map(e => expect.objectContaining(e))); + }); + + it('should validate AsyncAPI Schema with invalid schema (components.messages case)', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Invalid AsyncApi document', + version: '1.0', + }, + channels: {}, + components: { + messages: { + message: { + payload: { + oneOf: "this should be an array", + properties: { + name: { + if: "this should be an if" + } + } + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + + const expectedResult: SchemaValidateResult[] = [ + { + message: 'must be array', + path: ['components', 'messages', 'message', 'payload', 'oneOf'] + }, + { + message: 'must be object,boolean', + path: ['components', 'messages', 'message', 'payload', 'properties', 'name', 'if'] + } + ]; + + expect(filteredDiagnostics).toEqual(expectedResult.map(e => expect.objectContaining(e))); + }); + + it('should validate AsyncAPI Schema with invalid schema (components.channels case)', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Invalid AsyncApi document', + version: '1.0', + }, + channels: {}, + components: { + channels: { + channel: { + publish: { + message: { + payload: { + oneOf: "this should be an array", + properties: { + name: { + if: "this should be an if" + } + } + } + }, + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + + const expectedResult: SchemaValidateResult[] = [ + { + message: 'must be array', + path: ['components', 'channels', 'channel', 'publish', 'message', 'payload', 'oneOf'] + }, + { + message: 'must be object,boolean', + path: ['components', 'channels', 'channel', 'publish', 'message', 'payload', 'properties', 'name', 'if'] + } + ]; + + expect(filteredDiagnostics).toEqual(expectedResult.map(e => expect.objectContaining(e))); + }); + + it('should validate AsyncAPI Schema with invalid schema (oneOf case)', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Invalid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + message: { + oneOf: [ + { + payload: { + oneOf: "this should be an array", + properties: { + name: { + if: "this should be an if" + } + } + } + }, + { + payload: { + oneOf: "this should be an array", + } + } + ] + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + + const expectedResult: SchemaValidateResult[] = [ + { + message: 'must be array', + path: ['channels', 'channel', 'publish', 'message', 'oneOf', '0', 'payload', 'oneOf'] + }, + { + message: 'must be object,boolean', + path: ['channels', 'channel', 'publish', 'message', 'oneOf', '0', 'payload', 'properties', 'name', 'if'] + }, + { + message: 'must be array', + path: ['channels', 'channel', 'publish', 'message', 'oneOf', '1', 'payload', 'oneOf'] + } + ]; + + expect(filteredDiagnostics).toEqual(expectedResult.map(e => expect.objectContaining(e))); + }); + + it('should validate AsyncAPI Schema with supported schema format', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Valid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + message: { + schemaFormat: 'application/vnd.aai.asyncapi;version=2.0.0', + payload: { + type: 'object', + } + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + expect(filteredDiagnostics).toHaveLength(0); + }); + + it('should validate AsyncAPI Schema with non supported schema format', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Invalid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + message: { + schemaFormat: 'not existing', + payload: { + type: 'object', + } + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + const filteredDiagnostics = filterDiagnostics(diagnostics, 'asyncapi-schemas-v2'); + + const expectedResult: SchemaValidateResult[] = [ + { + message: 'Unknown schema format: "not existing"', + path: ['channels', 'channel', 'publish', 'message', 'schemaFormat'] + }, + ]; + + expect(filteredDiagnostics).toEqual(expectedResult.map(e => expect.objectContaining(e))); + }); + + it('should not contain errors from asyncapi-payload-unsupported-schemaFormat and asyncapi-payload rules', async function() { + const document = { + asyncapi: '2.0.0', + info: { + title: 'Invalid AsyncApi document', + version: '1.0', + }, + channels: { + channel: { + publish: { + message: { + payload: { + oneOf: "this should be an array", + properties: { + name: { + if: "this should be an if" + } + } + } + } + } + } + } + } + const { diagnostics } = await validate(parser, document); + + expect(filterDiagnostics(diagnostics, 'asyncapi-schemas-v2')).toHaveLength(2); + expect(filterDiagnostics(diagnostics, 'asyncapi-payload-unsupported-schemaFormat')).toHaveLength(0); + expect(filterDiagnostics(diagnostics, 'asyncapi-payload')).toHaveLength(0); + }); +}); + +function filterDiagnostics(diagnostics: ISpectralDiagnostic[], code: string) { + return diagnostics.filter(d => d.code === code); +}