UNPKG

@sap/cds-mtxs

Version:

SAP Cloud Application Programming Model - Multitenancy library

95 lines (86 loc) 4.09 kB
const cds = require('@sap/cds') module.exports = (srv) => { // mainly normalizing the input srv.before(['UPDATE', 'UPSERT'], 'Extensions', req => { // must be synchronous to be handled first const { csn: extension, i18n: bundles, csvs: csvData } = req.data // Validation of extension if (!extension) throw new cds.error({ message: 'Property "extension" is missing', code: 400 }) if (Array.isArray(extension)) { if (!extension.length) throw new cds.error({ message: 'Property "extension" is empty', code: 400 }) } else { const length = typeof extension === 'string' ? extension.length : Object.keys(extension).length if (!length) throw new cds.error({ message: 'Property "extension" is malformed', code: 400 }) } // Merge extension to one extension csn let extCsn for (let ext of extension) { if (typeof ext === 'string') { if (!ext.length) throw new cds.error({ message: 'Missing extension', code: 400 }) if (_isCSN(ext)) extCsn = _mergeCSN(JSON.parse(ext), extCsn) else try { extCsn = _mergeCSN(cds.parse.cdl(ext), extCsn) } catch (e) { if (e.code === 'ERR_CDS_COMPILATION_FAILURE') throw new cds.error({ message: e.message, code: 422 }) else throw e } } else { if (!Object.keys(ext).length) throw new cds.error({ message: 'Missing extension', code: 400 }) extCsn = _mergeCSN(ext, extCsn) } } if (extCsn.requires) delete extCsn.requires // merge i18n and csvs let csvs = {} const i18nJson = _mergeBundles(bundles) // convert to i18n.json if (csvData) csvs = _convertData(csvData) // REVISIT - overwrite existing parameters from API? req.data.csvs = csvs req.data.i18n = i18nJson req.data.csn = extCsn }) const _isCSN = str => str.substring(0, 1) === '{' const _mergeCSN = function (extension, merged) { if (!merged) merged = { extensions: [], definitions: {} } if (extension.definitions) Object.assign(merged.definitions, extension.definitions) if (extension.extensions) merged.extensions.push(...extension.extensions) return merged } const _mergeBundles = function (bundles) { if (!Array.isArray(bundles)) return bundles ?? {} let mergedI18nJson = {} let fromJson = false bundles.forEach(file => { const key = file.name.match(/i18n_*(.*)\.properties/), lang = key?.[1] if (key) { if (fromJson) throw new cds.error({ message: `Mixed i18n file types not supported: i18n.json and ${file.name}`, code: 422 }) mergedI18nJson[lang] = _toJson(file.content) } else if (file.name === 'i18n.json') { if (Object.entries(mergedI18nJson).length) throw new cds.error({ message: `Mixed i18n file types not supported: i18n.json and .properties`, code: 422 }) try { mergedI18nJson = JSON.parse(file.content) fromJson = true } catch (e) { throw new cds.error({ message: `Invalid JSON content in i18n.json: ${e.message}`, code: 422 }) } } }) return mergedI18nJson } const _convertData = function (resources) { const csvs = {} if (resources && Array.isArray(resources) && resources.length) { resources.forEach(file => { if (file.name.endsWith('.csv')) { csvs[file.name] = file.content } }) } return csvs } const _toJson = function (content) { const json = {}, splitted = content.split('\n') splitted.forEach(s => { const parts = s.split('=').map(s => s.trim()), [key, val] = parts if (parts.length === 2) json[key] = val }) return json } }