Skip to content

Commit

Permalink
feat(reference): change ReferenceSet from stamp to TypeScript class (#…
Browse files Browse the repository at this point in the history
…4100)

Refs #3481

BREAKING CHANGE: ReferenceSet 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 88f859c commit aeb195b
Show file tree
Hide file tree
Showing 21 changed files with 128 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const securitySchemeTypeRefractorPlugin =
uri: `${baseURI}#reference`,
value: new ParseResultElement([referenceElement]),
});
const refSet = ReferenceSet({ refs: [reference, rootReference] });
const refSet = new ReferenceSet({ refs: [reference, rootReference] });
// eslint-disable-next-line no-await-in-loop
const dereferenced = await dereferenceApiDOM(referenceElement, {
resolve: { baseURI: reference.uri },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export class DefaultValidationService implements ValidationService {
uri: `${baseURI}#reference${fragmentId}`,
value: refEl,
});
const refSet = ReferenceSet({ refs: [referenceElementReference, apiReference] });
const refSet = new ReferenceSet({ refs: [referenceElementReference, apiReference] });

try {
const promise = dereferenceApiDOM(refEl, {
Expand Down Expand Up @@ -344,7 +344,7 @@ export class DefaultValidationService implements ValidationService {
uri: `${baseURI}#reference${fragmentId}`,
value: refEl,
});
const refSet = ReferenceSet({ refs: [referenceElementReference, apiReference] });
const refSet = new ReferenceSet({ refs: [referenceElementReference, apiReference] });

try {
// eslint-disable-next-line no-await-in-loop
Expand Down
2 changes: 1 addition & 1 deletion packages/apidom-reference/src/Reference.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Element } from '@swagger-api/apidom-core';

import { ReferenceSet } from './types';
import ReferenceSet from './ReferenceSet';

export interface ReferenceOptions<T = Element> {
readonly uri: string;
Expand Down
116 changes: 60 additions & 56 deletions packages/apidom-reference/src/ReferenceSet.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,67 @@
import stampit from 'stampit';
import { propEq } from 'ramda';
import { isNotUndefined, isString } from 'ramda-adjunct';

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

const ReferenceSet: stampit.Stamp<IReferenceSet> = stampit({
props: {
rootRef: null,
refs: [],
circular: false,
},
init({ refs = [] } = {}) {
export interface ReferenceSetOptions {
readonly refs?: Reference[];
readonly circular?: boolean;
}

class ReferenceSet {
public rootRef?: Reference;

public readonly refs: Reference[];

public readonly circular: boolean;

constructor({ refs = [], circular = false }: ReferenceSetOptions = {}) {
this.refs = [];
refs.forEach((ref: Reference) => this.add(ref));
},
methods: {
get size(): number {
// @ts-ignore
return this.refs.length;
},

add(reference: Reference): IReferenceSet {
if (!this.has(reference)) {
this.refs.push(reference);
this.rootRef = this.rootRef === null ? reference : this.rootRef;
reference.refSet = this; // eslint-disable-line no-param-reassign
}
return this;
},

merge(anotherRefSet: IReferenceSet): IReferenceSet {
for (const reference of anotherRefSet.values()) {
this.add(reference);
}
return this;
},

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

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

*values() {
yield* this.refs;
},

clean() {
this.refs.forEach((ref: Reference) => {
ref.refSet = undefined; // eslint-disable-line no-param-reassign
});
this.rootRef = null;
this.refs = [];
},
},
});
this.circular = circular;
refs.forEach(this.add.bind(this));
}

get size(): number {
return this.refs.length;
}

add(reference: Reference): this {
if (!this.has(reference)) {
this.refs.push(reference);
this.rootRef = this.rootRef === undefined ? reference : this.rootRef;
reference.refSet = this; // eslint-disable-line no-param-reassign
}
return this;
}

merge(anotherRefSet: this): this {
for (const reference of anotherRefSet.values()) {
this.add(reference);
}
return this;
}

has(thing: string | Reference): boolean {
const uri = isString(thing) ? thing : thing.uri;
return isNotUndefined(this.find((ref: Reference) => ref.uri === uri));
}

find(
predicate: (value: Reference, index: number, obj: Reference[]) => boolean,
): Reference | undefined {
return this.refs.find(predicate);
}

*values() {
yield* this.refs;
}

clean() {
this.refs.forEach((ref: Reference) => {
ref.refSet = undefined; // eslint-disable-line no-param-reassign
});
this.rootRef = undefined;
this.refs.length = 0;
}
}

export default ReferenceSet;
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
},

async dereference(file: File, options: IReferenceOptions): Promise<Element> {
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
const mutableRefsSet = ReferenceSet();
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
const mutableRefSet = new ReferenceSet();
let refSet = immutableRefSet;
let reference;

Expand All @@ -55,19 +55,19 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefsSet;
.forEach((ref) => mutableRefSet.add(ref));
reference = mutableRefSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefSet;
}

const visitor = ApiDOMDereferenceVisitor({ reference, options });
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor);
const dereferencedElement = await visitAsync(refSet.rootRef!.value, visitor);

/**
* If immutable option is set, replay refs from the refSet.
*/
if (options.dereference.immutable) {
mutableRefsSet.refs
mutableRefSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map(
(ref) =>
Expand All @@ -89,7 +89,7 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
immutableRefSet.clean();
}

mutableRefsSet.clean();
mutableRefSet.clean();

return dereferencedElement;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi

async dereference(file: File, options: IReferenceOptions): Promise<Element> {
const namespace = createNamespace(asyncApi2Namespace);
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
const mutableRefsSet = ReferenceSet();
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
const mutableRefSet = new ReferenceSet();
let refSet = immutableRefSet;
let reference;

Expand All @@ -65,13 +65,13 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefsSet;
.forEach((ref) => mutableRefSet.add(ref));
reference = mutableRefSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefSet;
}

const visitor = AsyncApi2DereferenceVisitor({ reference, namespace, options });
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor, {
const dereferencedElement = await visitAsync(refSet.rootRef!.value, visitor, {
keyMap,
nodeTypeGetter: getNodeType,
});
Expand All @@ -80,7 +80,7 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
* If immutable option is set, replay refs from the refSet.
*/
if (options.dereference.immutable) {
mutableRefsSet.refs
mutableRefSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map(
(ref) =>
Expand All @@ -102,7 +102,7 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
immutableRefSet.clean();
}

mutableRefsSet.clean();
mutableRefSet.clean();

return dereferencedElement;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit

async dereference(file: File, options: IReferenceOptions): Promise<Element> {
const namespace = createNamespace(openApi2Namespace);
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
const mutableRefsSet = ReferenceSet();
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
const mutableRefSet = new ReferenceSet();
let refSet = immutableRefSet;
let reference;

Expand All @@ -65,13 +65,13 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefsSet;
.forEach((ref) => mutableRefSet.add(ref));
reference = mutableRefSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefSet;
}

const visitor = OpenApi2DereferenceVisitor({ reference, namespace, options });
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor, {
const dereferencedElement = await visitAsync(refSet.rootRef!.value, visitor, {
keyMap,
nodeTypeGetter: getNodeType,
});
Expand All @@ -80,7 +80,7 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
* If immutable option is set, replay refs from the refSet.
*/
if (options.dereference.immutable) {
mutableRefsSet.refs
mutableRefSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map(
(ref) =>
Expand All @@ -102,7 +102,7 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
immutableRefSet.clean();
}

mutableRefsSet.clean();
mutableRefSet.clean();

return dereferencedElement;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ const OpenApi3_0DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp

async dereference(file: File, options: IReferenceOptions): Promise<Element> {
const namespace = createNamespace(openApi3_0Namespace);
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
const mutableRefsSet = ReferenceSet();
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
const mutableRefSet = new ReferenceSet();
let refSet = immutableRefSet;
let reference;

Expand All @@ -67,13 +67,13 @@ const OpenApi3_0DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefsSet;
.forEach((ref) => mutableRefSet.add(ref));
reference = mutableRefSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefSet;
}

const visitor = OpenApi3_0DereferenceVisitor({ reference, namespace, options });
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor, {
const dereferencedElement = await visitAsync(refSet.rootRef!.value, visitor, {
keyMap,
nodeTypeGetter: getNodeType,
});
Expand All @@ -82,7 +82,7 @@ const OpenApi3_0DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp
* If immutable option is set, replay refs from the refSet.
*/
if (options.dereference.immutable) {
mutableRefsSet.refs
mutableRefSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map(
(ref) =>
Expand All @@ -104,7 +104,7 @@ const OpenApi3_0DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp
immutableRefSet.clean();
}

mutableRefsSet.clean();
mutableRefSet.clean();

return dereferencedElement;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ const OpenApi3_1DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp

async dereference(file: File, options: IReferenceOptions): Promise<Element> {
const namespace = createNamespace(openApi3_1Namespace);
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
const mutableRefsSet = ReferenceSet();
const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
const mutableRefSet = new ReferenceSet();
let refSet = immutableRefSet;
let reference;

Expand All @@ -67,13 +67,13 @@ const OpenApi3_1DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp
value: cloneDeep(ref.value),
}),
)
.forEach((ref) => mutableRefsSet.add(ref));
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefsSet;
.forEach((ref) => mutableRefSet.add(ref));
reference = mutableRefSet.find((ref) => ref.uri === file.uri);
refSet = mutableRefSet;
}

const visitor = OpenApi3_1DereferenceVisitor({ reference, namespace, options });
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor, {
const dereferencedElement = await visitAsync(refSet.rootRef!.value, visitor, {
keyMap,
nodeTypeGetter: getNodeType,
});
Expand All @@ -82,7 +82,7 @@ const OpenApi3_1DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp
* If immutable option is set, replay refs from the refSet.
*/
if (options.dereference.immutable) {
mutableRefsSet.refs
mutableRefSet.refs
.filter((ref) => ref.uri.startsWith('immutable://'))
.map(
(ref) =>
Expand All @@ -104,7 +104,7 @@ const OpenApi3_1DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stamp
immutableRefSet.clean();
}

mutableRefsSet.clean();
mutableRefSet.clean();

return dereferencedElement;
},
Expand Down
Loading

0 comments on commit aeb195b

Please sign in to comment.