@rxap/plugin-library
Version:
This package provides generators and executors for managing and maintaining Nx plugin libraries. It includes functionality for generating index exports, fixing dependencies, generating JSON schemas, and more. It helps streamline the development process fo
163 lines • 7.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.bundleJsonSchemaGenerator = bundleJsonSchemaGenerator;
const tslib_1 = require("tslib");
const json_schema_ref_parser_1 = tslib_1.__importDefault(require("@apidevtools/json-schema-ref-parser"));
const utilities_1 = require("@rxap/utilities");
const workspace_utilities_1 = require("@rxap/workspace-utilities");
const path_1 = require("path");
const generator_1 = require("../index-json-schema/generator");
/**
* Remove the definitions and $id and $schema properties from the schema and normalize the $ref properties to only have
* the prefix '#/definitions/' before the definition name
* @param tree
* @param projectSourceRoot
* @param $ref
*/
function loadCleanDefinition(tree, projectSourceRoot, { $ref }) {
const filePath = (0, path_1.join)(projectSourceRoot, $ref);
if (!tree.exists(filePath)) {
throw new Error(`The file '${filePath}' does not exist!`);
}
const schema = JSON.parse(tree.read(filePath).toString());
return cleanupDefinition(schema);
}
function cleanupDefinition(schema) {
if (schema['definitions']) {
schema['definitions'] = Object.entries(schema['definitions']).reduce((acc, [key, value]) => {
if (!value['$ref']) {
acc[key] = cleanupDefinition(value);
}
return acc;
}, {});
if (Object.keys(schema['definitions']).length === 0) {
delete schema['definitions'];
}
}
if (schema['$schema']) {
delete schema['$schema'];
}
if (schema['$id']) {
delete schema['$id'];
}
for (const { key, value, propertyPath, parent } of (0, utilities_1.EachProperty)(schema)) {
if (key === '$ref') {
if (typeof value === 'string') {
(parent !== null && parent !== void 0 ? parent : schema)[key] = value.replace(/^#\/definitions\//, '#/definitions/');
}
}
}
return schema;
}
function getCleanDefinitionMap(tree, projectSourceRoot, definitions) {
const resolvedDefinitions = {};
for (const [key, definition] of Object.entries(definitions)) {
resolvedDefinitions[key] = loadCleanDefinition(tree, projectSourceRoot, definition);
}
return resolvedDefinitions;
}
function bundleJsonSchemaGenerator(tree, options) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const projectSourceRoot = (0, workspace_utilities_1.GetProjectSourceRoot)(tree, options.project);
const workspaceRoot = tree.root;
const definitions = getCleanDefinitionMap(tree, projectSourceRoot, (0, generator_1.GenerateDefinitionsMap)(tree, options));
for (const file of (0, workspace_utilities_1.SearchFile)(tree, projectSourceRoot)) {
if (file.path.endsWith('template.schema.json')) {
const relativePathFromProjectSourceRoot = (0, path_1.dirname)((0, path_1.relative)(projectSourceRoot, file.path));
const schema = JSON.parse(file.content.toString());
const bundledSchema = yield json_schema_ref_parser_1.default.bundle(schema, {
resolve: {
file: {
canRead: ({ url }) => {
if (url.startsWith('http')) {
return false;
}
const relativeFromSchemaJsonFile = (0, path_1.relative)(workspaceRoot, url);
const absoluteFromSourceRoot = (0, path_1.join)(relativePathFromProjectSourceRoot, relativeFromSchemaJsonFile);
const absoluteFromWorkspaceRoot = (0, path_1.join)(projectSourceRoot, absoluteFromSourceRoot);
return tree.isFile(absoluteFromWorkspaceRoot);
},
read: ({ url }) => {
const relativeFromSchemaJsonFile = (0, path_1.relative)(workspaceRoot, url);
const absoluteFromSourceRoot = (0, path_1.join)(relativePathFromProjectSourceRoot, relativeFromSchemaJsonFile);
const absoluteFromWorkspaceRoot = (0, path_1.join)(projectSourceRoot, absoluteFromSourceRoot);
return tree.read(absoluteFromWorkspaceRoot).toString();
}
}
}
});
// removeProperty(bundledSchema, 'definitions');
// removeProperty(bundledSchema, '$id');
// removeProperty(bundledSchema, '$schema');
bundledSchema['definitions'] = Object.assign(Object.assign({}, bundledSchema['definitions']), definitions);
fixNestaedDefinitions(bundledSchema);
for (const [, definition] of Object.entries(bundledSchema['definitions'])) {
cleanupDefinition(definition);
}
(_a = bundledSchema['definitions']) !== null && _a !== void 0 ? _a : (bundledSchema['definitions'] = {});
bundledSchema['definitions'] = Object.entries(bundledSchema['definitions']).sort(([a], [b]) => a.localeCompare(b)).reduce((acc, [key, value]) => (Object.assign(Object.assign({}, acc), { [key]: value })), {});
(0, workspace_utilities_1.CoerceFile)(tree, file.path.replace('template.schema.json', 'schema.json'), JSON.stringify(bundledSchema, null, 2), true);
}
}
});
}
function removeProperty(obj, propertyName) {
const propertyPaths = [];
for (const { key, propertyPath } of (0, utilities_1.EachProperty)(obj)) {
if (key === propertyName) {
propertyPaths.push(propertyPath);
}
}
for (const propertyPath of propertyPaths) {
if (propertyPath === propertyName) {
continue;
}
(0, utilities_1.RemoveFromObject)(obj, propertyPath);
}
}
function getUsedDefinitions(item) {
const usedDefinitions = [];
for (const { key, value, parent } of (0, utilities_1.EachProperty)(item)) {
if (key === '$ref') {
if (typeof value !== 'string') {
throw new Error(`The value of the key '$ref' in definition '${key}' is not a string!`);
}
usedDefinitions.push(value.replace(/^#\/definitions\//, ''));
}
}
return usedDefinitions;
}
function fixNestaedDefinitions(schema) {
var _a;
const usedDefinitions = [];
// create a list of used refs excluding the definitions
for (const [key, item] of Object.entries(schema !== null && schema !== void 0 ? schema : {})) {
if (key === 'definitions') {
continue;
}
if (typeof item !== 'object') {
continue;
}
(0, utilities_1.CoerceArrayItems)(usedDefinitions, getUsedDefinitions(item));
}
let removeList = Object.keys(schema.definitions).filter((key) => !usedDefinitions.includes(key));
let removeListLength = 0;
do {
removeListLength = removeList.length;
// check for each definition that will not be removed if it is using another definition that should be removed
// if yes remove this from the list of definitions to remove
for (const [key, item] of Object.entries((_a = schema.definitions) !== null && _a !== void 0 ? _a : {})) {
if (removeList.includes(key)) {
continue;
}
(0, utilities_1.CoerceArrayItems)(usedDefinitions, getUsedDefinitions(item));
}
removeList = removeList.filter((key) => !usedDefinitions.includes(key));
} while (removeListLength !== removeList.length);
for (const key of removeList) {
delete schema.definitions[key];
}
}
exports.default = bundleJsonSchemaGenerator;
//# sourceMappingURL=generator.js.map