UNPKG

aws-cdk

Version:

AWS CDK CLI, the command line tool for CDK apps

778 lines 120 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InitTemplate = void 0; exports.cliInit = cliInit; exports.expandPlaceholders = expandPlaceholders; exports.availableInitTemplates = availableInitTemplates; exports.availableInitLanguages = availableInitLanguages; exports.printAvailableTemplates = printAvailableTemplates; exports.currentlyRecommendedAwsCdkLibFlags = currentlyRecommendedAwsCdkLibFlags; const childProcess = require("child_process"); const path = require("path"); const toolkit_lib_1 = require("@aws-cdk/toolkit-lib"); const chalk = require("chalk"); const fs = require("fs-extra"); const init_hooks_1 = require("./init-hooks"); const root_dir_1 = require("../../cli/root-dir"); const version_1 = require("../../cli/version"); const util_1 = require("../../util"); const language_1 = require("../language"); const package_manager_1 = require("./package-manager"); /* eslint-disable @typescript-eslint/no-var-requires */ // Packages don't have @types module // eslint-disable-next-line @typescript-eslint/no-require-imports const camelCase = require('camelcase'); // eslint-disable-next-line @typescript-eslint/no-require-imports const decamelize = require('decamelize'); const SUPPORTED_LANGUAGE_NAMES = language_1.SUPPORTED_LANGUAGES.map((l) => l.name); /** * Initialize a CDK package in the current directory */ async function cliInit(options) { await ensureValidCliInitOptions(options, options.ioHelper); const ioHelper = options.ioHelper; const canUseNetwork = options.canUseNetwork ?? true; const generateOnly = options.generateOnly ?? false; const workDir = options.workDir ?? process.cwd(); // Show available templates only if no fromPath, type, or language provided if (!options.fromPath && !options.type && !options.language) { await printAvailableTemplates(ioHelper); return; } // Step 1: Load template let template; if (options.fromPath) { template = await loadLocalTemplate(options.fromPath, options.templatePath); } else { template = await loadBuiltinTemplate(ioHelper, options.type, options.language); } // Step 2: Resolve language const language = await resolveLanguage(ioHelper, template, options.language, options.type); // Step 3: Initialize project following standard process await initializeProject(ioHelper, template, language, canUseNetwork, generateOnly, workDir, options.stackName, options.migrate, options.libVersion, options.packageManager); } /** * Validate CLI init options and handle invalid or incompatible option combinations */ async function ensureValidCliInitOptions(options, ioHelper) { if (options.packageManager && !['javascript', 'typescript'].includes(options.language ?? '')) { await ioHelper.defaults.warn(`--package-manager option is only applicable for JavaScript and TypeScript projects. Ignoring the provided value: ${options.packageManager}`); } } /** * Load a local custom template from file system path * @param fromPath - Path to the local template directory or multi-template repository * @param templatePath - Optional path to a specific template within a multi-template repository * @returns Promise resolving to the loaded InitTemplate */ async function loadLocalTemplate(fromPath, templatePath) { try { let actualTemplatePath = fromPath; // If templatePath is provided, it's a multi-template repository if (templatePath) { actualTemplatePath = path.join(fromPath, templatePath); if (!await fs.pathExists(actualTemplatePath)) { throw new toolkit_lib_1.ToolkitError(`Template path does not exist: ${actualTemplatePath}`); } } const template = await InitTemplate.fromPath(actualTemplatePath); if (template.languages.length === 0) { // Check if this might be a multi-template repository if (!templatePath) { const availableTemplates = await findPotentialTemplates(fromPath); if (availableTemplates.length > 0) { throw new toolkit_lib_1.ToolkitError('Use --template-path to specify which template to use.'); } } throw new toolkit_lib_1.ToolkitError('Custom template must contain at least one language directory'); } return template; } catch (error) { const displayPath = templatePath ? `${fromPath}/${templatePath}` : fromPath; throw new toolkit_lib_1.ToolkitError(`Failed to load template from path: ${displayPath}. ${error.message}`); } } /** * Load a built-in template by name */ async function loadBuiltinTemplate(ioHelper, type, language) { const templateType = type || 'default'; // "default" is the default type (and maps to "app") const template = (await availableInitTemplates()).find((t) => t.hasName(templateType)); if (!template) { await printAvailableTemplates(ioHelper, language); throw new toolkit_lib_1.ToolkitError(`Unknown init template: ${templateType}`); } return template; } /** * Resolve the programming language for the template * @param ioHelper - IO helper for user interaction * @param template - The template to resolve language for * @param requestedLanguage - User-requested language (optional) * @param type - The template type name for messages * @default undefined * @returns Promise resolving to the selected language */ async function resolveLanguage(ioHelper, template, requestedLanguage, type) { return (async () => { if (requestedLanguage) { return requestedLanguage; } if (template.languages.length === 1) { const templateLanguage = template.languages[0]; // Only show auto-detection message for built-in templates if (template.templateType !== TemplateType.CUSTOM) { await ioHelper.defaults.warn(`No --language was provided, but '${type || template.name}' supports only '${templateLanguage}', so defaulting to --language=${templateLanguage}`); } return templateLanguage; } await ioHelper.defaults.info(`Available languages for ${chalk.green(type || template.name)}: ${template.languages.map((l) => chalk.blue(l)).join(', ')}`); throw new toolkit_lib_1.ToolkitError('No language was selected'); })(); } /** * Find potential template directories in a multi-template repository * @param repositoryPath - Path to the repository root * @returns Promise resolving to array of potential template directory names */ async function findPotentialTemplates(repositoryPath) { const entries = await fs.readdir(repositoryPath, { withFileTypes: true }); const templateValidationPromises = entries .filter(entry => entry.isDirectory() && !entry.name.startsWith('.')) .map(async (entry) => { try { const templatePath = path.join(repositoryPath, entry.name); const { languages } = await getLanguageDirectories(templatePath); return languages.length > 0 ? entry.name : null; } catch (error) { // If we can't read a specific template directory, skip it but don't fail the entire operation return null; } }); /* eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism */ // Limited to directory entries const validationResults = await Promise.all(templateValidationPromises); return validationResults.filter((templateName) => templateName !== null); } /** * Get valid CDK language directories from a template path * @param templatePath - Path to the template directory * @returns Promise resolving to array of supported language names */ /** * Get valid CDK language directories from a template path * @param templatePath - Path to the template directory * @returns Promise resolving to array of supported language names and directory entries * @throws ToolkitError if directory cannot be read or validated */ async function getLanguageDirectories(templatePath) { try { const entries = await fs.readdir(templatePath, { withFileTypes: true }); const languageValidationPromises = entries .filter(directoryEntry => directoryEntry.isDirectory() && SUPPORTED_LANGUAGE_NAMES.includes(directoryEntry.name)) .map(async (directoryEntry) => { const languageDirectoryPath = path.join(templatePath, directoryEntry.name); try { const hasValidLanguageFiles = await hasLanguageFiles(languageDirectoryPath, (0, language_1.getLanguageExtensions)(directoryEntry.name)); return hasValidLanguageFiles ? directoryEntry.name : null; } catch (error) { throw new toolkit_lib_1.ToolkitError(`Cannot read language directory '${directoryEntry.name}': ${error.message}`); } }); /* eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism */ // Limited to supported CDK languages (7 max) const validationResults = await Promise.all(languageValidationPromises); return { languages: validationResults.filter((languageName) => languageName !== null), entries, }; } catch (error) { throw new toolkit_lib_1.ToolkitError(`Cannot read template directory '${templatePath}': ${error.message}`); } } /** * Iteratively check if a directory contains files with the specified extensions * @param directoryPath - Path to search for language files * @param extensions - Array of file extensions to look for * @returns Promise resolving to true if language files are found */ async function hasLanguageFiles(directoryPath, extensions) { const dirsToCheck = [directoryPath]; while (dirsToCheck.length > 0) { const currentDir = dirsToCheck.pop(); try { const entries = await fs.readdir(currentDir, { withFileTypes: true }); for (const entry of entries) { if (entry.isFile() && extensions.some(ext => entry.name.endsWith(ext))) { return true; } else if (entry.isDirectory()) { dirsToCheck.push(path.join(currentDir, entry.name)); } } } catch (error) { throw error; } } return false; } /** * Returns the name of the Python executable for this OS * @returns The Python executable name for the current platform */ function pythonExecutable() { let python = 'python3'; if (process.platform === 'win32') { python = 'python'; } return python; } const INFO_DOT_JSON = 'info.json'; var TemplateType; (function (TemplateType) { TemplateType["BUILT_IN"] = "builtin"; TemplateType["CUSTOM"] = "custom"; })(TemplateType || (TemplateType = {})); class InitTemplate { static async fromName(templatesDir, name) { const basePath = path.join(templatesDir, name); const languages = await listDirectory(basePath); const initInfo = await fs.readJson(path.join(basePath, INFO_DOT_JSON)); return new InitTemplate(basePath, name, languages, initInfo, TemplateType.BUILT_IN); } static async fromPath(templatePath) { const basePath = path.resolve(templatePath); if (!await fs.pathExists(basePath)) { throw new toolkit_lib_1.ToolkitError(`Template path does not exist: ${basePath}`); } let templateSourcePath = basePath; let { languages, entries } = await getLanguageDirectories(basePath); if (languages.length === 0) { const languageDirs = entries.filter(entry => entry.isDirectory() && SUPPORTED_LANGUAGE_NAMES.includes(entry.name)); if (languageDirs.length === 1) { // Validate that the language directory contains appropriate files const langDir = languageDirs[0].name; templateSourcePath = path.join(basePath, langDir); const hasValidFiles = await hasLanguageFiles(templateSourcePath, (0, language_1.getLanguageExtensions)(langDir)); if (!hasValidFiles) { // If we found a language directory but it doesn't contain valid files, we should inform the user throw new toolkit_lib_1.ToolkitError(`Found '${langDir}' directory but it doesn't contain the expected language files. Ensure the template contains ${langDir} source files.`); } } } const name = path.basename(basePath); return new InitTemplate(templateSourcePath, name, languages, null, TemplateType.CUSTOM); } constructor(basePath, name, languages, initInfo, templateType) { this.basePath = basePath; this.name = name; this.languages = languages; this.aliases = new Set(); this.templateType = templateType; // Only built-in templates have descriptions and aliases from info.json if (templateType === TemplateType.BUILT_IN && initInfo) { this.description = initInfo.description; for (const alias of initInfo.aliases || []) { this.aliases.add(alias); } } } /** * @param name - the name that is being checked * @returns ``true`` if ``name`` is the name of this template or an alias of it. */ hasName(name) { return name === this.name || this.aliases.has(name); } /** * Creates a new instance of this ``InitTemplate`` for a given language to a specified folder. * * @param language - the language to instantiate this template with * @param targetDirectory - the directory where the template is to be instantiated into * @param stackName - the name of the stack to create * @default undefined * @param libVersion - the version of the CDK library to use * @default undefined */ async install(ioHelper, language, targetDirectory, stackName, libVersion, packageManager) { if (this.languages.indexOf(language) === -1) { await ioHelper.defaults.error(`The ${chalk.blue(language)} language is not supported for ${chalk.green(this.name)} ` + `(it supports: ${this.languages.map((l) => chalk.blue(l)).join(', ')})`); throw new toolkit_lib_1.ToolkitError(`Unsupported language: ${language}`); } const projectInfo = { name: decamelize(path.basename(path.resolve(targetDirectory))), stackName, versions: await loadInitVersions(), }; if (libVersion) { projectInfo.versions['aws-cdk-lib'] = libVersion; } let sourceDirectory = path.join(this.basePath, language); // For auto-detected single language templates, use basePath directly if (this.templateType === TemplateType.CUSTOM && this.languages.length === 1 && path.basename(this.basePath) === language) { sourceDirectory = this.basePath; } if (this.templateType === TemplateType.CUSTOM) { // For custom templates, copy files without processing placeholders await this.installFilesWithoutProcessing(sourceDirectory, targetDirectory); } else { // For built-in templates, process placeholders as usual await this.installFiles(sourceDirectory, targetDirectory, language, projectInfo, packageManager); await this.applyFutureFlags(targetDirectory); await (0, init_hooks_1.invokeBuiltinHooks)(ioHelper, { targetDirectory, language, templateName: this.name }, { substitutePlaceholdersIn: async (...fileNames) => { const fileProcessingPromises = fileNames.map(async (fileName) => { const fullPath = path.join(targetDirectory, fileName); const template = await fs.readFile(fullPath, { encoding: 'utf-8' }); await fs.writeFile(fullPath, expandPlaceholders(template, language, projectInfo, packageManager)); }); /* eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism */ // Processing a small, known set of template files await Promise.all(fileProcessingPromises); }, placeholder: (ph) => expandPlaceholders(`%${ph}%`, language, projectInfo, packageManager), }); } } async installFiles(sourceDirectory, targetDirectory, language, project, packageManager) { for (const file of await fs.readdir(sourceDirectory)) { const fromFile = path.join(sourceDirectory, file); const toFile = path.join(targetDirectory, expandPlaceholders(file, language, project, packageManager)); if ((await fs.stat(fromFile)).isDirectory()) { await fs.mkdir(toFile); await this.installFiles(fromFile, toFile, language, project, packageManager); continue; } else if (file.match(/^.*\.template\.[^.]+$/)) { await this.installProcessed(fromFile, toFile.replace(/\.template(\.[^.]+)$/, '$1'), language, project, packageManager); continue; } else if (file.match(/^.*\.hook\.(d.)?[^.]+$/)) { // Ignore continue; } else { await fs.copy(fromFile, toFile); } } } async installProcessed(templatePath, toFile, language, project, packageManager) { const template = await fs.readFile(templatePath, { encoding: 'utf-8' }); await fs.writeFile(toFile, expandPlaceholders(template, language, project, packageManager)); } /** * Copy template files without processing placeholders (for custom templates) */ async installFilesWithoutProcessing(sourceDirectory, targetDirectory) { await fs.copy(sourceDirectory, targetDirectory, { filter: (src) => { const filename = path.basename(src); return !filename.match(/^.*\.hook\.(d.)?[^.]+$/); }, }); } /** * Adds context variables to `cdk.json` in the generated project directory to * enable future behavior for new projects. */ async applyFutureFlags(projectDir) { const cdkJson = path.join(projectDir, 'cdk.json'); if (!(await fs.pathExists(cdkJson))) { return; } const config = await fs.readJson(cdkJson); config.context = { ...config.context, ...await currentlyRecommendedAwsCdkLibFlags(), }; await fs.writeJson(cdkJson, config, { spaces: 2 }); } async addMigrateContext(projectDir) { const cdkJson = path.join(projectDir, 'cdk.json'); if (!(await fs.pathExists(cdkJson))) { return; } const config = await fs.readJson(cdkJson); config.context = { ...config.context, 'cdk-migrate': true, }; await fs.writeJson(cdkJson, config, { spaces: 2 }); } } exports.InitTemplate = InitTemplate; function expandPlaceholders(template, language, project, packageManager) { const cdkVersion = project.versions['aws-cdk-lib']; const cdkCliVersion = project.versions['aws-cdk']; let constructsVersion = project.versions.constructs; switch (language) { case 'java': case 'csharp': case 'fsharp': constructsVersion = (0, util_1.rangeFromSemver)(constructsVersion, 'bracket'); break; case 'python': constructsVersion = (0, util_1.rangeFromSemver)(constructsVersion, 'pep'); break; } return template .replace(/%name%/g, project.name) .replace(/%stackname%/, project.stackName ?? '%name.PascalCased%Stack') .replace(/%PascalNameSpace%/, project.stackName ? camelCase(project.stackName + 'Stack', { pascalCase: true }) : '%name.PascalCased%') .replace(/%PascalStackProps%/, project.stackName ? camelCase(project.stackName, { pascalCase: true }) + 'StackProps' : 'StackProps') .replace(/%name\.camelCased%/g, camelCase(project.name)) .replace(/%name\.PascalCased%/g, camelCase(project.name, { pascalCase: true })) .replace(/%cdk-version%/g, cdkVersion) .replace(/%cdk-cli-version%/g, cdkCliVersion) .replace(/%constructs-version%/g, constructsVersion) .replace(/%cdk-home%/g, (0, util_1.cdkHomeDir)()) .replace(/%name\.PythonModule%/g, project.name.replace(/-/g, '_')) .replace(/%python-executable%/g, pythonExecutable()) .replace(/%name\.StackName%/g, project.name.replace(/[^A-Za-z0-9-]/g, '-')) .replace(/%pm-cmd%/g, (0, package_manager_1.getPmCmdPrefix)(packageManager ?? 'npm')); } async function availableInitTemplates() { try { const templatesDir = path.join((0, root_dir_1.cliRootDir)(), 'lib', 'init-templates'); const templateNames = await listDirectory(templatesDir); const templatePromises = templateNames.map(templateName => InitTemplate.fromName(templatesDir, templateName)); /* eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism */ // Built-in templates are limited in number return await Promise.all(templatePromises); } catch (error) { // Return empty array if templates directory doesn't exist or can't be read // This allows the CLI to gracefully handle missing built-in templates if (error.code === 'ENOENT' || error.code === 'EACCES') { return []; } throw error; } } async function availableInitLanguages() { const templates = await availableInitTemplates(); const result = new Set(); for (const template of templates) { for (const language of template.languages) { const alias = (0, language_1.getLanguageAlias)(language); result.add(language); alias && result.add(alias); } } return [...result]; } /** * @param dirPath - is the directory to be listed. * @returns the list of file or directory names contained in ``dirPath``, excluding any dot-file, and sorted. */ async function listDirectory(dirPath) { return ((await fs.readdir(dirPath)) .filter((p) => !p.startsWith('.')) .filter((p) => !(p === 'LICENSE')) // if, for some reason, the temp folder for the hook doesn't get deleted we don't want to display it in this list .filter((p) => !(p === INFO_DOT_JSON)) .sort()); } /** * Print available templates to the user * @param ioHelper - IO helper for user interaction * @param language - Programming language filter * @default undefined */ async function printAvailableTemplates(ioHelper, language) { await ioHelper.defaults.info('Available templates:'); for (const template of await availableInitTemplates()) { if (language && template.languages.indexOf(language) === -1) { continue; } await ioHelper.defaults.info(`* ${chalk.green(template.name)}: ${template.description}`); const languageArg = language ? chalk.bold(language) : template.languages.length > 1 ? `[${template.languages.map((t) => chalk.bold(t)).join('|')}]` : chalk.bold(template.languages[0]); await ioHelper.defaults.info(` └─ ${chalk.blue(`cdk init ${chalk.bold(template.name)} --language=${languageArg}`)}`); } } async function initializeProject(ioHelper, template, language, canUseNetwork, generateOnly, workDir, stackName, migrate, cdkVersion, packageManager) { // Step 1: Ensure target directory is empty await assertIsEmptyDirectory(workDir); // Step 2: Copy template files await ioHelper.defaults.info(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`); await template.install(ioHelper, language, workDir, stackName, cdkVersion, packageManager); if (migrate) { await template.addMigrateContext(workDir); } if (await fs.pathExists(`${workDir}/README.md`)) { const readme = await fs.readFile(`${workDir}/README.md`, { encoding: 'utf-8' }); await ioHelper.defaults.info(chalk.green(readme)); } if (!generateOnly) { // Step 3: Initialize Git repository and create initial commit await initializeGitRepository(ioHelper, workDir); // Step 4: Post-install steps await postInstall(ioHelper, language, canUseNetwork, workDir, packageManager); } await ioHelper.defaults.info('✅ All done!'); } /** * Validate that a directory exists and is empty (ignoring hidden files) * @param workDir - Directory path to validate * @throws ToolkitError if directory doesn't exist or is not empty */ async function assertIsEmptyDirectory(workDir) { try { const stats = await fs.stat(workDir); if (!stats.isDirectory()) { throw new toolkit_lib_1.ToolkitError(`Path exists but is not a directory: ${workDir}`); } const files = await fs.readdir(workDir); const visibleFiles = files.filter(f => !f.startsWith('.')); if (visibleFiles.length > 0) { throw new toolkit_lib_1.ToolkitError('`cdk init` cannot be run in a non-empty directory!\n' + `Found ${visibleFiles.length} visible files in ${workDir}:\n` + visibleFiles.map(f => ` - ${f}`).join('\n')); } } catch (e) { if (e.code === 'ENOENT') { throw new toolkit_lib_1.ToolkitError(`Directory does not exist: ${workDir}\n` + 'Please create the directory first using: mkdir -p ' + workDir); } throw new toolkit_lib_1.ToolkitError(`Failed to validate directory ${workDir}: ${e.message}`); } } async function initializeGitRepository(ioHelper, workDir) { if (await isInGitRepository(workDir)) { return; } await ioHelper.defaults.info('Initializing a new git repository...'); try { await execute(ioHelper, 'git', ['init'], { cwd: workDir }); await execute(ioHelper, 'git', ['add', '.'], { cwd: workDir }); await execute(ioHelper, 'git', ['commit', '--message="Initial commit"', '--no-gpg-sign'], { cwd: workDir }); } catch { await ioHelper.defaults.warn('Unable to initialize git repository for your project.'); } } async function postInstall(ioHelper, language, canUseNetwork, workDir, packageManager) { switch (language) { case 'javascript': return postInstallJavascript(ioHelper, canUseNetwork, workDir, packageManager); case 'typescript': return postInstallTypescript(ioHelper, canUseNetwork, workDir, packageManager); case 'java': return postInstallJava(ioHelper, canUseNetwork, workDir); case 'python': return postInstallPython(ioHelper, workDir); case 'go': return postInstallGo(ioHelper, canUseNetwork, workDir); case 'csharp': return postInstallCSharp(ioHelper, canUseNetwork, workDir); case 'fsharp': return postInstallFSharp(ioHelper, canUseNetwork, workDir); } } async function postInstallJavascript(ioHelper, canUseNetwork, cwd, packageManager) { return postInstallTypescript(ioHelper, canUseNetwork, cwd, packageManager); } async function postInstallTypescript(ioHelper, canUseNetwork, cwd, packageManager) { const command = packageManager ?? 'npm'; if (!canUseNetwork) { await ioHelper.defaults.warn(`Please run '${command} install'!`); return; } await ioHelper.defaults.info(`Executing ${chalk.green(`${command} install`)}...`); try { await execute(ioHelper, command, ['install'], { cwd }); } catch (e) { await ioHelper.defaults.warn(`${command} install failed: ` + (0, util_1.formatErrorMessage)(e)); } } async function postInstallJava(ioHelper, canUseNetwork, cwd) { // Check if this is a Gradle or Maven project const hasGradleBuild = await fs.pathExists(path.join(cwd, 'build.gradle')); const hasMavenPom = await fs.pathExists(path.join(cwd, 'pom.xml')); if (hasGradleBuild) { // Gradle project const gradleWarning = "Please run './gradlew build'!"; if (!canUseNetwork) { await ioHelper.defaults.warn(gradleWarning); return; } await ioHelper.defaults.info("Executing './gradlew build'"); try { await execute(ioHelper, './gradlew', ['build'], { cwd }); } catch { await ioHelper.defaults.warn('Unable to build Gradle project'); await ioHelper.defaults.warn(gradleWarning); } } else if (hasMavenPom) { // Maven project const mvnPackageWarning = "Please run 'mvn package'!"; if (!canUseNetwork) { await ioHelper.defaults.warn(mvnPackageWarning); return; } await ioHelper.defaults.info("Executing 'mvn package'"); try { await execute(ioHelper, 'mvn', ['package'], { cwd }); } catch { await ioHelper.defaults.warn('Unable to package compiled code as JAR'); await ioHelper.defaults.warn(mvnPackageWarning); } } else { // No recognized build file await ioHelper.defaults.warn('No build.gradle or pom.xml found. Please set up your build system manually.'); } } async function postInstallPython(ioHelper, cwd) { const python = pythonExecutable(); // Check if requirements.txt exists const hasRequirements = await fs.pathExists(path.join(cwd, 'requirements.txt')); if (hasRequirements) { await ioHelper.defaults.info(`Executing ${chalk.green('Creating virtualenv...')}`); try { await execute(ioHelper, python, ['-m', 'venv', '.venv'], { cwd }); await ioHelper.defaults.info(`Executing ${chalk.green('Installing dependencies...')}`); // Install dependencies in the virtual environment const pipPath = process.platform === 'win32' ? '.venv\\Scripts\\pip' : '.venv/bin/pip'; await execute(ioHelper, pipPath, ['install', '-r', 'requirements.txt'], { cwd }); } catch { await ioHelper.defaults.warn('Unable to create virtualenv or install dependencies automatically'); await ioHelper.defaults.warn(`Please run '${python} -m venv .venv && .venv/bin/pip install -r requirements.txt'!`); } } else { await ioHelper.defaults.warn('No requirements.txt found. Please set up your Python environment manually.'); } } async function postInstallGo(ioHelper, canUseNetwork, cwd) { if (!canUseNetwork) { await ioHelper.defaults.warn('Please run \'go mod tidy\'!'); return; } await ioHelper.defaults.info(`Executing ${chalk.green('go mod tidy')}...`); try { await execute(ioHelper, 'go', ['mod', 'tidy'], { cwd }); } catch (e) { await ioHelper.defaults.warn('\'go mod tidy\' failed: ' + (0, util_1.formatErrorMessage)(e)); } } async function postInstallCSharp(ioHelper, canUseNetwork, cwd) { const dotnetWarning = "Please run 'dotnet restore && dotnet build'!"; if (!canUseNetwork) { await ioHelper.defaults.warn(dotnetWarning); return; } await ioHelper.defaults.info(`Executing ${chalk.green('dotnet restore')}...`); try { await execute(ioHelper, 'dotnet', ['restore'], { cwd }); await ioHelper.defaults.info(`Executing ${chalk.green('dotnet build')}...`); await execute(ioHelper, 'dotnet', ['build'], { cwd }); } catch (e) { await ioHelper.defaults.warn('Unable to restore/build .NET project: ' + (0, util_1.formatErrorMessage)(e)); await ioHelper.defaults.warn(dotnetWarning); } } async function postInstallFSharp(ioHelper, canUseNetwork, cwd) { // F# uses the same build system as C# return postInstallCSharp(ioHelper, canUseNetwork, cwd); } /** * @param dir - a directory to be checked * @returns true if ``dir`` is within a git repository. */ async function isInGitRepository(dir) { while (true) { if (await fs.pathExists(path.join(dir, '.git'))) { return true; } if (isRoot(dir)) { return false; } dir = path.dirname(dir); } } /** * @param dir - a directory to be checked. * @returns true if ``dir`` is the root of a filesystem. */ function isRoot(dir) { return path.dirname(dir) === dir; } /** * Executes `command`. STDERR is emitted in real-time. * * If command exits with non-zero exit code, an exception is thrown and includes * the contents of STDOUT. * * @returns STDOUT (if successful). */ async function execute(ioHelper, cmd, args, { cwd }) { const child = childProcess.spawn(cmd, args, { cwd, shell: true, stdio: ['ignore', 'pipe', 'inherit'], }); let stdout = ''; child.stdout.on('data', (chunk) => (stdout += chunk.toString())); return new Promise((ok, fail) => { child.once('error', (err) => fail(err)); child.once('exit', (status) => { if (status === 0) { return ok(stdout); } else { return fail(new toolkit_lib_1.ToolkitError(`${cmd} exited with status ${status}`)); } }); }).catch(async (err) => { await ioHelper.defaults.error(stdout); throw err; }); } /** * Return the 'aws-cdk-lib' version we will init * * This has been built into the CLI at build time. */ async function loadInitVersions() { const initVersionFile = path.join((0, root_dir_1.cliRootDir)(), 'lib', 'init-templates', '.init-version.json'); const contents = JSON.parse(await fs.readFile(initVersionFile, { encoding: 'utf-8' })); const ret = { 'aws-cdk-lib': contents['aws-cdk-lib'], 'constructs': contents.constructs, 'aws-cdk': (0, version_1.versionNumber)(), }; for (const [key, value] of Object.entries(ret)) { if (!value) { throw new toolkit_lib_1.ToolkitError(`Missing init version from ${initVersionFile}: ${key}`); } } return ret; } /** * Return the currently recommended flags for `aws-cdk-lib`. * * These have been built into the CLI at build time. */ async function currentlyRecommendedAwsCdkLibFlags() { const recommendedFlagsFile = path.join((0, root_dir_1.cliRootDir)(), 'lib', 'init-templates', '.recommended-feature-flags.json'); return JSON.parse(await fs.readFile(recommendedFlagsFile, { encoding: 'utf-8' })); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImluaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBMkZBLDBCQXNDQztBQXdiRCxnREFvQ0M7QUFVRCx3REFpQkM7QUFFRCx3REFXQztBQXVCRCwwREFjQztBQTZURCxnRkFHQztBQTErQkQsOENBQThDO0FBQzlDLDZCQUE2QjtBQUM3QixzREFBb0Q7QUFDcEQsK0JBQStCO0FBQy9CLCtCQUErQjtBQUMvQiw2Q0FBa0Q7QUFFbEQsaURBQWdEO0FBQ2hELCtDQUFrRDtBQUNsRCxxQ0FBNkU7QUFFN0UsMENBQTJGO0FBQzNGLHVEQUEwRTtBQUUxRSx1REFBdUQsQ0FBQyxvQ0FBb0M7QUFDNUYsaUVBQWlFO0FBQ2pFLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUN2QyxpRUFBaUU7QUFDakUsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBRXpDLE1BQU0sd0JBQXdCLEdBQUcsOEJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7QUFvRXRGOztHQUVHO0FBQ0ksS0FBSyxVQUFVLE9BQU8sQ0FBQyxPQUF1QjtJQUNuRCxNQUFNLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFM0QsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztJQUNsQyxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQztJQUNwRCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQztJQUNuRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUVqRCwyRUFBMkU7SUFDM0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzVELE1BQU0sdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEMsT0FBTztJQUNULENBQUM7SUFFRCx3QkFBd0I7SUFDeEIsSUFBSSxRQUFzQixDQUFDO0lBQzNCLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JCLFFBQVEsR0FBRyxNQUFNLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzdFLENBQUM7U0FBTSxDQUFDO1FBQ04sUUFBUSxHQUFHLE1BQU0sbUJBQW1CLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pGLENBQUM7SUFFRCwyQkFBMkI7SUFDM0IsTUFBTSxRQUFRLEdBQUcsTUFBTSxlQUFlLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUUzRix3REFBd0Q7SUFDeEQsTUFBTSxpQkFBaUIsQ0FDckIsUUFBUSxFQUNSLFFBQVEsRUFDUixRQUFRLEVBQ1IsYUFBYSxFQUNiLFlBQVksRUFDWixPQUFPLEVBQ1AsT0FBTyxDQUFDLFNBQVMsRUFDakIsT0FBTyxDQUFDLE9BQU8sRUFDZixPQUFPLENBQUMsVUFBVSxFQUNsQixPQUFPLENBQUMsY0FBYyxDQUN2QixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLHlCQUF5QixDQUFDLE9BQXVCLEVBQUUsUUFBa0I7SUFDbEYsSUFBSSxPQUFPLENBQUMsY0FBYyxJQUFJLENBQUMsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUM3RixNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLG9IQUFvSCxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztJQUM3SyxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQixDQUFDLFFBQWdCLEVBQUUsWUFBcUI7SUFDdEUsSUFBSSxDQUFDO1FBQ0gsSUFBSSxrQkFBa0IsR0FBRyxRQUFRLENBQUM7UUFFbEMsZ0VBQWdFO1FBQ2hFLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakIsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFFdkQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7Z0JBQzdDLE1BQU0sSUFBSSwwQkFBWSxDQUFDLGlDQUFpQyxrQkFBa0IsRUFBRSxDQUFDLENBQUM7WUFDaEYsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUVqRSxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3BDLHFEQUFxRDtZQUNyRCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ2xCLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbEUsSUFBSSxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0JBQ2xDLE1BQU0sSUFBSSwwQkFBWSxDQUNwQix1REFBdUQsQ0FDeEQsQ0FBQztnQkFDSixDQUFDO1lBQ0gsQ0FBQztZQUNELE1BQU0sSUFBSSwwQkFBWSxDQUFDLDhEQUE4RCxDQUFDLENBQUM7UUFDekYsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1FBQ3BCLE1BQU0sV0FBVyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLElBQUksWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUM1RSxNQUFNLElBQUksMEJBQVksQ0FBQyxzQ0FBc0MsV0FBVyxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ2hHLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsbUJBQW1CLENBQUMsUUFBa0IsRUFBRSxJQUFhLEVBQUUsUUFBaUI7SUFDckYsTUFBTSxZQUFZLEdBQUcsSUFBSSxJQUFJLFNBQVMsQ0FBQyxDQUFDLG9EQUFvRDtJQUU1RixNQUFNLFFBQVEsR0FBRyxDQUFDLE1BQU0sc0JBQXNCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO0lBQ3ZGLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNkLE1BQU0sdUJBQXVCLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sSUFBSSwwQkFBWSxDQUFDLDBCQUEwQixZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxLQUFLLFVBQVUsZUFBZSxDQUFDLFFBQWtCLEVBQUUsUUFBc0IsRUFBRSxpQkFBMEIsRUFBRSxJQUFhO0lBQ2xILE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRTtRQUNqQixJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDdEIsT0FBTyxpQkFBaUIsQ0FBQztRQUMzQixDQUFDO1FBQ0QsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNwQyxNQUFNLGdCQUFnQixHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDL0MsMERBQTBEO1lBQzFELElBQUksUUFBUSxDQUFDLFlBQVksS0FBSyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ2xELE1BQU0sUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQzFCLG9DQUFvQyxJQUFJLElBQUksUUFBUSxDQUFDLElBQUksb0JBQW9CLGdCQUFnQixrQ0FBa0MsZ0JBQWdCLEVBQUUsQ0FDbEosQ0FBQztZQUNKLENBQUM7WUFDRCxPQUFPLGdCQUFnQixDQUFDO1FBQzFCLENBQUM7UUFDRCxNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUMxQiwyQkFBMkIsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLFFBQVEsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQzVILENBQUM7UUFDRixNQUFNLElBQUksMEJBQVksQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ3JELENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDUCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxjQUFzQjtJQUMxRCxNQUFNLE9BQU8sR0FBRyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFFMUUsTUFBTSwwQkFBMEIsR0FBRyxPQUFPO1NBQ3ZDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ25FLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDbkIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNELE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxNQUFNLHNCQUFzQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2pFLE9BQU8sU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNsRCxDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQiw4RkFBOEY7WUFDOUYsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFTCwyRUFBMkUsQ0FBQywrQkFBK0I7SUFDM0csTUFBTSxpQkFBaUIsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUN4RSxPQUFPLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLFlBQVksRUFBMEIsRUFBRSxDQUFDLFlBQVksS0FBSyxJQUFJLENBQUMsQ0FBQztBQUNuRyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNIOzs7OztHQUtHO0FBQ0gsS0FBSyxVQUFVLHNCQUFzQixDQUFDLFlBQW9CO0lBQ3hELElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUV4RSxNQUFNLDBCQUEwQixHQUFHLE9BQU87YUFDdkMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxJQUFJLHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDaEgsR0FBRyxDQUFDLEtBQUssRUFBRSxjQUFjLEVBQUUsRUFBRTtZQUM1QixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzRSxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLGdCQUFnQixDQUFDLHFCQUFxQixFQUFFLElBQUEsZ0NBQXFCLEVBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ3hILE9BQU8scUJBQXFCLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUM1RCxDQUFDO1lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxJQUFJLDBCQUFZLENBQUMsbUNBQW1DLGNBQWMsQ0FBQyxJQUFJLE1BQU0sS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDdEcsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUwsMkVBQTJFLENBQUMsNkNBQTZDO1FBQ3pILE1BQU0saUJBQWlCLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDeEUsT0FBTztZQUNMLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQTBCLEVBQUUsQ0FBQyxZQUFZLEtBQUssSUFBSSxDQUFDO1lBQ3BHLE9BQU87U0FDUixDQUFDO0lBQ0osQ0FBQztJQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7UUFDcEIsTUFBTSxJQUFJLDBCQUFZLENBQUMsbUNBQW1DLFlBQVksTUFBTSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUMvRixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsS0FBSyxVQUFVLGdCQUFnQixDQUFDLGFBQXFCLEVBQUUsVUFBb0I7SUFDekUsTUFBTSxXQUFXLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUVwQyxPQUFPLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDOUIsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRyxDQUFDO1FBRXRDLElBQUksQ0FBQztZQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUV0RSxLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUM1QixJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUN2RSxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDO3FCQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7b0JBQy9CLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ3RELENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDcEIsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsZ0JBQWdCO0lBQ3ZCLElBQUksTUFBTSxHQUFHLFNBQVMsQ0FBQztJQUN2QixJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDakMsTUFBTSxHQUFHLFFBQVEsQ0FBQztJQUNwQixDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUNELE1BQU0sYUFBYSxHQUFHLFdBQVcsQ0FBQztBQU9sQyxJQUFLLFlBR0o7QUFIRCxXQUFLLFlBQVk7SUFDZixvQ0FBb0IsQ0FBQTtJQUNwQixpQ0FBaUIsQ0FBQTtBQUNuQixDQUFDLEVBSEksWUFBWSxLQUFaLFlBQVksUUFHaEI7QUFFRCxNQUFhLFlBQVk7SUFDaEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBb0IsRUFBRSxJQUFZO1FBQzdELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9DLE1BQU0sU0FBUyxHQUFHLE1BQU0sYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2hELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLE9BQU8sSUFBSSxZQUFZLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0RixDQUFDO0lBRU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBb0I7UUFDL0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUU1QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDbkMsTUFBTSxJQUFJLDBCQUFZLENBQUMsaUNBQWlDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDdEUsQ0FBQztRQUVELElBQUksa0JBQWtCLEdBQUcsUUFBUSxDQUFDO1FBQ2xDLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVwRSxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDM0IsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUMxQyxLQUFLLENBQUMsV0FBVyxFQUFFO2dCQUNuQix3QkFBd0IsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUM5QyxDQUFDO1lBRUYsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUM5QixrRUFBa0U7Z0JBQ2xFLE1BQU0sT0FBTyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3JDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNsRCxNQUFNLGFBQWEsR0FBRyxNQUFNLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLElBQUEsZ0NBQXFCLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFFakcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO29CQUNuQixpR0FBaUc7b0JBQ2pHLE1BQU0sSUFBSSwwQkFBWSxDQUFDLFVBQVUsT0FBTyxnR0FBZ0csT0FBTyxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUNuSyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXJDLE9BQU8sSUFBSSxZQUFZLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFNRCxZQUNtQixRQUFnQixFQUNqQixJQUFZLEVBQ1osU0FBbUIsRUFDbkMsUUFBaUMsRUFDakMsWUFBMEI7UUFKVCxhQUFRLEdBQVIsUUFBUSxDQUFRO1FBQ2pCLFNBQUksR0FBSixJQUFJLENBQVE7UUFDWixjQUFTLEdBQVQsU0FBUyxDQUFVO1FBTnJCLFlBQU8sR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBVTFDLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLHVFQUF1RTtRQUN2RSxJQUFJLFlBQVksS0FBSyxZQUFZLENBQUMsUUFBUSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ3ZELElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQztZQUN4QyxLQUFLLE1BQU0sS0FBSyxJQUFJLFFBQVEsQ0FBQyxPQUFPLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQzNDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzFCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLE9BQU8sQ0FBQyxJQUFZO1FBQ3pCLE9BQU8sSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNJLEtBQUssQ0FBQyxPQUFPLENBQ2xCLFFBQWtCLEVBQ2xCLFFBQWdCLEVBQ2hCLGVBQXVCLEVBQ3ZCLFNBQWtCLEVBQ2xCLFVBQW1CLEVBQ25CLGNBQWlDO1FBRWpDLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM1QyxNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUMzQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGtDQUFrQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRztnQkFDcEYsaUJBQWlCLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQzFFLENBQUM7WUFDRixNQUFNLElBQUksMEJBQVksQ0FBQyx5QkFBeUIsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM5RCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQWdCO1lBQy9CLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDOUQsU0FBUztZQUNULFFBQVEsRUFBRSxNQUFNLGdCQUFnQixFQUFFO1NBQ25DLENBQUM7UUFFRixJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsV0FBVyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsR0FBRyxVQUFVLENBQUM7UUFDbkQsQ0FBQztRQUVELElBQUksZUFBZSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUV6RCxxRUFBcUU7UUFDckUsSUFBSSxJQUFJLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUN4RSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM5QyxlQUFlLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUNsQyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUM5QyxtRUFBbUU7WUFDbkUsTUFBTSxJQUFJLENBQUMsNkJBQTZCLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQzdFLENBQUM7YUFBTSxDQUFDO1lBQ04sd0RBQXdEO1lBQ3hELE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsZUFBZSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7WUFDakcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDN0MsTUFBTSxJQUFBLCtCQUFrQixFQUN0QixRQUFRLEVBQ1IsRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQ3REO2dCQUNFLHdCQUF3QixFQUFFLEtBQUssRUFBRSxHQUFHLFNBQW1CLEVBQUUsRUFBRTtvQkFDekQsTUFBTSxzQkFBc0IsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTt3QkFDOUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsUUFBUSxDQUFDLENBQUM7d0JBQ3RELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQzt3QkFDcEUsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO29CQUNwRyxDQUFDLENBQUMsQ0FBQztvQkFDSCwyRUFBMkUsQ0FBQyxrREFBa0Q7b0JBQzlILE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO2dCQUM1QyxDQUFDO2dCQUNELFdBQVcsRUFBRSxDQUFDLEVBQVUsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQzthQUNsRyxDQUNGLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxZ