@elsikora/setup-wizard
Version:
Setup Wizard - CLI scaffolding utility
492 lines (489 loc) • 25.8 kB
JavaScript
import { EBuildTool } from '../../domain/enum/build-tool.enum.js';
import { EModule } from '../../domain/enum/module.enum.js';
import { EPackageJsonDependencyType } from '../../domain/enum/package-json-dependency-type.enum.js';
import { NodeCommandService } from '../../infrastructure/service/node-command.service.js';
import { BUILD_TOOL_CONFIG } from '../constant/builder/build-tool-config.constant.js';
import { BUILDER_CONFIG } from '../constant/builder/config.constant.js';
import { BUILDER_CONFIG_FILE_NAMES } from '../constant/builder/file-names.constant.js';
import { BUILDER_CONFIG_MESSAGES } from '../constant/builder/messages.constant.js';
import { BUILDER_ROLLUP_PLUGIN_GENERATE_PACKAGE_JSON } from '../constant/builder/package-names.constant.js';
import { BUILDER_CONFIG_SCRIPTS } from '../constant/builder/scripts.constant.js';
import { BUILDER_CONFIG_SUMMARY } from '../constant/builder/summary.constant.js';
import { PackageJsonService } from './package-json.service.js';
/**
* Service for setting up and managing build tool configuration.
* Currently supports Rollup as the build tool.
*/
class BuilderModuleService {
/** CLI interface service for user interaction */
CLI_INTERFACE_SERVICE;
/** Command service for executing shell commands */
COMMAND_SERVICE;
/** Configuration service for managing app configuration */
CONFIG_SERVICE;
/** File system service for file operations */
FILE_SYSTEM_SERVICE;
/** Service for managing package.json */
PACKAGE_JSON_SERVICE;
/** Cached builder configuration */
config = null;
/**
* Initializes a new instance of the BuilderModuleService.
* @param cliInterfaceService - Service for CLI user interactions
* @param fileSystemService - Service for file system operations
* @param configService - Service for managing app configuration
*/
constructor(cliInterfaceService, fileSystemService, configService) {
this.CLI_INTERFACE_SERVICE = cliInterfaceService;
this.FILE_SYSTEM_SERVICE = fileSystemService;
this.COMMAND_SERVICE = new NodeCommandService(cliInterfaceService);
this.PACKAGE_JSON_SERVICE = new PackageJsonService(fileSystemService, this.COMMAND_SERVICE);
this.CONFIG_SERVICE = configService;
}
/**
* Handles existing build tool setup.
* Checks for existing configuration files and asks if user wants to remove them.
* @returns Promise resolving to true if setup should proceed, false otherwise
*/
async handleExistingSetup() {
const existingFiles = await this.findExistingConfigFiles();
if (existingFiles.length > 0) {
const messageLines = [BUILDER_CONFIG_MESSAGES.existingFilesDetected];
messageLines.push("");
for (const file of existingFiles) {
messageLines.push(`- ${file}`);
}
messageLines.push("", BUILDER_CONFIG_MESSAGES.deleteFilesQuestion);
const shouldDelete = await this.CLI_INTERFACE_SERVICE.confirm(messageLines.join("\n"), true);
if (shouldDelete) {
await Promise.all(existingFiles.map((file) => this.FILE_SYSTEM_SERVICE.deleteFile(file)));
}
else {
this.CLI_INTERFACE_SERVICE.warn(BUILDER_CONFIG_MESSAGES.existingFilesAborted);
return false;
}
}
return true;
}
/**
* Installs and configures the build tool.
* Guides the user through setting up build configuration.
* @returns Promise resolving to the module setup result
*/
async install() {
try {
this.config = await this.CONFIG_SERVICE.getModuleConfig(EModule.BUILDER);
if (!(await this.shouldInstall())) {
return { wasInstalled: false };
}
if (!(await this.handleExistingSetup())) {
return { wasInstalled: false };
}
const setupParameters = await this.setupBuilder();
return {
customProperties: setupParameters,
wasInstalled: true,
};
}
catch (error) {
this.CLI_INTERFACE_SERVICE.handleError(BUILDER_CONFIG_MESSAGES.failedSetupError, error);
throw error;
}
}
/**
* Determines if the build tool should be installed.
* Asks the user if they want to set up build tool configuration.
* Uses the saved config value as default if it exists.
* @returns Promise resolving to true if the module should be installed, false otherwise
*/
async shouldInstall() {
try {
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmSetup, await this.CONFIG_SERVICE.isModuleEnabled(EModule.BUILDER));
}
catch (error) {
this.CLI_INTERFACE_SERVICE.handleError(BUILDER_CONFIG_MESSAGES.failedConfirmation, error);
return false;
}
}
/**
* Creates tsconfig.build.json if requested.
*/
async createBuildTsconfig() {
await this.FILE_SYSTEM_SERVICE.writeFile("tsconfig.build.json", BUILDER_CONFIG.buildTsconfigTemplate(), "utf8");
}
/**
* Creates build tool configuration file.
* Generates the configuration file with user-specified options.
* @param tool - The selected build tool
* @param entryPoint - The entry point file for the build
* @param outputDirectory - The output directory for built files
* @param formats - The output formats to generate
* @param isSourceMapsEnabled - Whether to generate source maps
* @param isMinifyEnabled - Whether to minify the output
* @param isCliApp - Whether this is a CLI application
* @param isPathAliasEnabled - Whether to use path aliases
* @param isDecoratorsEnabled - Whether decorators are used
* @param isPackageJsonGenerationEnabled - Whether to generate package.json
* @param isCommonjsEnabled - Whether to include CommonJS plugin
*/
async createConfig(tool, entryPoint, outputDirectory, formats, isSourceMapsEnabled, isMinifyEnabled, isCliApp, isPathAliasEnabled, isDecoratorsEnabled, isPackageJsonGenerationEnabled, isCommonjsEnabled) {
const toolConfig = BUILD_TOOL_CONFIG[tool];
const isTypeScript = entryPoint.endsWith(".ts") || entryPoint.endsWith(".tsx");
if (toolConfig.configGenerator) {
const configContent = toolConfig.configGenerator({
entryPoint,
formats,
isCliApp,
isCommonjsEnabled,
isDecoratorsEnabled,
isMinifyEnabled,
isPackageJsonGenerationEnabled,
isPathAliasEnabled,
isSourceMapsEnabled,
isTypeScript,
outputDirectory,
});
await this.FILE_SYSTEM_SERVICE.writeFile(toolConfig.configFileName, configContent, "utf8");
}
else {
// Fallback for tools without config generators yet
this.CLI_INTERFACE_SERVICE.warn(BUILDER_CONFIG_MESSAGES.configGeneratorNotImplemented(toolConfig.name));
await this.FILE_SYSTEM_SERVICE.writeFile(toolConfig.configFileName, BUILDER_CONFIG_MESSAGES.todoConfigContent, "utf8");
}
}
/**
* Displays a summary of the build tool setup results.
* Lists configuration options, generated scripts, and files.
* @param tool - The selected build tool
* @param entryPoint - The configured entry point
* @param outputDirectory - The configured output directory
* @param formats - The selected output formats
* @param isSourceMapsEnabled - Whether source maps are enabled
* @param isMinifyEnabled - Whether minification is enabled
* @param isCleanEnabled - Whether clean is enabled
* @param isCliApp - Whether this is a CLI application
* @param isPathAliasEnabled - Whether path aliases are enabled
* @param isDecoratorsEnabled - Whether decorators are enabled
* @param isPackageJsonGenerationEnabled - Whether package.json generation is enabled
* @param isBuildTsconfigEnabled - Whether build tsconfig is enabled
*/
displaySetupSummary(tool, entryPoint, outputDirectory, formats, isSourceMapsEnabled, isMinifyEnabled, isCleanEnabled, isCliApp, isPathAliasEnabled, isDecoratorsEnabled, isPackageJsonGenerationEnabled, isBuildTsconfigEnabled) {
const toolConfig = BUILD_TOOL_CONFIG[tool];
const summary = [BUILDER_CONFIG_MESSAGES.configurationCreated, "", BUILDER_CONFIG_MESSAGES.configurationOptionsLabel, BUILDER_CONFIG_MESSAGES.summaryTool(toolConfig.name), BUILDER_CONFIG_MESSAGES.summaryEntryPoint(entryPoint), BUILDER_CONFIG_MESSAGES.summaryOutputDirectory(outputDirectory), BUILDER_CONFIG_MESSAGES.summaryFormats(formats.join(", "))];
if (isCliApp) {
summary.push(BUILDER_CONFIG_MESSAGES.summaryCliApp);
}
if (isSourceMapsEnabled) {
summary.push(BUILDER_CONFIG_MESSAGES.sourceMapsEnabled);
}
if (isMinifyEnabled) {
summary.push(BUILDER_CONFIG_MESSAGES.minifyEnabled);
}
if (isCleanEnabled) {
summary.push(BUILDER_CONFIG_MESSAGES.cleanEnabled);
}
if (isPathAliasEnabled) {
summary.push(BUILDER_CONFIG_MESSAGES.pathAliasEnabled);
}
if (isDecoratorsEnabled) {
summary.push(BUILDER_CONFIG_MESSAGES.decoratorsEnabled);
}
if (isPackageJsonGenerationEnabled) {
summary.push(BUILDER_CONFIG_MESSAGES.packageJsonGenerationEnabled);
}
summary.push("", BUILDER_CONFIG_MESSAGES.generatedScriptsLabel, BUILDER_CONFIG_MESSAGES.buildDescription, BUILDER_CONFIG_MESSAGES.buildWatchDescription, "", BUILDER_CONFIG_MESSAGES.generatedFilesLabel, `• ${toolConfig.configFileName}`);
if (isBuildTsconfigEnabled) {
summary.push("• tsconfig.build.json");
}
this.CLI_INTERFACE_SERVICE.note(BUILDER_CONFIG_MESSAGES.setupCompleteTitle, summary.join("\n"));
}
/**
* Finds existing build tool configuration files.
* @returns Promise resolving to an array of file paths for existing configuration files
*/
async findExistingConfigFiles() {
const existingFiles = [];
for (const file of BUILDER_CONFIG_FILE_NAMES) {
if (await this.FILE_SYSTEM_SERVICE.isPathExists(file)) {
existingFiles.push(file);
}
}
return existingFiles;
}
/**
* Prompts the user for the entry point configuration.
* @returns Promise resolving to the entry point
*/
async getEntryPoint() {
const initialValue = this.config?.entryPoint ?? BUILDER_CONFIG_SUMMARY.entryPointDefault;
return await this.CLI_INTERFACE_SERVICE.text(BUILDER_CONFIG_MESSAGES.entryPointPrompt, BUILDER_CONFIG_SUMMARY.entryPointDefault, initialValue, (value) => {
if (!value) {
return BUILDER_CONFIG_MESSAGES.entryPointRequired;
}
return /\.(?:js|mjs|cjs|ts|tsx)$/.test(value) ? undefined : BUILDER_CONFIG_MESSAGES.entryPointValidation;
});
}
/**
* Prompts the user for the output directory configuration.
* @param isCliApp - Whether this is a CLI application
* @param toolConfig - The selected build tool configuration
* @returns Promise resolving to the output directory
*/
async getOutputDirectory(isCliApp, toolConfig) {
const defaultDirectory = isCliApp ? toolConfig.defaultOutputDirCli : toolConfig.defaultOutputDir;
const initialValue = this.config?.outputDirectory ?? defaultDirectory;
return await this.CLI_INTERFACE_SERVICE.text(BUILDER_CONFIG_MESSAGES.outputDirPrompt, defaultDirectory, initialValue, (value) => {
if (!value) {
return BUILDER_CONFIG_MESSAGES.outputDirRequired;
}
return !value.startsWith("./") && !value.startsWith("../") && value !== "." ? BUILDER_CONFIG_MESSAGES.outputDirValidation : undefined;
});
}
/**
* Prompts the user to select output formats.
* @param isCliApp - Whether this is a CLI application
* @param toolConfig - The selected build tool configuration
* @returns Promise resolving to the selected formats
*/
async getOutputFormats(isCliApp, toolConfig) {
if (isCliApp) {
// For CLI apps, let them choose a single format
const formatOptions = [];
// Add supported formats from the tool
if (toolConfig.supportedFormats.includes("esm")) {
formatOptions.push({ hint: "Modern JavaScript modules", label: "ESM (ECMAScript Modules)", value: "esm" });
}
if (toolConfig.supportedFormats.includes("cjs")) {
formatOptions.push({ hint: "Node.js compatible", label: "CommonJS", value: "cjs" });
}
const selected = await this.CLI_INTERFACE_SERVICE.select(BUILDER_CONFIG_MESSAGES.formatPromptCli, formatOptions, this.config?.formats?.[0] ?? "esm");
return [selected];
}
const defaultFormats = this.config?.formats ?? BUILDER_CONFIG_SUMMARY.formatsDefault;
const formatOptions = [];
// Build format options based on what the tool supports
const formatDefinitions = [
{ formats: ["esm", "es"], hint: "Modern JavaScript modules", label: "ESM (ECMAScript Modules)", value: "esm" },
{ formats: ["cjs", "commonjs"], hint: "Node.js compatible", label: "CommonJS", value: "cjs" },
{ formats: ["umd"], hint: "Works everywhere", label: "UMD (Universal Module Definition)", value: "umd" },
{ formats: ["iife"], hint: "For browsers", label: "IIFE (Immediately Invoked Function Expression)", value: "iife" },
{ formats: ["module"], hint: "ES6 modules", label: "Module", value: "module" },
];
for (const formatDefinition of formatDefinitions) {
if (formatDefinition.formats.some((f) => toolConfig.supportedFormats.includes(f))) {
formatOptions.push({ hint: formatDefinition.hint, label: formatDefinition.label, value: formatDefinition.value });
}
}
const selected = await this.CLI_INTERFACE_SERVICE.multiselect(BUILDER_CONFIG_MESSAGES.formatsPrompt, formatOptions, true, defaultFormats.filter((f) => toolConfig.supportedFormats.includes(f)));
if (!selected || selected.length === 0) {
throw new Error(BUILDER_CONFIG_MESSAGES.formatsRequired);
}
return selected;
}
/**
* Prompts the user if they want a separate build tsconfig.
* @param entryPoint - The entry point to check if TypeScript
* @param isCliApp - Whether this is a CLI application
* @returns Promise resolving to true if build tsconfig should be created
*/
async isBuildTsconfigEnabled(entryPoint, isCliApp) {
// Only ask for TypeScript projects that are not CLI apps
if (isCliApp || (!entryPoint.endsWith(".ts") && !entryPoint.endsWith(".tsx"))) {
return false;
}
const isConfirmedByDefault = this.config?.isBuildTsconfigEnabled ?? true;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmBuildTsconfig, isConfirmedByDefault);
}
/**
* Prompts the user if they want to clean the output directory before build.
* @returns Promise resolving to true if output directory should be cleaned
*/
async isCleanEnabled() {
const isConfirmedByDefault = this.config?.isCleanEnabled ?? true;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmClean, isConfirmedByDefault);
}
/**
* Prompts the user if this is a CLI application.
* @returns Promise resolving to true if this is a CLI app
*/
async isCliApp() {
const isConfirmedByDefault = this.config?.isCliApp ?? false;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmCliApp, isConfirmedByDefault);
}
/**
* Prompts the user if they need CommonJS plugin support.
* @param tool - The selected build tool
* @returns Promise resolving to true if CommonJS plugin should be included
*/
async isCommonjsEnabled(tool) {
// Only ask for tools that have CommonJS plugin support (mainly Rollup)
if (tool !== EBuildTool.ROLLUP) {
return false;
}
const isConfirmedByDefault = this.config?.isCommonjsEnabled ?? true;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmCommonjs, isConfirmedByDefault);
}
/**
* Prompts the user if they use decorators.
* @returns Promise resolving to true if decorators are used
*/
async isDecoratorsEnabled() {
const isConfirmedByDefault = this.config?.isDecoratorsEnabled ?? false;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmDecorators, isConfirmedByDefault);
}
/**
* Prompts the user if they want to minify the output.
* @returns Promise resolving to true if output should be minified
*/
async isMinifyEnabled() {
const isConfirmedByDefault = this.config?.isMinifyEnabled ?? false;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmMinify, isConfirmedByDefault);
}
/**
* Prompts the user if they want to generate package.json files.
* @param isCliApp - Whether this is a CLI application
* @returns Promise resolving to true if package.json should be generated
*/
async isPackageJsonGenerationEnabled(isCliApp) {
if (isCliApp) {
// CLI apps don't need package.json generation
return false;
}
const isConfirmedByDefault = this.config?.isPackageJsonGenerationEnabled ?? false;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmPackageJsonGeneration, isConfirmedByDefault);
}
/**
* Prompts the user if they want to use path aliases.
* @param entryPoint - The entry point to check if TypeScript
* @returns Promise resolving to true if path aliases should be used
*/
async isPathAliasEnabled(entryPoint) {
// Only ask for TypeScript projects
if (!entryPoint.endsWith(".ts") && !entryPoint.endsWith(".tsx")) {
return false;
}
const isConfirmedByDefault = this.config?.isPathAliasEnabled ?? false;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmPathAlias, isConfirmedByDefault);
}
/**
* Prompts the user if they want to generate source maps.
* @returns Promise resolving to true if source maps should be generated
*/
async isSourceMapsEnabled() {
const isConfirmedByDefault = this.config?.isSourceMapsEnabled ?? true;
return await this.CLI_INTERFACE_SERVICE.confirm(BUILDER_CONFIG_MESSAGES.confirmSourceMaps, isConfirmedByDefault);
}
/**
* Prompts the user to select a build tool.
* @returns Promise resolving to the selected build tool
*/
async selectBuildTool() {
const savedTool = this.config?.tool;
// Create options for all available build tools
const availableTools = Object.values(EBuildTool).map((tool) => ({
description: BUILD_TOOL_CONFIG[tool].description,
label: BUILD_TOOL_CONFIG[tool].name,
value: tool,
}));
return await this.CLI_INTERFACE_SERVICE.select(BUILDER_CONFIG_MESSAGES.selectBuildTool, availableTools, savedTool ?? EBuildTool.ROLLUP);
}
/**
* Sets up the builder configuration.
* Collects user input, installs dependencies, creates config files, and sets up scripts.
* @returns Promise resolving to an object containing builder parameters
*/
async setupBuilder() {
try {
const parameters = {};
// Select build tool
const tool = await this.selectBuildTool();
parameters.tool = tool;
const toolConfig = BUILD_TOOL_CONFIG[tool];
// Get user input for build configuration
const isCliApp = await this.isCliApp();
parameters.isCliApp = isCliApp;
// Check if tool supports CLI apps
if (isCliApp && !toolConfig.canSupportCliApps) {
throw new Error(BUILDER_CONFIG_MESSAGES.cliAppNotSupported(toolConfig.name));
}
const entryPoint = await this.getEntryPoint();
parameters.entryPoint = entryPoint;
const outputDirectory = await this.getOutputDirectory(isCliApp, toolConfig);
parameters.outputDirectory = outputDirectory;
const formats = await this.getOutputFormats(isCliApp, toolConfig);
parameters.formats = formats;
const isSourceMapsEnabled = await this.isSourceMapsEnabled();
parameters.isSourceMapsEnabled = isSourceMapsEnabled;
const isMinifyEnabled = await this.isMinifyEnabled();
parameters.isMinifyEnabled = isMinifyEnabled;
const isCleanEnabled = await this.isCleanEnabled();
parameters.isCleanEnabled = isCleanEnabled;
const isCommonjsEnabled = await this.isCommonjsEnabled(tool);
parameters.isCommonjsEnabled = isCommonjsEnabled;
const isTypeScript = entryPoint.endsWith(".ts") || entryPoint.endsWith(".tsx");
const isPathAliasEnabled = await this.isPathAliasEnabled(entryPoint);
parameters.isPathAliasEnabled = isPathAliasEnabled;
const isDecoratorsEnabled = await this.isDecoratorsEnabled();
parameters.isDecoratorsEnabled = isDecoratorsEnabled;
const isPackageJsonGenerationEnabled = await this.isPackageJsonGenerationEnabled(isCliApp);
parameters.isPackageJsonGenerationEnabled = isPackageJsonGenerationEnabled;
const isBuildTsconfigEnabled = await this.isBuildTsconfigEnabled(entryPoint, isCliApp);
parameters.isBuildTsconfigEnabled = isBuildTsconfigEnabled;
// Install and configure
this.CLI_INTERFACE_SERVICE.startSpinner(BUILDER_CONFIG_MESSAGES.settingUpSpinner);
// Install core dependencies
await this.PACKAGE_JSON_SERVICE.installPackages([...toolConfig.coreDependencies], "latest", EPackageJsonDependencyType.DEV);
// Install optional dependencies based on features
const optionalDeps = [];
if (isTypeScript && toolConfig.optionalDependencies.typescript) {
optionalDeps.push(...toolConfig.optionalDependencies.typescript);
}
if (isMinifyEnabled && toolConfig.optionalDependencies.minify) {
optionalDeps.push(...toolConfig.optionalDependencies.minify);
}
if (isPathAliasEnabled && toolConfig.optionalDependencies.pathAlias) {
optionalDeps.push(...toolConfig.optionalDependencies.pathAlias);
}
if (isDecoratorsEnabled && toolConfig.optionalDependencies.decorators) {
optionalDeps.push(...toolConfig.optionalDependencies.decorators);
}
// Add package.json generation dependency if needed (Rollup-specific for now)
if (isPackageJsonGenerationEnabled && tool === EBuildTool.ROLLUP) {
optionalDeps.push(BUILDER_ROLLUP_PLUGIN_GENERATE_PACKAGE_JSON);
}
if (optionalDeps.length > 0) {
await this.PACKAGE_JSON_SERVICE.installPackages(optionalDeps, "latest", EPackageJsonDependencyType.DEV);
}
// Create configuration files
await this.createConfig(tool, entryPoint, outputDirectory, formats, isSourceMapsEnabled, isMinifyEnabled, isCliApp, isPathAliasEnabled, isDecoratorsEnabled, isPackageJsonGenerationEnabled, isCommonjsEnabled);
if (isBuildTsconfigEnabled) {
await this.createBuildTsconfig();
}
await this.setupScripts(tool, isCleanEnabled, outputDirectory);
this.CLI_INTERFACE_SERVICE.stopSpinner(BUILDER_CONFIG_MESSAGES.setupCompleteSpinner);
this.displaySetupSummary(tool, entryPoint, outputDirectory, formats, isSourceMapsEnabled, isMinifyEnabled, isCleanEnabled, isCliApp, isPathAliasEnabled, isDecoratorsEnabled, isPackageJsonGenerationEnabled, isBuildTsconfigEnabled);
return parameters;
}
catch (error) {
this.CLI_INTERFACE_SERVICE.stopSpinner(BUILDER_CONFIG_MESSAGES.failedSetupSpinner);
throw error;
}
}
/**
* Sets up npm scripts for the build tool.
* Adds scripts for building and watching.
* @param tool - The selected build tool
* @param isCleanEnabled - Whether to add prebuild clean script
* @param outputDirectory - The output directory
*/
async setupScripts(tool, isCleanEnabled, outputDirectory) {
await this.PACKAGE_JSON_SERVICE.addScript(BUILDER_CONFIG_SCRIPTS.build.name, BUILDER_CONFIG_SCRIPTS.build.command(tool));
await this.PACKAGE_JSON_SERVICE.addScript(BUILDER_CONFIG_SCRIPTS.buildWatch.name, BUILDER_CONFIG_SCRIPTS.buildWatch.command(tool));
if (isCleanEnabled && outputDirectory) {
await this.PACKAGE_JSON_SERVICE.addScript(BUILDER_CONFIG_SCRIPTS.prebuild.name, BUILDER_CONFIG_SCRIPTS.prebuild.command(tool, outputDirectory));
}
}
}
export { BuilderModuleService };
//# sourceMappingURL=builder-module.service.js.map