Skip to content

Commit

Permalink
feat(reference): change Reference from stamp to TypeScript class (#4099)
Browse files Browse the repository at this point in the history
Refs #3481

BREAKING CHANGE: Reference from apidom-reference package became a class and requires to be instantiated with new operator.
  • Loading branch information
char0n committed May 14, 2024
1 parent cb4b90b commit 88f859c
Show file tree
Hide file tree
Showing 19 changed files with 136 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,15 @@ const securitySchemeTypeRefractorPlugin =
* to Security Scheme Objects that are going to be removed.
*/
const baseURI = url.cwd();
const rootReference = Reference({ uri: baseURI, value: cloneDeep(parseResultElement!) });
const rootReference = new Reference({
uri: baseURI,
value: cloneDeep(parseResultElement!),
});
for (const memberElement of element.securitySchemes) {
if (!isReferenceElement(memberElement.value)) continue; // eslint-disable-line no-continue

const { value: referenceElement } = memberElement;
const reference = Reference({
const reference = new Reference({
uri: `${baseURI}#reference`,
value: new ParseResultElement([referenceElement]),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,11 @@ export class DefaultValidationService implements ValidationService {
const baseURI = validationContext?.baseURI
? validationContext?.baseURI
: 'https://smartbear.com/';
const apiReference = Reference({ uri: baseURI, value: cloneDeep(result) });
const apiReference = new Reference({ uri: baseURI, value: cloneDeep(result)! });
const cachedParsers = options.parse.parsers.map(DefaultValidationService.createCachedParser);

for (const [fragmentId, refEl] of refElements.entries()) {
const referenceElementReference = Reference({
const referenceElementReference = new Reference({
uri: `${baseURI}#reference${fragmentId}`,
value: refEl,
});
Expand Down Expand Up @@ -336,11 +336,11 @@ export class DefaultValidationService implements ValidationService {
const baseURI = validationContext?.baseURI
? validationContext?.baseURI
: 'https://smartbear.com/';
const apiReference = Reference({ uri: baseURI, value: cloneDeep(result) });
const apiReference = new Reference({ uri: baseURI, value: cloneDeep(result) });
const cachedParsers = options.parse.parsers.map(DefaultValidationService.createCachedParser);

for (const [fragmentId, refEl] of refElements.entries()) {
const referenceElementReference = Reference({
const referenceElementReference = new Reference({
uri: `${baseURI}#reference${fragmentId}`,
value: refEl,
});
Expand Down
43 changes: 25 additions & 18 deletions packages/apidom-reference/src/Reference.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import stampit from 'stampit';

import { Reference as IReference } from './types';

const Reference: stampit.Stamp<IReference> = stampit({
props: {
uri: '',
value: null,
depth: 0,
refSet: null,
errors: [],
},
init(
this: IReference,
{ depth = this.depth, refSet = this.refSet, uri = this.uri, value = this.value } = {},
) {
import { Element } from '@swagger-api/apidom-core';

import { ReferenceSet } from './types';

export interface ReferenceOptions<T = Element> {
readonly uri: string;
readonly depth?: number;
readonly refSet?: ReferenceSet;
readonly value: T;
}

class Reference<T = Element> {
public readonly uri: string;

public readonly depth: number;

public readonly value: T;

public refSet?: ReferenceSet;

public readonly errors: Array<Error>;

constructor({ uri, depth = 0, refSet, value }: ReferenceOptions<T>) {
this.uri = uri;
this.value = value;
this.depth = depth;
this.refSet = refSet;
this.errors = [];
},
});
}
}

export default Reference;
15 changes: 8 additions & 7 deletions packages/apidom-reference/src/ReferenceSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import stampit from 'stampit';
import { propEq } from 'ramda';
import { isNotUndefined, isString } from 'ramda-adjunct';

import { Reference as IReference, ReferenceSet as IReferenceSet } from './types';
import { ReferenceSet as IReferenceSet } from './types';
import type Reference from './Reference';

const ReferenceSet: stampit.Stamp<IReferenceSet> = stampit({
props: {
Expand All @@ -12,15 +13,15 @@ const ReferenceSet: stampit.Stamp<IReferenceSet> = stampit({
},
init({ refs = [] } = {}) {
this.refs = [];
refs.forEach((ref: IReference) => this.add(ref));
refs.forEach((ref: Reference) => this.add(ref));
},
methods: {
get size(): number {
// @ts-ignore
return this.refs.length;
},

add(reference: IReference): IReferenceSet {
add(reference: Reference): IReferenceSet {
if (!this.has(reference)) {
this.refs.push(reference);
this.rootRef = this.rootRef === null ? reference : this.rootRef;
Expand All @@ -36,12 +37,12 @@ const ReferenceSet: stampit.Stamp<IReferenceSet> = stampit({
return this;
},

has(thing: string | IReference): boolean {
has(thing: string | Reference): boolean {
const uri = isString(thing) ? thing : thing.uri;
return isNotUndefined(this.find(propEq(uri, 'uri')));
},

find(callback): IReference | undefined {
find(callback): Reference | undefined {
return this.refs.find(callback);
},

Expand All @@ -50,8 +51,8 @@ const ReferenceSet: stampit.Stamp<IReferenceSet> = stampit({
},

clean() {
this.refs.forEach((ref: IReference) => {
ref.refSet = null; // eslint-disable-line no-param-reassign
this.refs.forEach((ref: Reference) => {
ref.refSet = undefined; // eslint-disable-line no-param-reassign
});
this.rootRef = null;
this.refs = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(

// determine the initial reference
if (!immutableRefSet.has(file.uri)) {
reference = Reference({ uri: file.uri, value: file.parseResult });
reference = new Reference({ uri: file.uri, value: file.parseResult! });
immutableRefSet.add(reference);
} else {
// pre-computed refSet was provided as configuration option
Expand All @@ -48,11 +48,12 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
*/
if (options.dereference.immutable) {
immutableRefSet.refs
.map((ref) =>
Reference({
...ref,
value: cloneDeep(ref.value),
}),
.map(
(ref) =>
new Reference({
...ref,
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
Expand All @@ -68,11 +69,12 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
if (options.dereference.immutable) {
mutableRefsSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map((ref) =>
Reference({
...ref,
uri: ref.uri.replace(/^immutable:\/\//, ''),
}),
.map(
(ref) =>
new Reference({
...ref,
uri: ref.uri.replace(/^immutable:\/\//, ''),
}),
)
.forEach((ref) => immutableRefSet.add(ref));
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
} from '@swagger-api/apidom-core';
import { uriToPointer as uriToElementID } from '@swagger-api/apidom-json-pointer';

import { Reference as IReference } from '../../../types';
import MaximumResolveDepthError from '../../../errors/MaximumResolveDepthError';
import * as url from '../../../util/url';
import parse from '../../../parse';
Expand Down Expand Up @@ -53,7 +52,7 @@ const ApiDOMDereferenceVisitor = stampit({
return url.resolve(this.reference.uri, url.sanitize(url.stripHash(uri)));
},

async toReference(uri: string): Promise<IReference> {
async toReference(uri: string): Promise<Reference> {
// detect maximum depth of resolution
if (this.reference.depth >= this.options.resolve.maxDepth) {
throw new MaximumResolveDepthError(
Expand All @@ -75,7 +74,7 @@ const ApiDOMDereferenceVisitor = stampit({
});

// register new mutable reference with a refSet
const mutableReference = Reference({
const mutableReference = new Reference({
uri: baseURI,
value: cloneDeep(parseResult),
depth: this.reference.depth + 1,
Expand All @@ -84,7 +83,7 @@ const ApiDOMDereferenceVisitor = stampit({

if (this.options.dereference.immutable) {
// register new immutable reference with a refSet
const immutableReference = Reference({
const immutableReference = new Reference({
uri: `immutable://${baseURI}`,
value: parseResult,
depth: this.reference.depth + 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
let reference;

if (!immutableRefSet.has(file.uri)) {
reference = Reference({ uri: file.uri, value: file.parseResult });
reference = new Reference({ uri: file.uri, value: file.parseResult! });
immutableRefSet.add(reference);
} else {
// pre-computed refSet was provided as configuration option
Expand All @@ -58,11 +58,12 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
*/
if (options.dereference.immutable) {
immutableRefSet.refs
.map((ref) =>
Reference({
...ref,
value: cloneDeep(ref.value),
}),
.map(
(ref) =>
new Reference({
...ref,
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
Expand All @@ -81,11 +82,12 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
if (options.dereference.immutable) {
mutableRefsSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map((ref) =>
Reference({
...ref,
uri: ref.uri.replace(/^immutable:\/\//, ''),
}),
.map(
(ref) =>
new Reference({
...ref,
uri: ref.uri.replace(/^immutable:\/\//, ''),
}),
)
.forEach((ref) => immutableRefSet.add(ref));
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
ReferenceElement,
} from '@swagger-api/apidom-ns-asyncapi-2';

import { Reference as IReference } from '../../../types';
import MaximumDereferenceDepthError from '../../../errors/MaximumDereferenceDepthError';
import MaximumResolveDepthError from '../../../errors/MaximumResolveDepthError';
import { AncestorLineage } from '../../util';
Expand Down Expand Up @@ -70,7 +69,7 @@ const AsyncApi2DereferenceVisitor = stampit({
return url.resolve(this.reference.uri, url.sanitize(url.stripHash(uri)));
},

async toReference(uri: string): Promise<IReference> {
async toReference(uri: string): Promise<Reference> {
// detect maximum depth of resolution
if (this.reference.depth >= this.options.resolve.maxDepth) {
throw new MaximumResolveDepthError(
Expand All @@ -92,7 +91,7 @@ const AsyncApi2DereferenceVisitor = stampit({
});

// register new mutable reference with a refSet
const mutableReference = Reference({
const mutableReference = new Reference({
uri: baseURI,
value: cloneDeep(parseResult),
depth: this.reference.depth + 1,
Expand All @@ -101,7 +100,7 @@ const AsyncApi2DereferenceVisitor = stampit({

if (this.options.dereference.immutable) {
// register new immutable reference with a refSet
const immutableReference = Reference({
const immutableReference = new Reference({
uri: `immutable://${baseURI}`,
value: parseResult,
depth: this.reference.depth + 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
let reference;

if (!immutableRefSet.has(file.uri)) {
reference = Reference({ uri: file.uri, value: file.parseResult });
reference = new Reference({ uri: file.uri, value: file.parseResult! });
immutableRefSet.add(reference);
} else {
// pre-computed refSet was provided as configuration option
Expand All @@ -58,11 +58,12 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
*/
if (options.dereference.immutable) {
immutableRefSet.refs
.map((ref) =>
Reference({
...ref,
value: cloneDeep(ref.value),
}),
.map(
(ref) =>
new Reference({
...ref,
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
Expand All @@ -81,11 +82,12 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
if (options.dereference.immutable) {
mutableRefsSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map((ref) =>
Reference({
...ref,
uri: ref.uri.replace(/^immutable:\/\//, ''),
}),
.map(
(ref) =>
new Reference({
...ref,
uri: ref.uri.replace(/^immutable:\/\//, ''),
}),
)
.forEach((ref) => immutableRefSet.add(ref));
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
JSONReferenceElement,
} from '@swagger-api/apidom-ns-openapi-2';

import { Reference as IReference } from '../../../types';
import MaximumDereferenceDepthError from '../../../errors/MaximumDereferenceDepthError';
import MaximumResolveDepthError from '../../../errors/MaximumResolveDepthError';
import { AncestorLineage } from '../../util';
Expand Down Expand Up @@ -71,7 +70,7 @@ const OpenApi2DereferenceVisitor = stampit({
return url.resolve(this.reference.uri, url.sanitize(url.stripHash(uri)));
},

async toReference(uri: string): Promise<IReference> {
async toReference(uri: string): Promise<Reference> {
// detect maximum depth of resolution
if (this.reference.depth >= this.options.resolve.maxDepth) {
throw new MaximumResolveDepthError(
Expand All @@ -93,7 +92,7 @@ const OpenApi2DereferenceVisitor = stampit({
});

// register new mutable reference with a refSet
const mutableReference = Reference({
const mutableReference = new Reference({
uri: baseURI,
value: cloneDeep(parseResult),
depth: this.reference.depth + 1,
Expand All @@ -102,7 +101,7 @@ const OpenApi2DereferenceVisitor = stampit({

if (this.options.dereference.immutable) {
// register new immutable reference with a refSet
const immutableReference = Reference({
const immutableReference = new Reference({
uri: `immutable://${baseURI}`,
value: parseResult,
depth: this.reference.depth + 1,
Expand Down

0 comments on commit 88f859c

Please sign in to comment.