Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/apidom-reference/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@
"lint:fix": "eslint ./ --fix",
"clean": "rimraf ./es ./cjs ./dist ./types",
"test": "cross-env NODE_ENV=test BABEL_ENV=cjs mocha",
"perf": "cross-env NODE_ENV=test BABEL_ENV=cjs node ./test/perf/index.cjs",
"perf:openapi-3-1-dereference": "cross-env NODE_ENV=test BABEL_ENV=cjs node ./test/perf/openapi-3-1-dereference.cjs",
"typescript:check-types": "tsc --noEmit",
"typescript:declaration": "tsc -p declaration.tsconfig.json && rollup -c config/rollup/types.dist.js",
"prepack": "copyfiles -u 3 ../../LICENSES/* LICENSES && copyfiles -u 2 ../../NOTICE .",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { isUndefined } from 'ramda-adjunct';
import { Element, find } from '@swagger-api/apidom-core';
import { isSchemaElement } from '@swagger-api/apidom-ns-openapi-3-1';
import { Element, filter } from '@swagger-api/apidom-core';
import { isSchemaElement, SchemaElement } from '@swagger-api/apidom-ns-openapi-3-1';
import { uriToPointer, evaluate as jsonPointerEvaluate } from '@swagger-api/apidom-json-pointer';

import * as url from '../../../../../util/url';
import { EvaluationJsonSchemaUriError } from './errors';
import { isAnchor, uriToAnchor, evaluate as $anchorEvaluate } from '../$anchor';
import { resolveSchema$idField } from '../../../../../resolve/strategies/openapi-3-1/util';

// evaluates JSON Schema $ref containing unknown URI against ApiDOM fragment
// eslint-disable-next-line import/prefer-default-export
/**
* Evaluates JSON Schema $ref containing unknown URI against ApiDOM fragment.
*/
export const evaluate = <T extends Element>(uri: string, element: T): Element | undefined => {
const { cache } = evaluate;
const uriStrippedHash = url.stripHash(uri);
const result = find(
// @ts-ignore
(e) => {
if (!isSchemaElement(e)) return false;
if (typeof e.$id === 'undefined') return false;

const $idBaseURI = resolveSchema$idField(uriStrippedHash, e);
return $idBaseURI === uriStrippedHash;
},
element,
);
const isSchemaElementWith$id = (e: any) => isSchemaElement(e) && typeof e.$id !== 'undefined';

// warm the cache
if (!cache.has(element)) {
const schemaObjectElements = filter(isSchemaElementWith$id, element);
cache.set(element, Array.from(schemaObjectElements));
}

// search for the matching schema
const result = cache.get(element).find((e: SchemaElement) => {
const $idBaseURI = resolveSchema$idField(uriStrippedHash, e);
return $idBaseURI === uriStrippedHash;
});

if (isUndefined(result)) {
throw new EvaluationJsonSchemaUriError(`Evaluation failed on URI: "${uri}"`);
Expand All @@ -43,5 +47,6 @@ export const evaluate = <T extends Element>(uri: string, element: T): Element |
// @ts-ignore
return fragmentEvaluate(selector, result);
};
evaluate.cache = new WeakMap();

export { EvaluationJsonSchemaUriError };
5 changes: 5 additions & 0 deletions packages/apidom-reference/test/perf/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"@typescript-eslint/no-var-requires": 0
}
}
30 changes: 30 additions & 0 deletions packages/apidom-reference/test/perf/fixtures/openapi-3-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"openapi": "3.1.0",
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"login": {
"type": "string"
},
"password": {
"type": "string"
},
"profile": {
"$ref": "https://swagger.io/schemas/user-profile"
}
}
},
"UserProfile": {
"$id": "https://swagger.io/schemas/user-profile",
"type": "object",
"properties": {
"avatar": {
"type": "string"
}
}
}
}
}
}
19 changes: 19 additions & 0 deletions packages/apidom-reference/test/perf/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require('@babel/register')({ extensions: ['.js', '.ts'], rootMode: 'upward' });

const Benchmark = require('benchmark');

const openapi31Dereference = require('./openapi-3-1-dereference.cjs');

const suite = new Benchmark.Suite();

suite
.add(openapi31Dereference)
// add listeners
.on('cycle', function (event) {
console.info(String(event.target));
})
.on('complete', function () {
console.info('\nAll benchmarks have completed');
})
// run
.run();
39 changes: 39 additions & 0 deletions packages/apidom-reference/test/perf/openapi-3-1-dereference.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require('@babel/register')({ extensions: ['.js', '.ts'], rootMode: 'upward' });

const fs = require('node:fs');
const path = require('node:path');
const Benchmark = require('benchmark');
const { OpenApi3_1Element } = require('@swagger-api/apidom-ns-openapi-3-1')

const { dereferenceApiDOM } = require('../../src/configuration/saturated')

const fixturePath = path.join(__dirname, 'fixtures/openapi-3-1.json');
const source = fs.readFileSync(fixturePath).toString();
const apidom = OpenApi3_1Element.refract(JSON.parse(source))

const options = {
name: 'openapi-3-1-dereference',
defer: true,
minSamples: 600,
expected: '1,738 ops/sec ±2.66% (674 runs sampled)',
async fn(deferred) {
await dereferenceApiDOM(apidom);
deferred.resolve();
},
};

module.exports = options;

// we're running as a script
if (module.parent === null) {
const bench = new Benchmark({
...options,
onComplete(event) {
console.info(String(event.target));
},
onError(event) {
console.error(event);
},
});
bench.run();
}