UNPKG

@sap/cds-dk

Version:

Command line client and development toolkit for the SAP Cloud Application Programming Model

94 lines (82 loc) 4.15 kB
const path = require('path') const cds = require('../../cds') const { DEFAULT_CSN_FILE_NAME, OUTPUT_MODE, OUTPUT_MODE_RESULT } = require('../constants') const InternalBuildPlugin = require('./internalBuildPlugin') const { getI18nDefaultFolder, filterFeaturePaths } = require('../util') class FeatureToggleBuildPlugin extends InternalBuildPlugin { init() { if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) { this._result = { dest: this.task.dest, edmx: new Map(), languages: new Set(), services: new Set() } } } async compileAll(csn, destBase, destFts) { const sources = filterFeaturePaths(csn, this.task.options.model || this.task.src) const dictionary = { base: null, features: null } if (sources.features) { // create base model as the given CSN is containing all features dictionary.base = await cds.load(sources.base, this.options()) } else { // CSN already represents the base model as no features exist dictionary.base = csn } // preserve @location as @source properties const csnStr = await this.compileToJson(dictionary.base, path.join(destBase, DEFAULT_CSN_FILE_NAME)) const csnModel = JSON.parse(csnStr) csnModel.meta = csn.meta if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) { this._result.csn = csnModel } if (sources.features) { dictionary.features = await this._compileFeatures(sources.features, destBase, destFts, dictionary.base) } return { dictionary, sources } } async collectAllLanguageBundles(dictionary, paths, destBase, destFts) { const i18nFolder = getI18nDefaultFolder() const ftsName = path.dirname(cds.env.features.folders || 'fts/*') // create language bundle for base model const i18n = await this.collectLanguageBundles(dictionary.base, path.join(destBase, i18nFolder)) if (i18n && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) { this._result.languageBundles = i18n.bundles } if (dictionary.features) { // create language bundles for all features for (const ftName in dictionary.features) { // attach the sources information for i18n location reference dictionary.features[ftName]['$sources'] = paths.features[ftName] await this.collectLanguageBundles(dictionary.features[ftName], path.join(destFts, ftsName, ftName, i18nFolder)) } } } async _compileFeatures(ftsPaths, destBase, destFts, baseCsn) { if (!ftsPaths) { return } const features = {} const options = { ...this.options(), flavor: 'parsed' } const ftsName = path.dirname(cds.env.features.folders || 'fts/*') // create feature models for (const ftName in ftsPaths) { const ftCsn = await cds.load(ftsPaths[ftName], options) const ftPath = path.join(destFts, ftsName, ftName) // replace require paths by base model path to ensure precedence of feature annotations // see https://pages.github.tools.sap/cap/docs/cds/compiler-messages#anno-duplicate-unrelated-layer ftCsn.requires = [path.join(path.relative(ftPath, destBase), DEFAULT_CSN_FILE_NAME).replace(/\\/g, '/')] await this.compileToJson(ftCsn, path.join(ftPath, DEFAULT_CSN_FILE_NAME)) this._validateFeature(ftCsn, baseCsn) features[ftName] = ftCsn } return features } _validateFeature(ftCsn, baseCsn) { // features must not have other dependencies than base model dependencies - cross feature dependencies are not supported // assuming only core compiler options are relevant for validation scenario cds.compiler.compileSources({ [ftCsn.requires[0]]: baseCsn, 'feature.csn': ftCsn }, { ...super.options(), ...cds.env.cdsc ?? {} }) } } module.exports = FeatureToggleBuildPlugin