@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
158 lines (140 loc) • 5.22 kB
JavaScript
const cds = require('../../cds')
const fs = require('fs').promises
const {existsSync} = require('fs')
const path = require('path')
const HDI_CONTAINER_TYPES = ['com.sap.xs.hdi-container']
const UTF_8 = 'utf-8'
const MTA_YAML = 'mta.yaml'
const DEBUG = cds.debug('cli');
async function getHanaDbModuleDescriptor(projectPath, moduleName) {
// mta might be null if mta.yaml does not exist
const mta = await _getMta(projectPath)
const projectInfo = await _getProjectInfo(projectPath, mta)
const hdiService = _findHdiResource(mta, moduleName)
const appName = _getApplicationName(mta, moduleName, 'hdb')
return {
project: projectInfo,
appName: appName ? appName : `${projectInfo.name}-${moduleName}-deployer`,
hdiServiceName: hdiService ? hdiService.name : `${projectInfo.name}-${moduleName}`,
hdiService: hdiService
}
}
async function _getProjectInfo(projectPath, mta) {
const details = {
}
// 1. use mta data
if (mta) {
details.id = mta.ID
details.description = mta.description
details.version = mta.version
if (mta.ID) {
details.name = mta.ID.replace(/\./g, '-')
}
}
// 2. use package.json data
const packageJsonPath = path.join(projectPath, 'package.json')
if (existsSync(packageJsonPath)) {
try {
const packageJson = JSON.parse((await fs.readFile(packageJsonPath, 'utf-8')).toString())
if (!details.description && packageJson.description) {
details.description = packageJson.description
}
if (!details.version && packageJson.version) {
details.version = packageJson.version
}
if (packageJson.name) {
let segments = packageJson.name.trim().split('/')
// scope as namespace
if (segments[0].startsWith('@')) {
segments[0] = segments[0].replace('@', '')
}
segments = segments.map(segment => segment.startsWith('@') ? encodeURIComponent(segment.replace('@', '')) : encodeURIComponent(segment))
if (!details.name) {
details.name = segments[segments.length - 1]
}
if (!details.id) {
details.id = segments.join('.')
}
if (!details.description) {
details.description = segments[segments.length - 1]
}
}
} catch (e) {
console.error(`Failed to load ${packageJsonPath} - skip application data`, e)
}
}
// 3. use project name and static default values
const projectName = path.basename(projectPath)
if (!details.name) {
details.name = projectName
}
if (!details.description) {
details.description = projectName
}
if (!details.id) {
details.id = projectName
}
if (!details.version) {
details.version = '1.0.0'
}
return details
}
async function _getMta(projectPath) {
// yaml.parse doesn't like null
const mtaFilePath = path.join(projectPath, MTA_YAML)
const existsMtaYaml = existsSync(mtaFilePath)
if (!existsMtaYaml) {
DEBUG?.('mta.yaml not existing')
return null
}
const yamlStr = await fs.readFile(mtaFilePath, UTF_8)
// yaml returns null if string couldn't be parsed, e.g. empty string
return cds.parse.yaml(yamlStr)
}
function _getApplicationName(mta, moduleName, moduleType) {
const module = _findModule(mta, moduleName, moduleType)
if (module) {
const appName = module.parameters && module.parameters['app-name']
return appName ? appName : module.name
}
return null
}
function _findModules(mta, moduleType) {
let modules = []
if (mta && Array.isArray(mta.modules)) {
modules = mta.modules.filter(module => module.type === moduleType)
}
return modules
}
function _findModule(mta, moduleName, moduleType) {
const modules = _findModules(mta, moduleType)
if (modules.length === 1) {
return modules[0]
} else if (modules.length > 1) {
return modules.find(module => typeof module.path === 'string' && module.path.includes(moduleName))
}
return null
}
function _findHdiResource(mta, moduleName) {
if (mta && Array.isArray(mta.resources)) {
const hdiResources = mta.resources.filter(resource => HDI_CONTAINER_TYPES.includes(resource.type))
if (hdiResources.length > 0) {
if (Array.isArray(mta.modules)) {
const module = _findModule(mta, moduleName, 'hdb')
if (module && Array.isArray(module.requires)) {
return hdiResources.find(hdiResource =>
module.requires.find(req =>
hdiResource.name === req.name
)
)
}
}
console.warn(`No matching hdi resource found for ${moduleName}. Using ${hdiResources[0].name}.`)
return hdiResources[0]
}
}
return null
}
module.exports = {
getHanaDbModuleDescriptor
}