Skip to content

Commit

Permalink
Merge pull request #390 from vlad-markin/hotfix/manifestschema-for-ba…
Browse files Browse the repository at this point in the history
…ckend

Hotfix/manifestschema for backend
  • Loading branch information
rpiontik authored Oct 7, 2023
2 parents 0f387a8 + ac82c29 commit c1229d3
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 162 deletions.
36 changes: 36 additions & 0 deletions src/backend/entities/entities.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {BaseEntities} from '../../global/entities/entities.mjs';
import queries from '../../global/jsonata/queries.mjs';
import driver from '../../global/jsonata/driver.mjs';
import yaml from 'yaml';
import {loadFromAssets} from '../storage/cache.mjs';

class BackendEntities extends BaseEntities {

// Подключает мастер-схему для подсказок и валидации метамодели
getMasterSchema() {
return yaml.parse(loadFromAssets('master-schema.yaml'));
}
async queryEntitiesJSONSchema(manifest) {
const query = queries.makeQuery(queries.QUERIES[queries.IDS.JSONSCEMA_ENTITIES]);
let result = null;
try {
result = await driver
.expression(query)
.evaluate(manifest);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
throw e;
}
return result;
}
}


// Регистрирует кастомные сущности
export default function(manifest) {
const entities = new BackendEntities();
entities.registerEntities(entities);
entities.setManifest(manifest);
void entities.reloadSchema();
}
16 changes: 11 additions & 5 deletions src/backend/storage/cache.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ const LOG_TAG = 'manifest-cache';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Подключает базовую метамодель
function loadBaseMatamodel() {
const source = path.resolve(__dirname, '../../assets/base.yaml');

export function loadFromAssets(filename) {
const source = path.resolve(__dirname, '../../assets/' + filename);

logger.log(`Import base metamodel from [${source}].`, LOG_TAG);
const content = fs.readFileSync(source, { encoding: 'utf8', flag: 'r' });
return yaml.parse(content);
return fs.readFileSync(source, { encoding: 'utf8', flag: 'r' });


}

// Подключает базовую метамодель
function loadBaseMatamodel() {
return yaml.parse(loadFromAssets('base.yaml'));
}

// Кэш в памяти
Expand Down
9 changes: 6 additions & 3 deletions src/backend/storage/manager.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cache from './cache.mjs';
import md5 from 'md5';
import events from '../helpers/events.mjs';
import validators from '../helpers/validators.mjs';
import entities from '../entities/entities.mjs';

const LOG_TAG = 'storage-manager';

Expand Down Expand Up @@ -31,10 +32,12 @@ export default {
await manifestParser.clean();
await manifestParser.startLoad();
await manifestParser.import('file:///$root$');
await manifestParser.checkAwaitedPackages();
await manifestParser.checkLoaded();
await manifestParser.checkAwaitedPackages();
await manifestParser.checkLoaded();
await manifestParser.stopLoad();


entities(manifestParser.manifest);

logger.log('Full reload is done', LOG_TAG);
const result = {
manifest: manifestParser.manifest, // Сформированный манифест
Expand Down
193 changes: 41 additions & 152 deletions src/frontend/entities/entities.js
Original file line number Diff line number Diff line change
@@ -1,166 +1,59 @@
// Обрабатывает кастомные сущности
import query from '@front/manifest/query';
import crc16 from '@global/helpers/crc16';
import {BaseEntities} from '@global/entities/entities.mjs';
import env from '@front/helpers/env';
import crc16 from '@global/helpers/crc16';
import { DocTypes } from '@front/components/Docs/enums/doc-types.enum';
import query from '@front/manifest/query';
import yaml from 'yaml';
import masterSchema from '!!raw-loader!@assets/master-schema.yaml';
import { DocTypes } from '@front/components/Docs/enums/doc-types.enum';

let appliedSchema = null;
let lastKnownManifest = null;
let appliedSchemaCRC = null;

async function loadSchema() {

//todo Здесь нужно рефачить, чтобы запросы в бэк ходили
const queryResult = await query
.expression(query.entitiesJSONSchema())
.evaluate(lastKnownManifest || {});

const master = getMasterSchema();

const $defs = {
...master.$defs,
...queryResult.$defs,
...makeDataSetSchema(lastKnownManifest)
};

const $rels = makeSubjectsRelationsSchema(lastKnownManifest || {});
class FrontEntities extends BaseEntities {

// Превращаем схему в строку для передачи в плагин
const schema = {
...queryResult,
properties: {
...master.$entities,
...queryResult.properties
},
$defs: {
...$defs,
...makeDefsEnum($defs, $rels),
...makeDocTypesEnum()
},
// Добавляем схемы связей с субъектами сущностей
$rels
};

// eslint-disable-next-line no-console
console.log('schema created');

return schema;
}

async function reloadSchema() {
if (appliedSchema !== null && lastKnownManifest !== null) {
appliedSchema = await loadSchema();
// Подключает мастер-схему для подсказок и валидации метамодели
getMasterSchema() {
return yaml.parse(masterSchema);
}
}

export async function getSchema() {
if (appliedSchema === null && lastKnownManifest !== null) {
appliedSchema = await loadSchema();
async queryEntitiesJSONSchema(manifest) {
return query
.expression(query.entitiesJSONSchema())
.evaluate(manifest || {});
}
return appliedSchema;
}

// Подключает мастер-схему для подсказок и валидации метамодели
function getMasterSchema() {
return yaml.parse(masterSchema);
}

// Генерируем схемы связей
function makeSubjectsRelationsSchema(manifest) {
try {
const rels = {};
for (const entityId in manifest.entities || {}) {
const objects = manifest.entities[entityId].objects;
// Если сущность не публикует субъекты, то игнорируем ее
if (!objects) continue;
// Генерируем схемы связей с объектами
for (const subjectId in objects) {
const route = (objects[subjectId].route || '/').split('/');
let location = manifest[entityId] || {};
for (let i = 1; i < route.length; i++) {
const pice = route[i];
pice?.length && (location = location[route[i]] || {});
}
const objId = `${entityId}.${subjectId}`;
rels[objId] = {
type: 'string',
minLength: 1,
enum: Object.keys(location)
};
}
}
return rels;
} catch (e) {
// eslint-disable-next-line no-console
console.error('Error of building of relations enumeration!');
// eslint-disable-next-line no-console
console.error(e);
return {};
}
}

// Генерирует схему DataSet
function makeDataSetSchema(manifest) {
return {
$dataset: {
type: 'string',
enum: Object.keys(manifest.datasets || {})
}
};
}


// Генерирует перечисления для подсказок
function makeDefsEnum($defs, $rels) {
let items = [];
try {
items = Object.keys($defs).map((item) => `#/$defs/${item}`);
Object.keys($rels).map((item) => items.push(`#/$rels/${item}`));
} catch (e) {
// eslint-disable-next-line no-console
console.error('Error of building of definitions enumeration!');
// eslint-disable-next-line no-console
console.error(e);

}
return {
'$defs': {
type: 'string',
enum: items
}
};
}

// Генерирует список доступных типов документов
function makeDocTypesEnum() {
const result = [];
try {
for (const id in DocTypes) {
result.push(DocTypes[id]);
}
window?.DocHub?.documents?.fetch().map((item) => result.push(item));
} catch (e) {
// eslint-disable-next-line no-console
console.error('Error of building of document types enumeration!');
// eslint-disable-next-line no-console
console.error(e);
}
return {
'$doc-types': {
type: 'string',
enum: result
}
};
// Генерирует список доступных типов документов
makeDocTypesEnum() {
const result = [];
try {
for (const id in DocTypes) {
result.push(DocTypes[id]);
}
window?.DocHub?.documents?.fetch().map((item) => result.push(item));
} catch (e) {
// eslint-disable-next-line no-console
console.error('Error of building of document types enumeration!');
// eslint-disable-next-line no-console
console.error(e);
}
return {
'$doc-types': {
type: 'string',
enum: result
}
};
}
}

// Регистрирует кастомные сущности
export default function(manifest) {
lastKnownManifest = manifest;
const entities = new FrontEntities();
entities.registerEntities(entities);
entities.setManifest(manifest);

if (env.isPlugin()) {
loadSchema().then((schema) => {
entities.loadSchema().then((schema) => {

entities.updateSchema(schema);

const schemaString = JSON.stringify(schema);
// Считаем контрольную сумму
Expand All @@ -170,14 +63,10 @@ export default function(manifest) {
window.$PAPI.applyEntitiesSchema(schemaString);
appliedSchemaCRC = crc;
}
// Отправляем в плагин только если схема изменилась
if (schema !== appliedSchema) {
window.$PAPI.applyEntitiesSchema(JSON.stringify(schema));
appliedSchema = schema;
}

// eslint-disable-next-line no-console
}).catch((e) => console.error(e));
} else {
void reloadSchema();
void entities.reloadSchema();
}
}
Loading

0 comments on commit c1229d3

Please sign in to comment.