UNPKG

@fibery/ai-utils

Version:

Utilities for Fibery AI

392 lines 15.3 kB
"use strict"; 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