diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index f88777a0..00000000 --- a/.eslintrc +++ /dev/null @@ -1,114 +0,0 @@ -parserOptions: - ecmaVersion: 2018 - -env: - node: true - es6: true - jest: true - mocha: true - browser: true - -plugins: - - sonarjs - - security - - github - -extends: - - eslint:recommended - - plugin:sonarjs/recommended - - plugin:security/recommended - -rules: - # Ignore Rules - strict: 0 - no-underscore-dangle: 0 - no-mixed-requires: 0 - no-process-exit: 0 - no-warning-comments: 0 - no-use-before-define: 0 - curly: 0 - no-multi-spaces: 0 - no-alert: 0 - consistent-return: 0 - func-style: 0 - max-nested-callbacks: 0 - camelcase: 0 - no-dupe-class-members: 0 - security/detect-object-injection: 0 - sonarjs/no-small-switch: 0 - sonarjs/no-nested-template-literals: 0 - - # Warnings - no-debugger: 1 - no-empty: 1 - no-invalid-regexp: 1 - no-unused-expressions: 1 - no-native-reassign: 1 - no-fallthrough: 1 - sonarjs/cognitive-complexity: 1 - - # Errors - eqeqeq: 2 - no-undef: 2 - no-dupe-keys: 2 - no-empty-character-class: 2 - no-self-compare: 2 - valid-typeof: 2 - handle-callback-err: 2 - no-shadow-restricted-names: 2 - no-new-require: 2 - no-mixed-spaces-and-tabs: 2 - block-scoped-var: 2 - no-else-return: 2 - no-throw-literal: 2 - no-void: 2 - radix: 2 - wrap-iife: 2 - no-shadow: 0 - no-path-concat: 2 - valid-jsdoc: 0 - - # Stylistic errors - no-spaced-func: 2 - semi-spacing: 2 - quotes: 2 - key-spacing: 2 - indent: 2 - no-lonely-if: 2 - no-floating-decimal: 2 - brace-style: 2 - comma-style: 2 - no-multiple-empty-lines: 2 - no-nested-ternary: 2 - operator-assignment: 2 - padded-blocks: 2 - quote-props: 2 - keyword-spacing: 2 - space-before-blocks: 2 - array-bracket-spacing: 2 - computed-property-spacing: 2 - space-in-parens: 2 - space-unary-ops: 2 - wrap-regex: 2 - linebreak-style: 0 - semi: 2 - arrow-spacing: 2 - no-class-assign: 2 - no-const-assign: 2 - no-this-before-super: 2 - no-var: 2 - object-shorthand: 2 - prefer-arrow-callback: 2 - prefer-const: 2 - prefer-spread: 2 - prefer-template: 2 - -overrides: - - files: - - "test/**" - - "*.spec.js" - - "*.test.js" - rules: - prefer-arrow-callback: 0 - sonarjs/no-duplicate-string: 0 - security/detect-object-injection: 0 diff --git a/.eslintrc.yml b/.eslintrc.yml index 13cffb38..fb0f05f0 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,4 +1,4 @@ -parser: "esprima" +parser: "@typescript-eslint/parser" env: node: true @@ -14,7 +14,7 @@ extends: - plugin:sonarjs/recommended parserOptions: - ecmaVersion: 2018 + ecmaVersion: 2017 rules: # Ignore Rules diff --git a/index.js b/index.js index 61058ea6..a6e2fb7b 100644 --- a/index.js +++ b/index.js @@ -1,22 +1,22 @@ module.exports = { - 'schemas': { - '2.0.0': require('./schemas/2.0.0.json'), - '2.1.0': require('./schemas/2.1.0.json'), - '2.2.0': require('./schemas/2.2.0.json'), - '2.3.0': require('./schemas/2.3.0.json'), - '2.4.0': require('./schemas/2.4.0.json'), - '2.5.0': require('./schemas/2.5.0.json'), - '2.6.0': require('./schemas/2.6.0.json'), - '3.0.0': require('./schemas/3.0.0.json'), - }, - 'schemasWithoutId': { - '2.0.0': require('./schemas/2.0.0-without-$id.json'), - '2.1.0': require('./schemas/2.1.0-without-$id.json'), - '2.2.0': require('./schemas/2.2.0-without-$id.json'), - '2.3.0': require('./schemas/2.3.0-without-$id.json'), - '2.4.0': require('./schemas/2.4.0-without-$id.json'), - '2.5.0': require('./schemas/2.5.0-without-$id.json'), - '2.6.0': require('./schemas/2.6.0-without-$id.json'), - '3.0.0': require('./schemas/3.0.0-without-$id.json'), - } + schemas: { + '2.0.0': require('./schemas/2.0.0.json'), + '2.1.0': require('./schemas/2.1.0.json'), + '2.2.0': require('./schemas/2.2.0.json'), + '2.3.0': require('./schemas/2.3.0.json'), + '2.4.0': require('./schemas/2.4.0.json'), + '2.5.0': require('./schemas/2.5.0.json'), + '2.6.0': require('./schemas/2.6.0.json'), + '3.0.0': require('./schemas/3.0.0.json'), + }, + schemasWithoutId: { + '2.0.0': require('./schemas/2.0.0-without-$id.json'), + '2.1.0': require('./schemas/2.1.0-without-$id.json'), + '2.2.0': require('./schemas/2.2.0-without-$id.json'), + '2.3.0': require('./schemas/2.3.0-without-$id.json'), + '2.4.0': require('./schemas/2.4.0-without-$id.json'), + '2.5.0': require('./schemas/2.5.0-without-$id.json'), + '2.6.0': require('./schemas/2.6.0-without-$id.json'), + '3.0.0': require('./schemas/3.0.0-without-$id.json'), + } }; diff --git a/package-lock.json b/package-lock.json index 6d176343..1ffe1677 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@types/json-schema": "^7.0.11" }, "devDependencies": { + "@typescript-eslint/parser": "^6.15.0", "ajv": "^8.12.0", "ajv-draft-04": "^1.0.0", "eslint": "^8.56.0", @@ -848,6 +849,141 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, + "node_modules/@typescript-eslint/parser": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", + "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -988,6 +1124,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1302,6 +1447,18 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1609,6 +1766,22 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1859,6 +2032,26 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2396,6 +2589,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/minimatch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", @@ -2789,6 +3004,15 @@ "node": ">=8" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3106,6 +3330,15 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3263,6 +3496,18 @@ "node": ">=8.0" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3293,6 +3538,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/package.json b/package.json index 9a98a0f0..691c0bd9 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,11 @@ }, "homepage": "https://github.com/asyncapi/spec-json-schemas#readme", "devDependencies": { + "@typescript-eslint/parser": "^6.15.0", "ajv": "^8.12.0", "ajv-draft-04": "^1.0.0", "eslint": "^8.56.0", "eslint-plugin-sonarjs": "^0.23.0", - "esprima": "^4.0.1", "mocha": "^10.0.0", "nyc": "^15.1.0" }, diff --git a/scripts/add-new-version.js b/scripts/add-new-version.js index 6cdeaf8f..97c2189a 100644 --- a/scripts/add-new-version.js +++ b/scripts/add-new-version.js @@ -16,7 +16,7 @@ const versionRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d */ function execute(command) { return new Promise((resolve, reject) => { - exec(command, function (error, stdout, stderr) { //NOSONAR + exec(command, (error, stdout, stderr) => { //NOSONAR if (!error) resolve(stdout); console.error(stderr); reject(error); @@ -42,11 +42,12 @@ function addNewSchemaVersion(newVersion, newVersionDir, latestVersion) { const obj = require(objFile); // Adapt all the MUST supported schema formats + /* eslint-disable no-empty-pattern,no-unsafe-optional-chaining */ let mustSupportedSchemaFormats = [] = obj?.else?.properties?.schemaFormat?.anyOf[1]?.enum; //Add new version to the list of available schemaFormat values - if(mustSupportedSchemaFormats) { - if(isMajorVersionChange) { + if (mustSupportedSchemaFormats) { + if (isMajorVersionChange) { //Remove all old AsyncAPI schema formats because we want a clean slate mustSupportedSchemaFormats = mustSupportedSchemaFormats.filter((format) => !format.includes('application/vnd.aai.asyncapi')); } @@ -54,17 +55,17 @@ function addNewSchemaVersion(newVersion, newVersionDir, latestVersion) { mustSupportedSchemaFormats.push(...newSchemaFormats); obj.else.properties.schemaFormat.anyOf[1].enum = mustSupportedSchemaFormats; } else { - throw new Error("Could not find object to add schemaFormat values to"); + throw new Error('Could not find object to add schemaFormat values to'); } //Make sure new versions apply the right schema - let enumsForValidatingSchema = [] = obj?.else?.allOf[1]?.if?.properties?.schemaFormat?.enum; - if(enumsForValidatingSchema) { + const enumsForValidatingSchema = [] = obj?.else?.allOf[1]?.if?.properties?.schemaFormat?.enum; + if (enumsForValidatingSchema) { //Add new schema formats enumsForValidatingSchema.push(...newSchemaFormats); obj.else.allOf[1].if.properties.schemaFormat.enum = enumsForValidatingSchema; } else { - throw new Error("Could not find location for schemaFormats that applies the AsyncAPI Schema object to the schema property"); + throw new Error('Could not find location for schemaFormats that applies the AsyncAPI Schema object to the schema property'); } fs.writeFileSync(objFile, JSON.stringify(obj, null, 2)); @@ -87,9 +88,9 @@ async function addNewVersion(newVersion) { try { fs.accessSync(newVersionDir); - console.error(`Directory ${newVersionDir} already exist and cannot be overwritten. Please create a different version.`) + console.error(`Directory ${newVersionDir} already exist and cannot be overwritten. Please create a different version.`); return process.exit(1); - } catch (err) { } + } catch (err) /* eslint-disable no-empty */ { } //Use the newest version as baseline for the new one const latestVersion = (await execute('ls -d ./definitions/* | sort -V -r | head -1 | xargs -n 1 basename')).trim(); @@ -99,6 +100,7 @@ async function addNewVersion(newVersion) { await execute(`cp -R ./examples/${latestExampleVersion} ${newExampleVersionDir}`); // Replace $ref and $id paths such as `/3.0.0/` with new version (http://asyncapi.com/definitions/3.0.0/specificationExtension.json) + /* eslint-disable no-useless-escape */ await execute(`find ${newVersionDir} -name '*.json' -exec sed -i '' \"s+\/${latestVersion}\/+\/${newVersion}\/+g\" {} +`); // Replace .asyncapi version from old to new version @@ -108,12 +110,12 @@ async function addNewVersion(newVersion) { // Add new schemaFormat version entries addNewSchemaVersion(newVersion, newVersionDir, latestVersion); - console.log(`New version added to ${newVersionDir}`) + console.log(`New version added to ${newVersionDir}`); } const versionMatch = inputNewVersion.match(versionRegex); if (!versionMatch) { - console.error(`The new version ${inputNewVersion} must use semver versioning. `) + console.error(`The new version ${inputNewVersion} must use semver versioning. `); process.exit(1); } else { addNewVersion(inputNewVersion); diff --git a/scripts/validate-schemas.js b/scripts/validate-schemas.js index 200f2c52..91ec4c8d 100644 --- a/scripts/validate-schemas.js +++ b/scripts/validate-schemas.js @@ -7,82 +7,77 @@ const ajvDraft04 = new AjvDraft04(); const Ajv = require('ajv'); const ajv = new Ajv(); -function validation (excludedFiles){ - +/* eslint-disable sonarjs/cognitive-complexity */ +function validation (excludedFiles) { // Specify the path to the 'schemas' directory const directoryPath = './schemas'; - try{ - + try { const files = fs.readdirSync(directoryPath); // Filter files const filteredFiles = files.filter(file => !excludedFiles.includes(file) && path.extname(file).toLowerCase() === '.json'); - // Collect errors in an array const validationErrors = []; // Iterate through the filtered files filteredFiles.forEach(file => { - // Construct the full path to the JSON schema file - const filePath = path.join(directoryPath, file); - + // Construct the full path to the JSON schema file + const filePath = path.join(directoryPath, file); - try { - // Read and parse the JSON schema - const fileContent = fs.readFileSync(filePath, 'utf8'); - const obj = JSON.parse(fileContent); + try { + // Read and parse the JSON schema + const fileContent = fs.readFileSync(filePath, 'utf8'); + const obj = JSON.parse(fileContent); - let validate; - if (obj.$schema === 'http://json-schema.org/draft-04/schema') { - // Validate the schema - validate = ajvDraft04.validateSchema(obj); - if(validate){ - console.log(`\n${file}: JSON Schema is valid!`); - } - } else { - // Validate the schema - validate = ajv.validateSchema(obj); - if(validate){ - console.log(`\n${file}: JSON Schema is valid!`); - } - } + let validate; + if (obj.$schema === 'http://json-schema.org/draft-04/schema') { + // Validate the schema + validate = ajvDraft04.validateSchema(obj); + if (validate) { + console.log(`\n${file}: JSON Schema is valid!`); + } + } else { + // Validate the schema + validate = ajv.validateSchema(obj); + if (validate) { + console.log(`\n${file}: JSON Schema is valid!`); + } + } - // Check if the schema is not valid and collect errors - if (!validate) { - validationErrors.push({ - file, - errors: obj.$schema === 'http://json-schema.org/draft-04/schema' - ? ajvDraft04.errors - : ajv.errors - }); - } - } catch (error) { - validationErrors.push({ + // Check if the schema is not valid and collect errors + if (!validate) { + validationErrors.push({ file, - errors: [{ message: `\nError reading or parsing JSON Schema: ${error.message}` }] - }); + errors: obj.$schema === 'http://json-schema.org/draft-04/schema' + ? ajvDraft04.errors + : ajv.errors + }); } + } catch (error) { + validationErrors.push({ + file, + errors: [{ message: `\nError reading or parsing JSON Schema: ${error.message}` }] }); + } + }); - // Print errors after processing all files - validationErrors.forEach(({ file, errors }) => { - console.error(`\n${file}: JSON Schema is not valid:`, errors); - }); + // Print errors after processing all files + validationErrors.forEach(({ file, errors }) => { + console.error(`\n${file}: JSON Schema is not valid:`, errors); + }); - // Exit with an error code if there are validation errors - if (validationErrors.length > 0) { - process.exit(1); - } - - } catch (error) { - console.error('\nError during validation:', error.message); - process.exit(1); + // Exit with an error code if there are validation errors + if (validationErrors.length > 0) { + process.exit(1); } + } catch (error) { + console.error('\nError during validation:', error.message); + process.exit(1); + } } - const excludedFiles=['2.0.0-rc1.json', '2.0.0-rc1-without-$id.json']; // added temporarily to avoid validation failure due to these two files. The schemas version are incorrect in these and needs to be fixed. validation(excludedFiles); diff --git a/test/index.js b/test/index.js index 02e41eed..5d174716 100644 --- a/test/index.js +++ b/test/index.js @@ -9,13 +9,13 @@ describe('AsyncAPI', () => { }); it('should check if json schema is exported and if it matches the original file', () => { - const skipFiles = ["README", "all.schema-store", "1.0.0", "1.1.0", "1.2.0", "2.0.0-rc1", "2.0.0-rc2", "1.0.0-without-$id", "1.1.0-without-$id", "1.2.0-without-$id", "2.0.0-rc1-without-$id", "2.0.0-rc2-without-$id"]; + const skipFiles = ['README', 'all.schema-store', '1.0.0', '1.1.0', '1.2.0', '2.0.0-rc1', '2.0.0-rc2', '1.0.0-without-$id', '1.1.0-without-$id', '1.2.0-without-$id', '2.0.0-rc1-without-$id', '2.0.0-rc2-without-$id']; const files = fs.readdirSync('schemas'); files.forEach(file => { const fileName = path.parse(file).name; if (skipFiles.includes(fileName)) return; - const asyncapi = require('..') + const asyncapi = require('..'); if (fileName.includes('-without-$id')) { const schemaName = fileName.replace('-without-$id', ''); diff --git a/test/schemas.js b/test/schemas.js index 3d7c6a72..787490cf 100644 --- a/test/schemas.js +++ b/test/schemas.js @@ -1,13 +1,13 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const Ajv = require("ajv") +const Ajv = require('ajv'); const versionsToTest = [ { version: '3.0.0' } -] -describe("Should be able to validate", function () { +]; +describe('Should be able to validate', function () { this.timeout(30000); it('all valid documents', () => { const asyncapi = require('..'); @@ -24,12 +24,12 @@ describe("Should be able to validate", function () { validateFormats: false, strict: false }); - const documentPaths = fs.readdirSync(path.resolve(__dirname, `./docs/${version}`)).map((pathToDoc) => {return path.resolve(__dirname, `./docs/${version}/${pathToDoc}`)}); + const documentPaths = fs.readdirSync(path.resolve(__dirname, `./docs/${version}`)).map((pathToDoc) => {return path.resolve(__dirname, `./docs/${version}/${pathToDoc}`);}); for (const documentPath of documentPaths) { const document = require(documentPath); - const validate = ajv.compile(schema) - const valid = validate(document) - assert(valid === true, 'Document ' + documentPath + ' must be validated correctly: ' + JSON.stringify(validate.errors, null, 4)); + const validate = ajv.compile(schema); + const valid = validate(document); + assert(valid === true, `Document ${ documentPath } must be validated correctly: ${ JSON.stringify(validate.errors, null, 4)}`); } } } diff --git a/tools/bundler/index.js b/tools/bundler/index.js index 0ff04696..f752f456 100644 --- a/tools/bundler/index.js +++ b/tools/bundler/index.js @@ -1,7 +1,7 @@ const path = require('path'); const fs = require('fs'); const traverse = require('json-schema-traverse'); -const { url } = require('inspector'); +// const { url } = require('inspector'); const definitionsDirectory = path.resolve(__dirname, '../../definitions'); const bindingsDirectory = path.resolve(__dirname, '../../bindings'); const outputDirectory = path.resolve(__dirname, '../../schemas'); @@ -11,17 +11,17 @@ console.log(`Looking for binding version schemas in the following directory: ${b console.log(`Using the following output directory: ${outputDirectory}`); // definitionsRegex is used to transform the name of a definition into a valid one to be used in the -without-$id.json files. -const definitionsRegex = /http:\/\/asyncapi\.com\/definitions\/[^/]*\/(.+)\.json#?(.*)/i +const definitionsRegex = /http:\/\/asyncapi\.com\/definitions\/[^/]*\/(.+)\.json#?(.*)/i; // definitionsRegex is used to transform the name of a binding into a valid one to be used in the -without-$id.json files. -const bindingsRegex = /http:\/\/asyncapi\.com\/(bindings\/[^/]+)\/([^/]+)\/(.+)\.json(.*)/i +const bindingsRegex = /http:\/\/asyncapi\.com\/(bindings\/[^/]+)\/([^/]+)\/(.+)\.json(.*)/i; /** * Function to load all the core AsyncAPI spec definition (except the root asyncapi schema, as that will be loaded later) into the bundler. */ async function loadDefinitions(bundler, versionDir) { const definitions = await fs.promises.readdir(versionDir); - const definitionFiles = definitions.filter((value) => {return !value.includes('asyncapi')}).map((file) => fs.readFileSync(path.resolve(versionDir, file))); + const definitionFiles = definitions.filter((value) => {return !value.includes('asyncapi');}).map((file) => fs.readFileSync(path.resolve(versionDir, file))); const definitionJson = definitionFiles.map((file) => JSON.parse(file)); for (const jsonFile of definitionJson) { if (jsonFile.example) { @@ -67,8 +67,8 @@ async function loadBindings(bundler) { } console.log(`The following versions have separate definitions: ${versions.join(',')}`); for (const version of versions) { - const Bundler = require("@hyperjump/json-schema-bundle"); - try{ + const Bundler = require('@hyperjump/json-schema-bundle'); + try { console.log(`Bundling the following version together: ${version}`); const outputFileWithId = path.resolve(outputDirectory, `${version}.json`); const outputFileWithoutId = path.resolve(outputDirectory, `${version}-without-$id.json`); @@ -94,7 +94,7 @@ async function loadBindings(bundler) { const bundledSchemaWithoutIds = modifyRefsAndDefinitions(bundledSchemaWithId); console.log(`Writing the bundled file WITHOUT $ids to: ${outputFileWithoutId}`); await fs.promises.writeFile(outputFileWithoutId, JSON.stringify(bundledSchemaWithoutIds, null, 4)); - }catch(e) { + } catch (e) { throw new Error(e); } } @@ -113,24 +113,23 @@ async function loadRefProperties(filePath) { try { const data = await fs.promises.readFile(`../../examples${versionPath}`); return JSON.parse(data); - }catch(e) { - throw new Error(e); - } + } catch (e) { + throw new Error(e); } +} /** * we first update definitions from URL to normal names * than update refs to point to new definitions, always inline never remote */ function modifyRefsAndDefinitions(bundledSchema) { - //first we need to improve names of the definitions from URL to their names for (const def of Object.keys(bundledSchema.definitions)) { const newDefName = getDefinitionName(def); //creating copy of definition under new name so later definition stored under URL name can be removed bundledSchema.definitions[newDefName] = bundledSchema.definitions[def]; - delete bundledSchema.definitions[def] + delete bundledSchema.definitions[def]; } traverse(bundledSchema, replaceRef); @@ -138,7 +137,7 @@ function modifyRefsAndDefinitions(bundledSchema) { traverse(bundledSchema.definitions.openapiSchema_3_0, updateOpenApi); traverse(bundledSchema.definitions['json-schema-draft-07-schema'], updateJsonSchema); - return bundledSchema + return bundledSchema; } /** @@ -156,7 +155,7 @@ function getDefinitionName(def) { if (result) return `${result[1].replace('/', '-')}-${result[2]}-${result[3]}`; } - return path.basename(def, '.json') + return path.basename(def, '.json'); } /** @@ -165,10 +164,10 @@ function getDefinitionName(def) { */ function replaceRef(schema) { //new refs will only work if we remove $id that all point to asyncapi.com - delete schema.$id + delete schema.$id; //traversing shoudl take place only in case of schemas with refs - if (schema.$ref === undefined ) return; + if (schema.$ref === undefined) return; // updating refs that are related to remote URL refs that need to be update and point to inlined versions if (!schema.$ref.startsWith('#')) schema.$ref = `#/definitions/${getDefinitionName(schema.$ref)}`; } @@ -177,11 +176,12 @@ function replaceRef(schema) { * this is a callback used when traversing through json schema * to fix avro schema definitions to point to right direction */ -function updateAvro(schema){ +function updateAvro(schema) { //traversing shoudl take place only in case of schemas with refs if (schema.$ref === undefined) return; schema.$ref = schema.$ref.replace( + /* eslint-disable sonarjs/no-duplicate-string */ '#/definitions/', '#/definitions/avroSchema_v1/definitions/' ); @@ -191,7 +191,7 @@ function updateAvro(schema){ * this is a callback used when traversing through json schema * to fix open api schema definitions to point to right direction */ -function updateOpenApi(schema){ +function updateOpenApi(schema) { //traversing shoudl take place only in case of schemas with refs if (schema.$ref === undefined) return; const openApiPropName = 'openapiSchema_3_0'; @@ -210,7 +210,7 @@ function updateOpenApi(schema){ * this is a callback used when traversing through json schema * to fix open api schema definitions to point to right direction */ -function updateJsonSchema(schema){ +function updateJsonSchema(schema) { //traversing shoudl take place only in case of schemas with refs if (schema.$ref === undefined) return;