/**
* Create service scripts containing entity definition for code insight in WebStorm or other IDE work well.
*
* Usage from a command line:
ubcli createCodeInsightHelper -u admin -p admin -m UBS -cfg myConfig.json
* Usage from a code:
const createCodeInsightHelper = require('@unitybase/ubcli/createCodeInsightHelper')
var options = {
host: "http://localhost:888",
user: "admin",
pwd: "admin",
model: 'UBS'
}
createCodeInsightHelper(options)
* @author pavel.mash
* @module createCodeInsightHelper
* @memberOf module:@unitybase/ubcli
*/
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
const mustache = require('mustache')
const options = require('@unitybase/base').options
const argv = require('@unitybase/base').argv
module.exports = function createCodeInsightHelper (cfg) {
if (!cfg) {
const opts = options.describe('createCodeInsightHelper',
'create service scripts containing entity definition for code insight in WebStorm or other IDE work well',
'ubcli'
).add(
argv.establishConnectionFromCmdLineAttributes._cmdLineParams
).add({
short: 'm',
long: 'model',
param: 'model',
defaultValue: '*',
help: 'Model name to generate helpers for. If not specified then all domain models is used'
})
cfg = opts.parseVerbose({}, true)
if (!cfg) return
}
const config = argv.getServerConfiguration()
const domain = config.application.domain
let models = domain.models
if (!Array.isArray(models)) {
throw new Error('Domain.models configuration MUST be an array on object')
}
const filterByModel = cfg.model
if (filterByModel) {
console.log('Will generate a helpers for model', filterByModel)
models = _.filter(models, function (modelCfg) {
return modelCfg.name === filterByModel
})
}
models = _.filter(models, function (modelCfg) {
return modelCfg.path !== '_public_only_'
})
/**
* Convert named collection - {name1: {}, name2: {}} to array -> [{name: name1, ...}, ...]
* Will mutate original!
* @param {object} namedCollection
*/
function namedCollection2Array (namedCollection) {
const result = []
let item
_.forEach(namedCollection, function (value, key) {
item = { name: key }
item = _.defaults(item, value)
result.push(item)
})
return result
}
const ub2JS = (dataType, associatedEntity) => {
const ubTypes = {
Unknown: () => '*',
String: () => 'string',
Int: () => 'number',
BigInt: () => 'number',
Float: () => 'number',
Currency: () => 'number',
Boolean: () => 'boolean',
DateTime: () => 'Date',
Text: () => 'string',
ID: () => 'number',
Entity: associatedEntity => `number|${_.camelCase(associatedEntity)}Attrs`,
Document: () => 'string',
Many: associatedEntity => `number|${_.camelCase(associatedEntity)}Attrs`,
TimeLog: () => 'number',
Enum: () => 'string|ubmEnumAttrs',
BLOB: () => 'ArrayBuffer',
Date: () => 'Date'
}
return (typeof ubTypes[dataType] === 'function') ? ubTypes[dataType](associatedEntity) : '*'
}
const tpl = fs.readFileSync(path.join(__dirname, 'templates', 'codeInsightHelper.mustache'), 'utf8')
function processEntities (entities, folderName, modelName) {
let res, resFileName
const modulePackage = require(path.join(folderName, 'package.json'))
if (entities.length) {
res = mustache.render(tpl, {
module: modulePackage,
entities: entities,
getJSType: function () {
return '{' + (ub2JS(this.dataType, this.associatedEntity) || '*') + '}'
},
getDefaultValue: function () {
var res = ''
if (this.allowNull) {
res = 'null'
} else {
switch (ub2JS[this.dataType]) {
case 'String':
res = "''"
break
case 'Number':
res = '0'
break
case 'Date':
res = 'new Date()'
break
default:
res = 'undefined'
}
}
return res
},
getAccessLevel: function () {
return (this.defaultView === false) ? 'not viewable by default' : undefined
}
})
if (res) {
resFileName = path.join(folderName, '_' + modelName + '_entities.js')
console.log('Generate %s', resFileName)
fs.writeFileSync(resFileName, res)
}
}
}
// function processFolder (folderName, modelName) {
// let files = fs.readdirSync(folderName)
// let entities = []
//
// function validateAndParse (fileName) {
// let arr = /^([^_].+)\.meta$/.exec(fileName)
// let meta
//
// if (arr && arr[1]) {
// try {
// meta = argv.safeParseJSONfile(path.join(folderName, fileName), true) // JSON.parse(content);
// if (!_.isArray(meta.attributes)) {
// // convert attributes to array of object
// meta.attributes = namedCollection2Array(meta.attributes)
// }
// entities.push({name: arr[1], meta: meta})
// } catch (e) {
// console.error('Invalid JSON file ' + folderName + '\\' + fileName + ' \n' + e.toString())
// }
// } else if (/^[^_].+\\$/.test(fileName)) { // this is folder
// let nameOfSubModel = modelName + '_' + fileName.split('\\')[0] // remove last \ from fileName
// processFolder(path.join(folderName, fileName), nameOfSubModel)
// }
// }
// files.forEach(validateAndParse)
// processEntities(entities, folderName, modelName)
// }
mustache.parse(tpl)
const session = argv.establishConnectionFromCmdLineAttributes(cfg)
const realDomain = session.connection.getDomainInfo()
let entities = []
models.forEach(function processModel (modelCfg) {
const currentPath = modelCfg.realPath
entities = []
_.forEach(realDomain.entities, function (entityDef, entityName) {
if (entityDef.modelName === modelCfg.name) {
entityDef.attributes = namedCollection2Array(entityDef.attributes)
entityDef.mixins = namedCollection2Array(entityDef.mixins)
let doc = entityDef.description ? entityDef.description : entityDef.caption
if (entityDef.documentation) doc += '.\n * ' + entityDef.documentation
entities.push({
name: entityName,
camelName: _.camelCase(entityName),
description: doc,
meta: entityDef
})
}
})
processEntities(entities, currentPath, modelCfg.name)
})
}
module.exports.shortDoc = `Create service scripts containing entity definition
\t\t\tfor code insight in WebStorm or other IDE work well`