88 lines
2.0 KiB
TypeScript

import { JsonSchema, JsonSchema1 } from '@nx/nx-dev/models-package';
import { get as pointerGet } from 'jsonpointer';
/**
* @param reference '#' is root
* @param lookup Instantiated Lookup class
*/
export function getSchemaFromReference(
reference: string,
lookup: Lookup
): JsonSchema | undefined {
return getSchemaFromResult(loadReference(reference, lookup));
}
export function loadReference(reference: string, lookup: Lookup): LookupResult {
return lookup.getSchema({ $ref: reference });
}
export function getSchemaFromResult(
result: LookupResult
): JsonSchema | undefined {
return result === undefined ? undefined : result.schema;
}
export type LookupResult =
| undefined
| {
schema: JsonSchema;
baseReference?: string;
};
function isReference(s: JsonSchema1): boolean {
return s.$ref !== undefined;
}
export interface Lookup {
getSchema: (schema: JsonSchema) => LookupResult;
}
export class IdLookup {
getSchema(schema: JsonSchema): LookupResult {
if (typeof schema === 'boolean') {
return { schema };
}
if (isReference(schema)) {
return undefined;
}
return { schema };
}
}
export class InternalLookup {
constructor(private schema: JsonSchema) {}
getSchema(schema: JsonSchema): LookupResult {
if (schema === undefined) {
return undefined;
}
if (typeof schema === 'boolean') return { schema };
if (schema.$ref === undefined) return { schema };
const ref = schema.$ref;
if (!ref.startsWith('#')) {
// We do not support non-internal references
console.error(
'[SCHEMA] The schema appears to have non-internal references which is not supported:',
ref
);
return undefined;
}
const result = pointerGet(this.schema, ref.slice(1));
if (result === undefined) return undefined;
const subResult = this.getSchema(result);
if (subResult === undefined) return undefined;
return {
schema: subResult.schema,
baseReference: subResult.baseReference ?? ref,
};
}
}