@fibery/ai-utils
Version:
Utilities for Fibery AI
392 lines • 15.3 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAllTypesString = exports.getDomainTypesString = exports.getDomainTypes = exports.getWorkspaceStructureString = exports.getSchemaString = exports.processSchema = void 0;
const _ = __importStar(require("lodash"));
const formulas_1 = require("@fibery/formulas");
const templates_1 = require("./templates");
const getFieldName = (field) => {
return `${field.title} [${field.name}]`;
};
const getReferenceField = ({ field, schema }) => {
if (field.typeObject.isPrimitive) {
return null;
}
const relationType = schema.typeObjectsByName[field.type];
if (!relationType) {
return null;
}
return _.find(relationType.fieldObjects, (r) => r.relation === field.relation && r !== field) || null;
};
const getManyToMany = ({ field, schema }) => {
if (!field.isCollection) {
return null;
}
if (!field.relation) {
return null;
}
const refField = getReferenceField({ field, schema });
if (!refField) {
return null;
}
if (!refField.isCollection) {
return null;
}
return refField;
};
const getEnumValues = async ({ fetchEnums, type, enums, defaultValue = null, includeEnumId = false, }) => {
if (enums[type.name]) {
return enums[type.name];
}
if (!fetchEnums) {
throw new Error(`Please, pass fetchEnums function for dynamic schema exploration`);
}
const records = await fetchEnums(type);
const enumArray = _.sortBy(records, `rank`).map((v) => includeEnumId ? `"${v.name}" (${v.id})` : v.name);
enumArray.getDefaultValue = () => null;
if (defaultValue) {
const value = _.find(records, { id: defaultValue[`fibery/id`] });
enumArray.getDefaultValue = () => (value ? value.name : null);
}
enumArray.getFinalStateNames = () => {
return _.filter(records, { isFinal: true });
};
enums[type.name] = enumArray;
return enumArray;
};
const getFormulaText = (options) => {
const { type, field } = options;
if (!field.isFormula) {
return '';
}
const formulaType = field.isLookup ? 'Formula (Lookup)' : 'Formula';
const formula = field.formula;
const formulaText = (0, formulas_1.printFormulaExpression)({
expression: formula?.expression || {},
params: formula?.params || {},
implicitRootTypeObject: type,
});
return `${formulaType}: \`${formulaText}\``;
};
const processType = async ({ fetchEnums, type, schema, typeObjects, includeEnumId, onAddField, isIncludedRelation = () => true, enums, }) => {
const typeSchema = {
color: _.toUpper(type.color),
fields: {},
description: !type.description || _.isEmpty(type.description) ? `no description` : type.description,
};
const typeName = type.name;
const externalTypes = {};
const fieldObjects = type.fieldObjects;
for (const field of fieldObjects) {
if (field.isHidden) {
continue;
}
const typeOfField = schema.typeObjectsByName[field.type];
const manyToMany = getManyToMany({ field, schema });
let fieldTypeName = typeOfField.isPrimitive ? typeOfField.nameParts.name : typeOfField.name;
let refField = getReferenceField({ field, schema });
let fieldType = fieldTypeName;
if (typeOfField.name === `fibery/rank`) {
fieldType = `int`;
}
if (field.isReadOnly) {
fieldType = `${fieldType} // read-only`;
}
if (field.isFormula) {
fieldType = `${fieldType}; ${getFormulaText({ type, field })}`;
}
if (field.isTitle) {
fieldType = `${fieldType} // UI Title`;
}
let fieldName = getFieldName(field);
if (type.isEnum && field.isTitle) {
const values = await getEnumValues({ fetchEnums, type, enums, includeEnumId });
const options = values.map((v) => (includeEnumId ? v : `"${v}"`));
fieldType = `${fieldType} // available values: ${options.join(`, `)}`;
}
if (type.nameParts.namespace === `workflow` && field.title === `Type`) {
fieldType = `${fieldType} // available values: "Not started", "Started", "Finished"`;
}
if (refField) {
fieldType = {
relation: manyToMany ? `many-to-many` : `many-to-one`,
type: field.isCollection ? `Collection(${fieldTypeName})` : fieldTypeName,
field: getFieldName(refField),
};
if (field.isFormula) {
const formulaText = getFormulaText({ type, field });
_.extend(fieldType, { formulaText });
}
if (typeOfField.isEnum) {
const values = await getEnumValues({
fetchEnums,
type: typeOfField,
enums,
defaultValue: field.defaultValue,
includeEnumId,
});
const defaultValue = values.getDefaultValue();
_.extend(fieldType, { values, defaultValue });
}
if (!isIncludedRelation({ field, fieldTypeName, typeOfField })) {
continue;
}
if (!_.find(typeObjects, { name: typeOfField.name })) {
if (!externalTypes[fieldTypeName]) {
externalTypes[fieldTypeName] = typeOfField;
}
}
if (field.isDependencyStart) {
fieldType.type = fieldType.type += ' // Dependency Start';
}
else if (field.isDependency) {
fieldType.type = fieldType.type += ' // Dependency';
}
}
const overrideNameType = onAddField({ type, field, typeName, fieldType, fieldName }) || {};
if (overrideNameType.name) {
fieldName = overrideNameType.name;
}
if (overrideNameType.type) {
fieldType = overrideNameType.type;
}
typeSchema.fields[fieldName] = fieldType;
}
return { typeSchema, typeName, externalTypes, enums };
};
const createTypeSchema = async ({ fetchEnums, typeObjects, schema, includeEnumId, onAddField, enums, }) => {
const appSchema = {};
const external = {};
for (const type of typeObjects) {
const { typeSchema, typeName, externalTypes } = await processType({
fetchEnums,
type,
schema,
typeObjects,
includeEnumId,
onAddField,
enums,
});
appSchema[typeName] = typeSchema;
_.extend(external, externalTypes);
}
return { appSchema, external };
};
const processLevelOfExternals = async ({ external, appSchema, fetchEnums, typeObjects, schema, includeEnumId, onAddField, enums, }) => {
const nextLevelOfExternals = {};
for (const key of _.keys(external)) {
if (appSchema[key]) {
continue;
}
const type = external[key];
if (key === `fibery/field` || key === `fibery/type`) {
continue;
}
const { typeSchema, externalTypes } = await processType({
fetchEnums,
type,
typeObjects,
schema,
includeEnumId,
onAddField,
isIncludedRelation: ({ fieldTypeName, field }) => {
return _.toLower(fieldTypeName).indexOf(`fibery`) === 0 || !field.isCollection;
},
enums,
});
appSchema[key] = typeSchema;
_.extend(nextLevelOfExternals, externalTypes);
}
return nextLevelOfExternals;
};
const createFromTypeObjectsWithExternals = async ({ fetchEnums, compact = false, typeObjects, schema, includeEnumId, onAddField, enums = {}, }) => {
const { appSchema, external } = await createTypeSchema({
fetchEnums,
typeObjects,
schema,
includeEnumId,
onAddField,
enums,
});
let nextLevelOfExternals = external;
let countOfLevels = compact ? 0 : 1;
for (let i = 0; i < countOfLevels; i++) {
nextLevelOfExternals = await processLevelOfExternals({
external: nextLevelOfExternals,
appSchema,
fetchEnums,
typeObjects,
schema,
includeEnumId,
onAddField,
enums,
});
}
return { appSchema, enums };
};
const processSchema = async ({ fetchEnums, typeObjects, compact = false, fiberySchema, overrideFieldNameType = () => ({}), includeEnumId, }) => {
const dataTypeMap = {};
const { appSchema: spaceSchema, enums } = await createFromTypeObjectsWithExternals({
fetchEnums,
typeObjects,
compact,
schema: fiberySchema,
includeEnumId,
onAddField: ({ type, field, typeName, fieldType, fieldName }) => {
if (!dataTypeMap.hasOwnProperty(typeName)) {
dataTypeMap[typeName] = {
type,
fields: {},
};
}
dataTypeMap[typeName].fields[fieldName] = {
type,
fieldType,
field,
};
return overrideFieldNameType({
type,
field,
typeName,
fieldType,
fieldName,
});
},
});
return { spaceSchema, dataTypeMap, enums };
};
exports.processSchema = processSchema;
const processSpaces = ({ schema, apps }) => {
const spaces = {};
for (let app of apps) {
spaces[app.name] = [];
}
for (let type of schema.typeObjects) {
if (!type.isDomain && !_.includes([`fibery/file`, `comments/comment`], type.name)) {
continue;
}
const spaceName = `${type.nameParts.namespace}`;
if (!spaces[spaceName]) {
spaces[spaceName] = [];
}
spaces[spaceName].push({ name: `${type.title}`, type });
}
return { spaces };
};
const renderSchemaToString = async ({ schema, nonExistentTypes, dataTypeMap, compact = false, template = `workspace-schema`, }) => {
const app = { schema };
const getField = (name, type) => {
if (_.isObject(type)) {
const isManyToMany = type.relation === `many-to-many`;
const refType = type.type;
const formulaText = type.formulaText ? `${type.formulaText}` : '';
const defaultValue = type.defaultValue ? `${type.defaultValue}` : null;
return { name, type: refType, isManyToMany, values: type.values || null, formulaText, defaultValue };
}
return { name, type };
};
const templateData = (0, templates_1.getDataToRenderTemplate)({ app, getField });
return await (0, templates_1.renderToString)({
data: { ...templateData, compact, nonExistentTypes, dataTypeMap },
template,
});
};
const getSchemaString = async ({ fetchEnums, typeObjects, schema, nonExistentTypes = [], compact = false, overrideFieldNameType, includeEnumId, }) => {
const { spaceSchema, dataTypeMap, enums } = await (0, exports.processSchema)({
fetchEnums,
typeObjects,
fiberySchema: schema,
overrideFieldNameType,
compact,
includeEnumId,
});
const schemaString = await renderSchemaToString({
schema: spaceSchema,
compact,
dataTypeMap,
nonExistentTypes,
});
return { spaceSchema, dataTypeMap, schemaString, typeObjects, schema, enums };
};
exports.getSchemaString = getSchemaString;
const getWorkspaceStructureString = async ({ schema, apps }) => {
const { spaces } = processSpaces({ schema, apps });
let data = _.keys(spaces).map((space) => ({ name: space, databases: spaces[space] }));
const schemaString = await (0, templates_1.renderToString)({ data: { spaces: data }, template: `databases-names` });
return { spaces, schemaString, schema };
};
exports.getWorkspaceStructureString = getWorkspaceStructureString;
const getDomainTypes = ({ schema, apps }) => {
const { spaces } = processSpaces({ schema, apps });
const typeObjects = [];
for (let types of _.values(spaces)) {
types.forEach((db) => typeObjects.push(db.type));
}
return { schema, typeObjects };
};
exports.getDomainTypes = getDomainTypes;
const getDomainTypesString = async ({ fetchEnums, schema, apps, detection, includeEnumId, buildSchema = exports.getSchemaString, }) => {
const { typeObjects } = (0, exports.getDomainTypes)({ schema, apps });
let detectedTypes = typeObjects;
if (detection && !_.isEmpty(detection)) {
detectedTypes = [];
for (const db of detection) {
const type = _.find(typeObjects, { name: db });
if (!type) {
throw new Error(`${db} doesn't exist`);
}
detectedTypes.push(type);
}
}
return await buildSchema({ fetchEnums, typeObjects: detectedTypes, schema, includeEnumId });
};
exports.getDomainTypesString = getDomainTypesString;
const getAllTypesString = async ({ fetchEnums, schema, detection, includeEnumId, buildSchema = exports.getSchemaString, }) => {
// builds schema for given detection using ALL fibery types instead of only user-defined types
let detectedTypes = schema.typeObjects;
if (detection && !_.isEmpty(detection)) {
detectedTypes = [];
for (const db of detection) {
const type = _.find(schema.typeObjects, { name: db });
if (!type) {
throw new Error(`${db} doesn't exist`);
}
detectedTypes.push(type);
}
}
return await buildSchema({ fetchEnums, typeObjects: detectedTypes, schema, includeEnumId });
};
exports.getAllTypesString = getAllTypesString;
//# sourceMappingURL=schema.js.map