Skip to content

Recipes

Vladimír Gorej edited this page Aug 31, 2023 · 4 revisions

Sequential dereferencing of ApiDOM fragments

The goal of this recipe is to demonstrate how to dereference ApiDOM fragments in sequential way, reusing the single instance of ReferenceSet.

fixture.json

{
  "openapi": "3.1.0",
  "components": {
    "schemas": {
      "a": {
        "$ref": "https://gist.githubusercontent.com/frantuma/e1aac0ce898985d3ceabbb40a41ff471/raw/441e54bd96d2da5ec8aca5120d5e136c4bf493bb/petstore31-3.json#/components/schemas/Pet"
      },
      "b": {
        "$ref": "https://gist.githubusercontent.com/frantuma/e1aac0ce898985d3ceabbb40a41ff471/raw/441e54bd96d2da5ec8aca5120d5e136c4bf493bb/petstore31-3.json#/components/schemas/Pet"
      }
    }
  }
}
import { mediaTypes } from '@swagger-api/apidom-ns-openapi-3-1';
import { ParseResultElement } from '@swagger-api/apidom-core';
import { parse, ReferenceSet, Reference, dereferenceApiDOM } from '@swagger-api/apidom-reference';

const fileURL = new URL('./fixture.json', import.meta.url).toString();
const parseResult = await parse(fileURL, {
  parse: {
    mediaType: mediaTypes.latest('json'),
  },
  resolve: {
    resolverOpts: {
      fileAllowList: ['*'],
    },
  },
});

const referenceElement1 = parseResult.result.get('components').get('schemas').get('a');
const referenceElement2 = parseResult.result.get('components').get('schemas').get('b');

const rootRef = Reference({ uri: fileURL, value: parseResult });
const reference1 = Reference({
  uri: `${fileURL}#reference1`,
  value: new ParseResultElement([referenceElement1]),
});
const reference2 = Reference({
  uri: `${fileURL}#reference2`,
  value: new ParseResultElement([referenceElement2]),
});

const refSet = ReferenceSet({ refs: [reference1, rootRef] });

const dereferenced1 = await dereferenceApiDOM(referenceElement1, {
  resolve: {
    baseURI: reference1.uri,
  },
  parse: {
    mediaType: mediaTypes.latest('json'),
  },
  dereference: {
    refSet,
  },
});

refSet.rootRef = null;

const dereferenced2 = await dereferenceApiDOM(referenceElement1, {
  resolve: {
    baseURI: reference2.uri,
  },
  parse: {
    mediaType: mediaTypes.latest('json'),
  },
  dereference: {
    refSet: refSet.add(reference2),
  },
});

console.dir([dereferenced1, dereferenced2]);

Concurrent dereferencing of ApiDOM fragments

The goal of this recipe is to demonstrate how to dereference ApiDOM fragments in concurrent way, using specialized SharedReferenceSet instances.

fixture.json

{
  "openapi": "3.1.0",
  "components": {
    "schemas": {
      "a": {
        "$ref": "https://gist.githubusercontent.com/frantuma/e1aac0ce898985d3ceabbb40a41ff471/raw/441e54bd96d2da5ec8aca5120d5e136c4bf493bb/petstore31-3.json#/components/schemas/Pet"
      },
      "b": {
        "$ref": "https://gist.githubusercontent.com/frantuma/e1aac0ce898985d3ceabbb40a41ff471/raw/441e54bd96d2da5ec8aca5120d5e136c4bf493bb/petstore31-3.json#/components/schemas/Pet"
      }
    }
  }
}
import stampit from 'stampit';
import { mediaTypes } from '@swagger-api/apidom-ns-openapi-3-1';
import { ParseResultElement } from '@swagger-api/apidom-core';
import { parse, ReferenceSet, Reference, dereferenceApiDOM } from '@swagger-api/apidom-reference';

const SharedReferenceSet = stampit(ReferenceSet, {
  statics: {
    refs: [],
    clean() {
      this.refs.forEach((ref) => {
        ref.refSet = null; // eslint-disable-line no-param-reassign
      });
      this.refs = [];
    },
  },
  init({ refs }, { stamp }) {
    this.rootRef = null;
    this.refs = stamp.refs;

    refs.forEach((ref) => this.add(ref));
  },
  methods: {
    add(reference) {
      if (this.has(reference)) {
        const foundReference = this.find((ref) => ref.uri === reference.uri);
        const foundReferenceIndex = this.refs.indexOf(foundReference);

        this.refs[foundReferenceIndex] = reference;
      } else {
        this.rootRef = this.rootRef === null ? reference : this.rootRef;
        this.refs.push(reference);
      }
      reference.refSet = this; // eslint-disable-line no-param-reassign

      return this;
    },
    clean() {
      throw new Error('Use static SharedReferenceSet.clean() instead.');
    },
  },
});

const fileURL = new URL('./fixture.json', import.meta.url).toString();
const parseResult = await parse(fileURL, {
  parse: {
    mediaType: mediaTypes.latest('json'),
  },
  resolve: {
    resolverOpts: {
      fileAllowList: ['*'],
    },
  },
});

const referenceElement1 = parseResult.result.get('components').get('schemas').get('a');
const referenceElement2 = parseResult.result.get('components').get('schemas').get('b');

const rootRef = Reference({ uri: fileURL, value: parseResult });
const reference1 = Reference({
  uri: `${fileURL}#reference1`,
  value: new ParseResultElement([referenceElement1]),
});
const reference2 = Reference({
  uri: `${fileURL}#reference2`,
  value: new ParseResultElement([referenceElement2]),
});

const sharedRefSet1 = SharedReferenceSet({ refs: [reference1, rootRef] });
const sharedRefSet2 = SharedReferenceSet({ refs: [reference2, rootRef] });

const dereferencedP1 = dereferenceApiDOM(referenceElement1, {
  resolve: {
    baseURI: reference1.uri,
  },
  parse: {
    mediaType: mediaTypes.latest('json'),
  },
  dereference: {
    refSet: sharedRefSet1,
  },
});

const dereferencedP2 = dereferenceApiDOM(referenceElement1, {
  resolve: {
    baseURI: reference2.uri,
  },
  parse: {
    mediaType: mediaTypes.latest('json'),
  },
  dereference: {
    refSet: sharedRefSet2,
  },
});

const dereferenced = await Promise.all([dereferencedP1, dereferencedP2]);
SharedReferenceSet.clean();
console.dir(dereferenced);
Clone this wiki locally