From ddb9a806cca1425efd37379751e5d32fa2c61572 Mon Sep 17 00:00:00 2001 From: Udeesha Gautam <46980425+udeeshagautam@users.noreply.github.com> Date: Tue, 12 May 2020 20:17:37 -0700 Subject: [PATCH] Feature/project build (#10332) * initial build command execution * adding tests * Clean up test names * update SqltoolsService release in ADS for Build * Updating as per PR comments * updating yarn lock * Adding one more test for command run * Test fixes --- build/gulpfile.hygiene.js | 1 + extensions/mssql/config.json | 2 +- extensions/sql-database-projects/.gitignore | 3 +- extensions/sql-database-projects/package.json | 3 +- .../src/common/constants.ts | 2 +- .../sql-database-projects/src/common/utils.ts | 33 ++++++- .../src/controllers/mainController.ts | 4 +- .../src/controllers/projectController.ts | 19 +++- .../src/test/buildHelper.test.ts | 38 ++++++++ .../src/test/netCoreTool.test.ts | 35 +++++-- .../src/tools/buildHelper.ts | 93 +++++++++++++++++++ .../src/tools/netcoreTool.ts | 89 +++++++++++++++++- extensions/sql-database-projects/yarn.lock | 19 ++++ 13 files changed, 319 insertions(+), 22 deletions(-) create mode 100644 extensions/sql-database-projects/src/test/buildHelper.test.ts create mode 100644 extensions/sql-database-projects/src/tools/buildHelper.ts diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 84ea9b4287..1f9aab7df5 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -106,6 +106,7 @@ const indentationFilter = [ '!extensions/sql-database-projects/resources/templates/*.xml', '!extensions/sql-database-projects/src/test/baselines/*.xml', '!extensions/sql-database-projects/src/test/baselines/*.json', + '!extensions/sql-database-projects/src/test/baselines/*.sqlproj', '!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts', '!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts', '!resources/linux/snap/electron-launch' diff --git a/extensions/mssql/config.json b/extensions/mssql/config.json index 8849988ff3..1a30841305 100644 --- a/extensions/mssql/config.json +++ b/extensions/mssql/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "2.0.0-release.64", + "version": "2.0.0-release.65", "downloadFileNames": { "Windows_86": "win-x86-netcoreapp2.2.zip", "Windows_64": "win-x64-netcoreapp2.2.zip", diff --git a/extensions/sql-database-projects/.gitignore b/extensions/sql-database-projects/.gitignore index dfacd4d5b4..39c56f32b7 100644 --- a/extensions/sql-database-projects/.gitignore +++ b/extensions/sql-database-projects/.gitignore @@ -1 +1,2 @@ -*.vsix \ No newline at end of file +*.vsix +BuildDirectory/*.* diff --git a/extensions/sql-database-projects/package.json b/extensions/sql-database-projects/package.json index 23aa5c5978..59ae6b1b16 100644 --- a/extensions/sql-database-projects/package.json +++ b/extensions/sql-database-projects/package.json @@ -7,7 +7,7 @@ "preview": true, "engines": { "vscode": "^1.30.1", - "azdata": ">=1.12.0" + "azdata": ">=1.18.0" }, "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt", "icon": "images/extension.png", @@ -239,6 +239,7 @@ } }, "dependencies": { + "promisify-child-process": "^3.1.1", "vscode-languageclient": "^5.3.0-next.1", "vscode-nls": "^3.2.1", "xmldom": "^0.3.0" diff --git a/extensions/sql-database-projects/src/common/constants.ts b/extensions/sql-database-projects/src/common/constants.ts index ce35d6c9a4..6b85170b84 100644 --- a/extensions/sql-database-projects/src/common/constants.ts +++ b/extensions/sql-database-projects/src/common/constants.ts @@ -52,7 +52,7 @@ export const projectNameRequired = localize('projectNameRequired', "Name is requ export const projectLocationRequired = localize('projectLocationRequired', "Location is required to create a new database project."); export function projectAlreadyOpened(path: string) { return localize('projectAlreadyOpened', "Project '{0}' is already opened.", path); } export function projectAlreadyExists(name: string, path: string) { return localize('projectAlreadyExists', "A project named {0} already exists in {1}.", name, path); } - +export function mssqlNotFound(mssqlConfigDir: string) { return localize('mssqlNotFound', "Could not get mssql extension's install location at {0}", mssqlConfigDir); } // Project script types diff --git a/extensions/sql-database-projects/src/common/utils.ts b/extensions/sql-database-projects/src/common/utils.ts index 2dcf94181e..78a3dac9f2 100644 --- a/extensions/sql-database-projects/src/common/utils.ts +++ b/extensions/sql-database-projects/src/common/utils.ts @@ -4,11 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import * as os from 'os'; /** * Consolidates on the error message string */ -export function getErrorMessage(error: Error | string): string { - return (error instanceof Error) ? error.message : error; +export function getErrorMessage(error: any): string { + return (error instanceof Error) + ? (typeof error.message === 'string' ? error.message : '') + : typeof error === 'string' ? error : `${JSON.stringify(error, undefined, '\t')}`; } /** @@ -45,3 +48,29 @@ export function trimChars(input: string, chars: string): string { return output; } + +/** + * get quoted path to be used in any commandline argument + * @param filePath + */ +export function getSafePath(filePath: string): string { + return (os.platform() === 'win32') ? + getSafeWindowsPath(filePath) : + getSafeNonWindowsPath(filePath); +} + +/** + * ensure that path with spaces are handles correctly + */ +export function getSafeWindowsPath(filePath: string): string { + filePath = filePath.split('\\').join('\\\\').split('"').join(''); + return '"' + filePath + '"'; +} + +/** + * ensure that path with spaces are handles correctly + */ +export function getSafeNonWindowsPath(filePath: string): string { + filePath = filePath.split('\\').join('/').split('"').join(''); + return '"' + filePath + '"'; +} diff --git a/extensions/sql-database-projects/src/controllers/mainController.ts b/extensions/sql-database-projects/src/controllers/mainController.ts index f8e52fe5ae..4a566ab996 100644 --- a/extensions/sql-database-projects/src/controllers/mainController.ts +++ b/extensions/sql-database-projects/src/controllers/mainController.ts @@ -49,8 +49,8 @@ export default class MainController implements Disposable { this.apiWrapper.registerCommand('sqlDatabaseProjects.close', (node: BaseProjectTreeItem) => { this.projectsController.closeProject(node); }); this.apiWrapper.registerCommand('sqlDatabaseProjects.properties', async (node: BaseProjectTreeItem) => { await this.apiWrapper.showErrorMessage(`Properties not yet implemented: ${node.uri.path}`); }); // TODO - this.apiWrapper.registerCommand('sqlDatabaseProjects.build', async (node: BaseProjectTreeItem) => { await this.projectsController.build(node); }); - this.apiWrapper.registerCommand('sqlDatabaseProjects.deploy', (node: BaseProjectTreeItem) => { this.projectsController.deploy(node); }); + this.apiWrapper.registerCommand('sqlDatabaseProjects.build', async (node: BaseProjectTreeItem) => { await this.projectsController.buildProject(node); }); + this.apiWrapper.registerCommand('sqlDatabaseProjects.deploy', async (node: BaseProjectTreeItem) => { await this.projectsController.deploy(node); }); this.apiWrapper.registerCommand('sqlDatabaseProjects.import', async (node: BaseProjectTreeItem) => { await this.projectsController.import(node); }); this.apiWrapper.registerCommand('sqlDatabaseProjects.newScript', async (node: BaseProjectTreeItem) => { await this.projectsController.addItemPromptFromNode(node, templates.script); }); diff --git a/extensions/sql-database-projects/src/controllers/projectController.ts b/extensions/sql-database-projects/src/controllers/projectController.ts index 99adcdf12e..9377e1cea8 100644 --- a/extensions/sql-database-projects/src/controllers/projectController.ts +++ b/extensions/sql-database-projects/src/controllers/projectController.ts @@ -19,20 +19,25 @@ import { BaseProjectTreeItem } from '../models/tree/baseTreeItem'; import { ProjectRootTreeItem } from '../models/tree/projectTreeItem'; import { FolderNode } from '../models/tree/fileFolderTreeItem'; import { DeployDatabaseDialog } from '../dialogs/deployDatabaseDialog'; +import { NetCoreTool, DotNetCommandOptions } from '../tools/netcoreTool'; +import { BuildHelper } from '../tools/buildHelper'; /** * Controller for managing project lifecycle */ export class ProjectsController { private projectTreeViewProvider: SqlDatabaseProjectTreeViewProvider; + private netCoreTool: NetCoreTool; + private buildHelper: BuildHelper; projects: Project[] = []; constructor(private apiWrapper: ApiWrapper, projTreeViewProvider: SqlDatabaseProjectTreeViewProvider) { this.projectTreeViewProvider = projTreeViewProvider; + this.netCoreTool = new NetCoreTool(); + this.buildHelper = new BuildHelper(); } - public refreshProjectsTree() { this.projectTreeViewProvider.load(this.projects); } @@ -114,9 +119,17 @@ export class ProjectsController { this.refreshProjectsTree(); } - public async build(treeNode: BaseProjectTreeItem) { + public async buildProject(treeNode: BaseProjectTreeItem): Promise { + // Check mssql extension for project dlls (tracking issue #10273) + await this.buildHelper.createBuildDirFolder(); + const project = this.getProjectContextFromTreeNode(treeNode); - await this.apiWrapper.showErrorMessage(`Build not yet implemented: ${project.projectFilePath}`); // TODO + const options: DotNetCommandOptions = { + commandTitle: 'Build', + workingDirectory: project.projectFolderPath, + argument: this.buildHelper.constructBuildArguments(project.projectFilePath, this.buildHelper.extensionBuildDirPath) + }; + await this.netCoreTool.runDotnetCommand(options); } public deploy(treeNode: BaseProjectTreeItem): void { diff --git a/extensions/sql-database-projects/src/test/buildHelper.test.ts b/extensions/sql-database-projects/src/test/buildHelper.test.ts new file mode 100644 index 0000000000..e2aa6d5000 --- /dev/null +++ b/extensions/sql-database-projects/src/test/buildHelper.test.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as should from 'should'; +import * as os from 'os'; +import * as vscode from 'vscode'; +import * as path from 'path'; +import { BuildHelper } from '../tools/buildHelper'; + +describe('BuildHelper: Build Helper tests', function (): void { + + it('Should get correct build arguments', async function (): Promise { + // update settings and validate + const buildHelper = new BuildHelper(); + const resultArg = buildHelper.constructBuildArguments('dummy\\project path\\more space in path', 'dummy\\dll path'); + + if (os.platform() === 'win32') { + should(resultArg).equal(' build "dummy\\\\project path\\\\more space in path" /p:NetCoreBuild=true /p:NETCoreTargetsPath="dummy\\\\dll path"'); + } + else { + should(resultArg).equal(' build "dummy/project path/more space in path" /p:NetCoreBuild=true /p:NETCoreTargetsPath="dummy/dll path"'); + } + }); + + it('Should get correct build folder', async function (): Promise { + const buildHelper = new BuildHelper(); + await buildHelper.createBuildDirFolder(); + + // get expected path for build + let expectedPath = vscode.extensions.getExtension('Microsoft.sql-database-projects')?.extensionPath ?? 'EmptyPath'; + expectedPath = path.join(expectedPath, 'BuildDirectory'); + should(buildHelper.extensionBuildDirPath).equal(expectedPath); + }); +}); + + diff --git a/extensions/sql-database-projects/src/test/netCoreTool.test.ts b/extensions/sql-database-projects/src/test/netCoreTool.test.ts index 92a086ad9d..b0d5fecc02 100644 --- a/extensions/sql-database-projects/src/test/netCoreTool.test.ts +++ b/extensions/sql-database-projects/src/test/netCoreTool.test.ts @@ -5,19 +5,23 @@ import * as should from 'should'; import * as os from 'os'; +import * as fs from 'fs'; +import * as path from 'path'; import * as vscode from 'vscode'; import { NetCoreTool, DBProjectConfigurationKey, NetCoreInstallLocationKey, NextCoreNonWindowsDefaultPath } from '../tools/netcoreTool'; +import { getSafePath } from '../common/utils'; import { isNullOrUndefined } from 'util'; +import { generateTestFolderPath } from './testUtils'; -describe('NetCoreTool: Net core install popup tests', function (): void { +describe('NetCoreTool: Net core tests', function (): void { - it('settings value should override default paths', async function (): Promise { + it('Should override dotnet default value with settings', async function (): Promise { try { // update settings and validate await vscode.workspace.getConfiguration(DBProjectConfigurationKey).update(NetCoreInstallLocationKey, 'test value path', true); const netcoreTool = new NetCoreTool(); should(netcoreTool.netcoreInstallLocation).equal('test value path'); // the path in settings should be taken - should(netcoreTool.isNetCoreInstallationPresent).equal(false); // dotnet can not be present at dummy path in settings + should(netcoreTool.findOrInstallNetCore()).equal(false); // dotnet can not be present at dummy path in settings } finally { // clean again @@ -25,7 +29,7 @@ describe('NetCoreTool: Net core install popup tests', function (): void { } }); - it('should find right default paths', async function (): Promise { + it('Should find right dotnet default paths', async function (): Promise { const netcoreTool = new NetCoreTool(); netcoreTool.findOrInstallNetCore(); @@ -41,8 +45,23 @@ describe('NetCoreTool: Net core install popup tests', function (): void { should(result).true('dotnet is either not present or in /usr/local/share by default'); } }); -}); -export async function sleep(ms: number): Promise<{}> { - return new Promise(resolve => setTimeout(resolve, ms)); -} + it('should run a command successfully', async function (): Promise { + const netcoreTool = new NetCoreTool(); + const dummyFile = path.join(await generateTestFolderPath(), 'dummy.dacpac'); + const outputChannel = vscode.window.createOutputChannel('db project test'); + + try { + await netcoreTool.runStreamedCommand('echo test > ' + getSafePath(dummyFile), outputChannel, undefined); + const text = await fs.promises.readFile(dummyFile); + should(text.toString().trim()).equal('test'); + } + finally { + await fs.exists(dummyFile, async (existBool) => { + if (existBool) { + await fs.promises.unlink(dummyFile); + } + }); + } + }); +}); diff --git a/extensions/sql-database-projects/src/tools/buildHelper.ts b/extensions/sql-database-projects/src/tools/buildHelper.ts new file mode 100644 index 0000000000..24d48fd7bd --- /dev/null +++ b/extensions/sql-database-projects/src/tools/buildHelper.ts @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as os from 'os'; +import { promises as fs, existsSync } from 'fs'; +import * as utils from '../common/utils'; +import { mssqlNotFound } from '../common/constants'; + +const buildDirectory = 'BuildDirectory'; +const buildFiles: string[] = [ + 'Microsoft.Data.SqlClient.dll', + 'Microsoft.Data.Tools.Schema.Sql.dll', + 'Microsoft.Data.Tools.Schema.Tasks.Sql.dll', + 'Microsoft.Data.Tools.Utilities.dll', + 'Microsoft.SqlServer.Dac.dll', + 'Microsoft.SqlServer.Dac.Extensions.dll', + 'Microsoft.SqlServer.TransactSql.ScriptDom.dll', + 'Microsoft.SqlServer.Types.dll', + 'System.ComponentModel.Composition.dll', + 'Microsoft.Data.Tools.Schema.SqlTasks.targets' +]; + +export class BuildHelper { + + private extensionDir: string; + private extensionBuildDir: string; + private initialized: boolean = false; + + constructor() { + this.extensionDir = vscode.extensions.getExtension('Microsoft.sql-database-projects')?.extensionPath ?? ''; + this.extensionBuildDir = path.join(this.extensionDir, buildDirectory); + } + + // create build dlls directory + // this should not be required. temporary solution for issue #10273 + public async createBuildDirFolder(): Promise { + + if (this.initialized) { + return; + } + + if (!existsSync(this.extensionBuildDir)) { + await fs.mkdir(this.extensionBuildDir); + } + + const buildfilesPath = await this.getBuildDirPathFromMssqlTools(); + + buildFiles.forEach(async (fileName) => { + if (existsSync(path.join(buildfilesPath, fileName))) { + await fs.copyFile(path.join(buildfilesPath, fileName), path.join(this.extensionBuildDir, fileName)); + } + }); + + this.initialized = true; + } + + // get mssql sqltoolsservice path + private async getBuildDirPathFromMssqlTools(): Promise { + const mssqlConfigDir = path.join(this.extensionDir, '..', 'mssql'); + + if (existsSync(path.join(mssqlConfigDir, 'config.json'))) { + const rawConfig = await fs.readFile(path.join(mssqlConfigDir, 'config.json')); + const config = JSON.parse(rawConfig.toString()); + const installDir = config.installDirectory?.replace('{#version#}', config.version).replace('{#platform#}', this.getPlatform()); + if (installDir) { + return path.join(mssqlConfigDir, installDir); + } + } + throw new Error(mssqlNotFound(mssqlConfigDir)); + } + + private getPlatform(): string { + return os.platform() === 'win32' ? 'Windows' : + os.platform() === 'darwin' ? 'OSX' : + os.platform() === 'linux' ? 'Linux' : + ''; + } + + public get extensionBuildDirPath(): string { + return this.extensionBuildDir; + } + + public constructBuildArguments(projectPath: string, buildDirPath: string): string { + projectPath = utils.getSafePath(projectPath); + buildDirPath = utils.getSafePath(buildDirPath); + return ` build ${projectPath} /p:NetCoreBuild=true /p:NETCoreTargetsPath=${buildDirPath}`; + } +} + diff --git a/extensions/sql-database-projects/src/tools/netcoreTool.ts b/extensions/sql-database-projects/src/tools/netcoreTool.ts index 17d4e51076..83e9d11c26 100644 --- a/extensions/sql-database-projects/src/tools/netcoreTool.ts +++ b/extensions/sql-database-projects/src/tools/netcoreTool.ts @@ -7,8 +7,10 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as fs from 'fs'; import * as os from 'os'; -import { isNullOrUndefined } from 'util'; +import * as cp from 'promisify-child-process'; import * as nls from 'vscode-nls'; +import { isNullOrUndefined } from 'util'; +import * as utils from '../common/utils'; const localize = nls.loadMessageBundle(); export const DBProjectConfigurationKey: string = 'sqlDatabaseProjects'; @@ -18,12 +20,26 @@ export const NetCoreInstallationConfirmation: string = localize('sqlDatabaseProj export const UpdateNetCoreLocation: string = localize('sqlDatabaseProjects.UpdateNetCoreLocation', "Update .Net Core location"); export const InstallNetCore: string = localize('sqlDatabaseProjects.InstallNetCore', "Install .Net Core SDK"); +const projectsOutputChannel = localize('sqlDatabaseProjects.outputChannel', "Database Projects"); +const dotnet = os.platform() === 'win32' ? 'dotnet.exe' : 'dotnet'; + +export interface DotNetCommandOptions { + workingDirectory?: string; + additionalEnvironmentVariables?: NodeJS.ProcessEnv; + commandTitle?: string; + argument?: string; +} + export class NetCoreTool { - public findOrInstallNetCore(): void { + private _outputChannel: vscode.OutputChannel = vscode.window.createOutputChannel(projectsOutputChannel); + + public findOrInstallNetCore(): boolean { if (!this.isNetCoreInstallationPresent) { this.showInstallDialog(); + return false; } + return true; } private showInstallDialog(): void { @@ -40,7 +56,7 @@ export class NetCoreTool { }); } - public get isNetCoreInstallationPresent(): Boolean { + private get isNetCoreInstallationPresent(): Boolean { return (!isNullOrUndefined(this.netcoreInstallLocation) && fs.existsSync(this.netcoreInstallLocation)); } @@ -75,4 +91,71 @@ export class NetCoreTool { } return undefined; } + + public async runDotnetCommand(options: DotNetCommandOptions): Promise { + if (options && options.commandTitle !== undefined && options.commandTitle !== null) { + this._outputChannel.appendLine(`\t[ ${options.commandTitle} ]`); + } + + if (!this.findOrInstallNetCore()) { + throw new Error(NetCoreInstallationConfirmation); + } + + const dotnetPath = utils.getSafePath(path.join(this.netcoreInstallLocation, dotnet)); + const command = dotnetPath + ' ' + options.argument; + + try { + return await this.runStreamedCommand(command, this._outputChannel, options); + } catch (error) { + this._outputChannel.append(localize('sqlDatabaseProject.RunCommand.ErroredOut', "\t>>> {0} … errored out: {1}", command, utils.getErrorMessage(error))); //errors are localized in our code where emitted, other errors are pass through from external components that are not easily localized + throw error; + } + } + + // spawns the dotnet command with aruments and redirects the error and output to ADS output channel + public async runStreamedCommand(command: string, outputChannel: vscode.OutputChannel, options?: DotNetCommandOptions): Promise { + const stdoutData: string[] = []; + outputChannel.appendLine(` > ${command}`); + + const spawnOptions = { + cwd: options && options.workingDirectory, + env: Object.assign({}, process.env, options && options.additionalEnvironmentVariables), + encoding: 'utf8', + maxBuffer: 10 * 1024 * 1024, // 10 Mb of output can be captured. + shell: true, + detached: false, + windowsHide: true + }; + + const child = cp.spawn(command, [], spawnOptions); + outputChannel.show(); + + // Add listeners to print stdout and stderr and exit code + child.on('exit', (code: number | null, signal: string | null) => { + if (code !== null) { + outputChannel.appendLine(localize('sqlDatabaseProjects.RunStreamedCommand.ExitedWithCode', " >>> {0} … exited with code: {1}", command, code)); + } else { + outputChannel.appendLine(localize('sqlDatabaseProjects.RunStreamedCommand.ExitedWithSignal', " >>> {0} … exited with signal: {1}", command, signal)); + } + }); + + child.stdout!.on('data', (data: string | Buffer) => { + stdoutData.push(data.toString()); + this.outputDataChunk(data, outputChannel, localize('sqlDatabaseProjects.RunCommand.stdout', " stdout: ")); + }); + + child.stderr!.on('data', (data: string | Buffer) => { + this.outputDataChunk(data, outputChannel, localize('sqlDatabaseProjects.RunCommand.stderr', " stderr: ")); + }); + await child; + + return stdoutData.join(''); + } + + private outputDataChunk(data: string | Buffer, outputChannel: vscode.OutputChannel, header: string): void { + data.toString().split(/\r?\n/) + .forEach(line => { + outputChannel.appendLine(header + line); + }); + } } diff --git a/extensions/sql-database-projects/yarn.lock b/extensions/sql-database-projects/yarn.lock index e994a94df2..3d5776a56c 100644 --- a/extensions/sql-database-projects/yarn.lock +++ b/extensions/sql-database-projects/yarn.lock @@ -160,6 +160,13 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== +"@babel/runtime@^7.1.5": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" + integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" @@ -680,6 +687,18 @@ postinstall-build@^5.0.1: resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7" integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg== +promisify-child-process@^3.1.1: + version "3.1.4" + resolved "https://registry.yarnpkg.com/promisify-child-process/-/promisify-child-process-3.1.4.tgz#3321827f283c0be30de1354bec1c6c627f02d53c" + integrity sha512-tLifJs99E4oOXUz/dKQjRgdchfiepmYQzBVrcVX9BtUWi9aGJeGSf2KgXOWBW1JFsSYgLkl1Z9HRm8i0sf4cTg== + dependencies: + "@babel/runtime" "^7.1.5" + +regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + resolve@^1.3.2: version "1.13.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"