@spartacus/schematics
Version:
Spartacus schematics
547 lines • 27.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.runExternalSpartacusLibrary = exports.addSchematicsTasks = exports.createSpartacusFeatureOptionsForLibrary = exports.configureB2bFeatures = exports.dependencyExists = exports.addPackageJsonDependenciesForLibrary = exports.addPackageJsonDependencies = exports.installPackageJsonDependencies = exports.createNodePackageInstallationTask = exports.addLibraryStyles = exports.checkAppStructure = exports.addLibraryFeature = exports.getPackageBySubFeature = exports.prepareCliPackageAndSubFeature = exports.shouldAddFeature = exports.packageSubFeaturesMapping = void 0;
const strings_1 = require("@angular-devkit/core/src/utils/strings");
const schematics_1 = require("@angular-devkit/schematics");
const tasks_1 = require("@angular-devkit/schematics/tasks");
const dependencies_1 = require("@schematics/angular/utility/dependencies");
const ts_morph_1 = require("ts-morph");
const constants_1 = require("../constants");
const config_utils_1 = require("./config-utils");
const import_utils_1 = require("./import-utils");
const new_module_utils_1 = require("./new-module-utils");
const package_utils_1 = require("./package-utils");
const program_1 = require("./program");
const project_tsconfig_paths_1 = require("./project-tsconfig-paths");
const workspace_utils_1 = require("./workspace-utils");
exports.packageSubFeaturesMapping = {
[constants_1.SPARTACUS_ASM]: [constants_1.CLI_ASM_FEATURE],
[constants_1.SPARTACUS_CART]: [
constants_1.CLI_CART_IMPORT_EXPORT_FEATURE,
constants_1.CLI_CART_QUICK_ORDER_FEATURE,
constants_1.CLI_CART_SAVED_CART_FEATURE,
],
[constants_1.SPARTACUS_ORGANIZATION]: [
constants_1.CLI_ORGANIZATION_ADMINISTRATION_FEATURE,
constants_1.CLI_ORGANIZATION_ORDER_APPROVAL_FEATURE,
],
[constants_1.SPARTACUS_CDC]: [constants_1.CLI_CDC_FEATURE],
[constants_1.SPARTACUS_CDS]: [constants_1.CLI_CDS_FEATURE],
[constants_1.SPARTACUS_DIGITAL_PAYMENTS]: [constants_1.CLI_DIGITAL_PAYMENTS_FEATURE],
[constants_1.SPARTACUS_EPD_VISUALIZATION]: [constants_1.CLI_EPD_VISUALIZATION_FEATURE],
[constants_1.SPARTACUS_PRODUCT]: [
constants_1.CLI_PRODUCT_BULK_PRICING_FEATURE,
constants_1.CLI_PRODUCT_VARIANTS_FEATURE,
constants_1.CLI_PRODUCT_IMAGE_ZOOM_FEATURE,
],
[constants_1.SPARTACUS_PRODUCT_CONFIGURATOR]: [
constants_1.CLI_PRODUCT_CONFIGURATOR_VC_FEATURE,
constants_1.CLI_PRODUCT_CONFIGURATOR_TEXTFIELD_FEATURE,
constants_1.CLI_PRODUCT_CONFIGURATOR_CPQ_FEATURE,
],
[constants_1.SPARTACUS_QUALTRICS]: [constants_1.CLI_QUALTRICS_FEATURE],
[constants_1.SPARTACUS_SMARTEDIT]: [constants_1.CLI_SMARTEDIT_FEATURE],
[constants_1.SPARTACUS_STOREFINDER]: [constants_1.CLI_STOREFINDER_FEATURE],
[constants_1.SPARTACUS_TRACKING]: [
constants_1.CLI_TRACKING_PERSONALIZATION_FEATURE,
constants_1.CLI_TRACKING_TMS_GTM_FEATURE,
constants_1.CLI_TRACKING_TMS_AEP_FEATURE,
],
[constants_1.SPARTACUS_USER]: [constants_1.CLI_USER_ACCOUNT_FEATURE, constants_1.CLI_USER_PROFILE_FEATURE],
[constants_1.SPARTACUS_CHECKOUT]: [constants_1.CLI_CHECKOUT_FEATURE],
[constants_1.SPARTACUS_ORDER]: [constants_1.CLI_ORDER_FEATURE],
};
function shouldAddFeature(feature, features = []) {
return features.includes(feature);
}
exports.shouldAddFeature = shouldAddFeature;
function prepareCliPackageAndSubFeature(features) {
return features.reduce((cliFeatures, subFeature) => {
var _a;
const packageName = getPackageBySubFeature(subFeature);
const subFeatures = [...((_a = cliFeatures[packageName]) !== null && _a !== void 0 ? _a : []), subFeature];
return Object.assign(Object.assign({}, cliFeatures), { [packageName]: subFeatures });
}, {});
}
exports.prepareCliPackageAndSubFeature = prepareCliPackageAndSubFeature;
function getPackageBySubFeature(subFeature) {
for (const spartacusPackage in exports.packageSubFeaturesMapping) {
if (!exports.packageSubFeaturesMapping.hasOwnProperty(spartacusPackage)) {
continue;
}
const subFeatures = exports.packageSubFeaturesMapping[spartacusPackage];
if (subFeatures.includes(subFeature)) {
return spartacusPackage;
}
}
throw new schematics_1.SchematicsException(`The given '${subFeature}' doesn't contain a Spartacus package mapping.
Please check 'packageSubFeaturesMapping' in 'projects/schematics/src/shared/utils/lib-utils.ts'`);
}
exports.getPackageBySubFeature = getPackageBySubFeature;
function addLibraryFeature(options, config) {
return (tree, context) => {
const spartacusFeatureModuleExists = checkAppStructure(tree, options.project);
if (!spartacusFeatureModuleExists) {
context.logger.info('Scaffolding the new app structure...');
context.logger.warn('Please migrate manually the rest of your feature modules to the new app structure: https://sap.github.io/spartacus-docs/reference-app-structure/');
}
return schematics_1.chain([
spartacusFeatureModuleExists ? schematics_1.noop() : workspace_utils_1.scaffoldStructure(options),
handleFeature(options, config),
config.styles ? addLibraryStyles(config.styles, options) : schematics_1.noop(),
config.assets ? addLibraryAssets(config.assets, options) : schematics_1.noop(),
config.dependencyManagement
? installRequiredSpartacusFeatures(config.dependencyManagement, options)
: schematics_1.noop(),
]);
};
}
exports.addLibraryFeature = addLibraryFeature;
function checkAppStructure(tree, project) {
const { buildPaths } = project_tsconfig_paths_1.getProjectTsConfigPaths(tree, project);
if (!buildPaths.length) {
throw new schematics_1.SchematicsException(`Could not find any tsconfig file. Can't find ${constants_1.SPARTACUS_FEATURES_NG_MODULE}.`);
}
const basePath = process.cwd();
for (const tsconfigPath of buildPaths) {
if (spartacusFeatureModuleExists(tree, tsconfigPath, basePath)) {
return true;
}
}
return false;
}
exports.checkAppStructure = checkAppStructure;
function spartacusFeatureModuleExists(tree, tsconfigPath, basePath) {
const { appSourceFiles } = program_1.createProgram(tree, basePath, tsconfigPath);
for (const sourceFile of appSourceFiles) {
if (sourceFile
.getFilePath()
.includes(`${constants_1.SPARTACUS_FEATURES_MODULE}.module.ts`)) {
if (getSpartacusFeaturesModule(sourceFile)) {
return true;
}
}
}
return false;
}
function getSpartacusFeaturesModule(sourceFile) {
let spartacusFeaturesModule;
function visitor(node) {
if (ts_morph_1.Node.isCallExpression(node)) {
const expression = node.getExpression();
if (ts_morph_1.Node.isIdentifier(expression) &&
expression.getText() === 'NgModule' &&
import_utils_1.isImportedFrom(expression, constants_1.ANGULAR_CORE)) {
const classDeclaration = node.getFirstAncestorByKind(ts_morph_1.ts.SyntaxKind.ClassDeclaration);
if (classDeclaration) {
const identifier = classDeclaration.getNameNode();
if (identifier &&
identifier.getText() === constants_1.SPARTACUS_FEATURES_NG_MODULE) {
spartacusFeaturesModule = node;
}
}
}
}
node.forEachChild(visitor);
}
sourceFile.forEachChild(visitor);
return spartacusFeaturesModule;
}
function handleFeature(options, config) {
return (tree, _context) => {
const { buildPaths } = project_tsconfig_paths_1.getProjectTsConfigPaths(tree, options.project);
const basePath = process.cwd();
const rules = [];
for (const tsconfigPath of buildPaths) {
rules.push(new_module_utils_1.ensureModuleExists({
name: `${strings_1.dasherize(config.moduleName)}-feature`,
path: `app/spartacus/features/${config.folderName}`,
module: constants_1.SPARTACUS_FEATURES_MODULE,
project: options.project,
}));
rules.push(addRootModule(tsconfigPath, basePath, config));
rules.push(addFeatureModule(tsconfigPath, basePath, config, options));
rules.push(addFeatureTranslations(tsconfigPath, basePath, config));
rules.push(addCustomConfig(tsconfigPath, basePath, config));
}
return schematics_1.chain(rules);
};
}
function addRootModule(tsconfigPath, basePath, config) {
return (tree) => {
if (!config.rootModule) {
return tree;
}
const { appSourceFiles } = program_1.createProgram(tree, basePath, tsconfigPath);
const moduleFileName = createModuleFileName(config);
for (const sourceFile of appSourceFiles) {
if (sourceFile.getFilePath().endsWith('/' + moduleFileName)) {
new_module_utils_1.addModuleImport(sourceFile, {
import: {
moduleSpecifier: config.rootModule.importPath,
namedImports: [config.rootModule.name],
},
content: config.rootModule.content || config.rootModule.name,
});
program_1.saveAndFormat(sourceFile);
break;
}
}
return tree;
};
}
function addFeatureModule(tsconfigPath, basePath, config, options) {
return (tree) => {
const { appSourceFiles } = program_1.createProgram(tree, basePath, tsconfigPath);
const moduleFileName = createModuleFileName(config);
for (const sourceFile of appSourceFiles) {
if (sourceFile.getFilePath().endsWith('/' + moduleFileName)) {
if (options.lazy) {
let lazyLoadingChunkName = config.moduleName;
if (config.lazyLoadingChunk) {
const content = config.lazyLoadingChunk.namedImports[0];
lazyLoadingChunkName = `[${content}]`;
sourceFile.addImportDeclaration(config.lazyLoadingChunk);
}
new_module_utils_1.addModuleProvider(sourceFile, {
import: [
{
moduleSpecifier: constants_1.SPARTACUS_CORE,
namedImports: [constants_1.PROVIDE_CONFIG_FUNCTION, constants_1.CMS_CONFIG],
},
],
content: `${constants_1.PROVIDE_CONFIG_FUNCTION}(<${constants_1.CMS_CONFIG}>{
featureModules: {
${lazyLoadingChunkName}: {
module: () =>
import('${config.featureModule.importPath}').then((m) => m.${config.featureModule.name}),
},
}
})`,
});
}
else {
new_module_utils_1.addModuleImport(sourceFile, {
import: {
moduleSpecifier: config.featureModule.importPath,
namedImports: [config.featureModule.name],
},
content: config.featureModule.content || config.featureModule.name,
});
}
program_1.saveAndFormat(sourceFile);
break;
}
}
return tree;
};
}
function addFeatureTranslations(tsconfigPath, basePath, config) {
return (tree) => {
const { appSourceFiles } = program_1.createProgram(tree, basePath, tsconfigPath);
const moduleFileName = createModuleFileName(config);
for (const sourceFile of appSourceFiles) {
if (sourceFile.getFilePath().endsWith('/' + moduleFileName)) {
if (config.i18n) {
new_module_utils_1.addModuleProvider(sourceFile, {
import: [
{
moduleSpecifier: constants_1.SPARTACUS_CORE,
namedImports: [constants_1.PROVIDE_CONFIG_FUNCTION, constants_1.I18N_CONFIG],
},
{
moduleSpecifier: config.i18n.importPath,
namedImports: [config.i18n.chunks, config.i18n.resources],
},
],
content: `${constants_1.PROVIDE_CONFIG_FUNCTION}(<${constants_1.I18N_CONFIG}>{
i18n: {
resources: ${config.i18n.resources},
chunks: ${config.i18n.chunks},
},
})`,
});
program_1.saveAndFormat(sourceFile);
}
break;
}
}
return tree;
};
}
function addCustomConfig(tsconfigPath, basePath, config) {
return (tree) => {
const { appSourceFiles } = program_1.createProgram(tree, basePath, tsconfigPath);
const moduleFileName = createModuleFileName(config);
for (const sourceFile of appSourceFiles) {
if (sourceFile.getFilePath().endsWith('/' + moduleFileName)) {
if (config.customConfig) {
const customConfigs = [].concat(config.customConfig);
customConfigs.forEach((customConfig) => {
new_module_utils_1.addModuleProvider(sourceFile, {
import: [
{
moduleSpecifier: constants_1.SPARTACUS_CORE,
namedImports: [constants_1.PROVIDE_CONFIG_FUNCTION],
},
...customConfig.import,
],
content: `${constants_1.PROVIDE_CONFIG_FUNCTION}(${customConfig.content})`,
});
});
program_1.saveAndFormat(sourceFile);
}
break;
}
}
return tree;
};
}
function addLibraryAssets(assetsConfig, options) {
return (tree) => {
var _a, _b, _c, _d;
const { path, workspace: angularJson } = workspace_utils_1.getWorkspace(tree);
const defaultProject = workspace_utils_1.getDefaultProjectNameFromWorkspace(tree);
const project = options.project || defaultProject;
const architect = angularJson.projects[project].architect;
// `build` architect section
const architectBuild = architect === null || architect === void 0 ? void 0 : architect.build;
const buildAssets = createAssetsArray(assetsConfig, (_a = architectBuild === null || architectBuild === void 0 ? void 0 : architectBuild.options) === null || _a === void 0 ? void 0 : _a.assets);
const buildOptions = Object.assign(Object.assign({}, architectBuild === null || architectBuild === void 0 ? void 0 : architectBuild.options), { assets: buildAssets });
// `test` architect section
const architectTest = architect === null || architect === void 0 ? void 0 : architect.test;
const testAssets = createAssetsArray(assetsConfig, (_b = architectTest === null || architectTest === void 0 ? void 0 : architectTest.options) === null || _b === void 0 ? void 0 : _b.assets);
const testOptions = Object.assign(Object.assign({}, architectTest === null || architectTest === void 0 ? void 0 : architectTest.options), { assets: testAssets });
const updatedAngularJson = Object.assign(Object.assign({}, angularJson), { projects: Object.assign(Object.assign({}, angularJson.projects), { [project]: Object.assign(Object.assign({}, angularJson.projects[project]), { architect: Object.assign(Object.assign({}, architect), { build: Object.assign(Object.assign({}, architectBuild), { options: buildOptions }), test: Object.assign(Object.assign({}, architectTest), { options: testOptions }) }) }) }) });
const initialContent = (_d = (_c = tree.read(path)) === null || _c === void 0 ? void 0 : _c.toString(constants_1.UTF_8)) !== null && _d !== void 0 ? _d : '';
const toUpdate = JSON.stringify(updatedAngularJson, null, 2);
// prevent the unnecessary Angular logs about the files being updated
if (initialContent !== toUpdate) {
tree.overwrite(path, toUpdate);
}
};
}
function createAssetsArray(assetsConfig, angularJsonAssets = []) {
for (const asset of angularJsonAssets) {
if (typeof asset === 'object') {
if (asset.glob === assetsConfig.glob &&
asset.input === `./node_modules/@spartacus/${assetsConfig.input}` &&
asset.output === (assetsConfig.output || 'assets/')) {
return angularJsonAssets;
}
}
}
angularJsonAssets = [
...angularJsonAssets,
{
glob: assetsConfig.glob,
input: `./node_modules/@spartacus/${assetsConfig.input}`,
output: assetsConfig.output || 'assets/',
},
];
return angularJsonAssets;
}
function addLibraryStyles(stylingConfig, options) {
return (tree, _context) => {
var _a, _b, _c, _d, _e, _f;
const defaultProject = workspace_utils_1.getDefaultProjectNameFromWorkspace(tree);
const project = options.project || defaultProject;
const libraryScssPath = `${workspace_utils_1.getSourceRoot(tree, {
project: project,
})}/styles/spartacus/${stylingConfig.scssFileName}`;
const toAdd = `@import "${stylingConfig.importStyle}";`;
if (tree.exists(libraryScssPath)) {
const initialContent = (_b = (_a = tree.read(libraryScssPath)) === null || _a === void 0 ? void 0 : _a.toString(constants_1.UTF_8)) !== null && _b !== void 0 ? _b : '';
let content = initialContent;
if (!content.includes(toAdd)) {
content += `\n${toAdd}`;
}
// prevent the unnecessary Angular logs about the files being updated
if (initialContent !== content) {
tree.overwrite(libraryScssPath, content);
}
return tree;
}
tree.create(libraryScssPath, toAdd);
const { path, workspace: angularJson } = workspace_utils_1.getWorkspace(tree);
const architect = angularJson.projects[project].architect;
// `build` architect section
const architectBuild = architect === null || architect === void 0 ? void 0 : architect.build;
const buildOptions = Object.assign(Object.assign({}, architectBuild === null || architectBuild === void 0 ? void 0 : architectBuild.options), { styles: [
...(((_c = architectBuild === null || architectBuild === void 0 ? void 0 : architectBuild.options) === null || _c === void 0 ? void 0 : _c.styles)
? (_d = architectBuild === null || architectBuild === void 0 ? void 0 : architectBuild.options) === null || _d === void 0 ? void 0 : _d.styles
: []),
libraryScssPath,
] });
// `test` architect section
const architectTest = architect === null || architect === void 0 ? void 0 : architect.test;
const testOptions = Object.assign(Object.assign({}, architectTest === null || architectTest === void 0 ? void 0 : architectTest.options), { styles: [
...(((_e = architectTest === null || architectTest === void 0 ? void 0 : architectTest.options) === null || _e === void 0 ? void 0 : _e.styles)
? (_f = architectTest === null || architectTest === void 0 ? void 0 : architectTest.options) === null || _f === void 0 ? void 0 : _f.styles
: []),
libraryScssPath,
] });
const updatedAngularJson = Object.assign(Object.assign({}, angularJson), { projects: Object.assign(Object.assign({}, angularJson.projects), { [project]: Object.assign(Object.assign({}, angularJson.projects[project]), { architect: Object.assign(Object.assign({}, architect), { build: Object.assign(Object.assign({}, architectBuild), { options: buildOptions }), test: Object.assign(Object.assign({}, architectTest), { options: testOptions }) }) }) }) });
tree.overwrite(path, JSON.stringify(updatedAngularJson, null, 2));
};
}
exports.addLibraryStyles = addLibraryStyles;
function createNodePackageInstallationTask(context) {
return context.addTask(new tasks_1.NodePackageInstallTask());
}
exports.createNodePackageInstallationTask = createNodePackageInstallationTask;
function installPackageJsonDependencies() {
return (tree, context) => {
createNodePackageInstallationTask(context);
return tree;
};
}
exports.installPackageJsonDependencies = installPackageJsonDependencies;
function addPackageJsonDependencies(dependencies, packageJson) {
return (tree, context) => {
for (const dependency of dependencies) {
if (!dependencyExists(dependency, packageJson)) {
dependencies_1.addPackageJsonDependency(tree, dependency);
context.logger.info(`✅️ Added '${dependency.name}' into ${dependency.type}`);
}
}
return tree;
};
}
exports.addPackageJsonDependencies = addPackageJsonDependencies;
function addPackageJsonDependenciesForLibrary(dependencies, options) {
return (tree, context) => {
const packageJson = package_utils_1.readPackageJson(tree);
const spartacusLibraries = package_utils_1.createSpartacusDependencies(dependencies);
const thirdPartyLibraries = package_utils_1.createDependencies(dependencies);
const libraries = spartacusLibraries.concat(thirdPartyLibraries);
const cliFeatures = spartacusLibraries
.map((dependency) => dependency.name)
.reduce((previous, current) => {
return Object.assign(Object.assign({}, previous), {
// just install the Spartacus library, without any sub-features
[current]: [] });
}, {});
const featureOptions = createSpartacusFeatureOptionsForLibrary(options, cliFeatures, false);
addSchematicsTasks(featureOptions, context);
return schematics_1.chain([
addPackageJsonDependencies(libraries, packageJson),
installPackageJsonDependencies(),
]);
};
}
exports.addPackageJsonDependenciesForLibrary = addPackageJsonDependenciesForLibrary;
function installRequiredSpartacusFeatures(dependencyManagement, options) {
return (_tree, context) => {
if (!dependencyManagement) {
return;
}
logFeatureInstallation(dependencyManagement, context);
const featureOptions = createSpartacusFeatureOptionsForLibrary(options, dependencyManagement.featureDependencies);
addSchematicsTasks(featureOptions, context);
};
}
function logFeatureInstallation(dependencyManagement, context) {
const cliFeatures = dependencyManagement.featureDependencies;
for (const spartacusScope in cliFeatures) {
if (!cliFeatures.hasOwnProperty(spartacusScope)) {
continue;
}
const requiredFeatures = cliFeatures[spartacusScope].join(',');
context.logger.info(`⚙️ ${dependencyManagement.featureName} requires the following features from ${spartacusScope}: ${requiredFeatures}`);
}
}
function dependencyExists(dependency, packageJson) {
var _a;
return (_a = packageJson[dependency.type]) === null || _a === void 0 ? void 0 : _a.hasOwnProperty(dependency.name);
}
exports.dependencyExists = dependencyExists;
function configureB2bFeatures(options, packageJson) {
return (_tree, _context) => {
const spartacusVersion = package_utils_1.getPrefixedSpartacusSchematicsVersion();
return schematics_1.chain([
addB2bProviders(options),
addPackageJsonDependencies([
{
type: dependencies_1.NodeDependencyType.Default,
version: spartacusVersion,
name: constants_1.SPARTACUS_SETUP,
},
], packageJson),
]);
};
}
exports.configureB2bFeatures = configureB2bFeatures;
function addB2bProviders(options) {
return (tree, _context) => {
const { buildPaths } = project_tsconfig_paths_1.getProjectTsConfigPaths(tree, options.project);
if (!buildPaths.length) {
throw new schematics_1.SchematicsException('Could not find any tsconfig file. Cannot configure SpartacusConfigurationModule.');
}
const basePath = process.cwd();
for (const tsconfigPath of buildPaths) {
const { appSourceFiles } = program_1.createProgram(tree, basePath, tsconfigPath);
for (const sourceFile of appSourceFiles) {
if (sourceFile
.getFilePath()
.includes(`${constants_1.SPARTACUS_CONFIGURATION_MODULE}.module.ts`)) {
config_utils_1.getB2bConfiguration().forEach((provider) => new_module_utils_1.addModuleProvider(sourceFile, provider));
program_1.saveAndFormat(sourceFile);
break;
}
}
}
return tree;
};
}
/**
* A helper method that creates the default options for the given Spartacus' libraries.
*
* All `features` options will be set to an empty array, meaning that no features should be installed.
*
* @param spartacusLibraries
* @param options
* @returns
*/
function createSpartacusFeatureOptionsForLibrary(options, cliFeatures, interactive = true) {
return Object.keys(cliFeatures).map((spartacusLibrary) => {
var _a;
return ({
feature: spartacusLibrary,
options: Object.assign(Object.assign({}, options), {
// an empty array means that no library features will be installed.
features: (_a = cliFeatures[spartacusLibrary]) !== null && _a !== void 0 ? _a : [], interactive }),
});
});
}
exports.createSpartacusFeatureOptionsForLibrary = createSpartacusFeatureOptionsForLibrary;
function addSchematicsTasks(featureOptions, context) {
const installationTaskId = createNodePackageInstallationTask(context);
featureOptions.forEach((featureOption) => {
const runSchematicTaskOptions = {
collection: featureOption.feature,
name: 'add',
options: featureOption.options,
};
context.addTask(new tasks_1.RunSchematicTask('add-spartacus-library', runSchematicTaskOptions), [installationTaskId]);
});
}
exports.addSchematicsTasks = addSchematicsTasks;
function runExternalSpartacusLibrary(taskOptions) {
return (tree, context) => {
if (!taskOptions.collection) {
throw new schematics_1.SchematicsException(`Can't run the Spartacus library schematic, please specify the 'collection' argument.`);
}
const executionOptions = {
interactive: taskOptions.options.interactive,
};
return schematics_1.chain([
schematics_1.externalSchematic(taskOptions.collection, taskOptions.name, taskOptions.options, executionOptions),
])(tree, context);
};
}
exports.runExternalSpartacusLibrary = runExternalSpartacusLibrary;
function createModuleFileName(config) {
return `${strings_1.dasherize(config.moduleName)}-feature.module.ts`;
}
//# sourceMappingURL=lib-utils.js.map