fs-extra#ensureDir TypeScript Examples

The following examples show how to use fs-extra#ensureDir. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: packaging-manager.ts    From nx-plugins with MIT License 6 votes vote down vote up
private async putAssetsNextToFunctionFiles(
    assets: string[],
    outputAbsolutePath: string,
  ): Promise<void> {
    if (!assets.length) {
      return;
    }
    await Promise.all(
      assets.map(async (file) => {
        const src = join(this.originalServicePath, file);
        const dst = join(outputAbsolutePath, file);
        await ensureDir(dirname(dst));
        return await copyFile(src, dst);
      }),
    );
  }
Example #2
Source File: common-hooks.ts    From cucumber-playwright with MIT License 6 votes vote down vote up
BeforeAll(async function () {
  switch (config.browser) {
    case 'firefox':
      browser = await firefox.launch(config.browserOptions);
      break;
    case 'webkit':
      browser = await webkit.launch(config.browserOptions);
      break;
    default:
      browser = await chromium.launch(config.browserOptions);
  }
  await ensureDir(tracesDir);
});
Example #3
Source File: build.ts    From malagu with MIT License 6 votes vote down vote up
async function renderEntry(entryTemplate: string, cfg: ApplicationConfig, entry: string) {
    ensureDir(PathUtil.getProjectHomePath());
    const server = ConfigUtil.getBackendMalaguConfig(cfg).server;
    const port = server?.port ?? 9000;
    let path = server?.path ?? '';
    let entryContent = readFileSync(entryTemplate, { encoding: 'utf8' });
    entry = entry.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    path = path.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    entryContent = entryContent
        .replace(/{{ entry }}/g, entry)
        .replace(/{{ port }}/g, port)
        .replace(/{{ path }}/g, path);
    await ensureDir(PathUtil.getBackendProjectDistPath());
    const newEntry = join(PathUtil.getBackendProjectDistPath(), 'gen-entry.js');
    writeFileSync(newEntry, entryContent, { encoding: 'utf8' });
    return newEntry;

}
Example #4
Source File: formats.ts    From rediagram with MIT License 6 votes vote down vote up
async function render(
  element: ReactElement,
  {
    name,
    dir,
    format,
    dotOptions,
  }: Required<RenderOption> & {
    format: Format;
    dotOptions: ChildProcessOptions;
  },
): Promise<void> {
  const dot = renderToDot(element);
  const output = path.format({ dir, name, ext: `.${format}` });
  if (dir !== undefined) {
    await ensureDir(dir);
  }
  await exportToFile(dot, {
    format,
    output,
    childProcessOptions: dotOptions,
  });
}
Example #5
Source File: get-definitely-typed.ts    From DefinitelyTyped-tools with MIT License 6 votes vote down vote up
export async function getDefinitelyTyped(options: ParseDefinitionsOptions, log: LoggerWithErrors): Promise<FS> {
  if (options.definitelyTypedPath === undefined) {
    log.info("Downloading Definitely Typed ...");
    await ensureDir(dataDirPath);
    log.info(dataDirPath + " exists.");
    return downloadAndExtractFile(definitelyTypedZipUrl, log);
  }
  const { error, stderr, stdout } = await exec("git diff --name-only", options.definitelyTypedPath);
  if (error) {
    throw new Error(error.message + ": " + (error as ExecException).cmd);
  }
  if (stderr) {
    throw new Error(stderr);
  }
  if (stdout) {
    throw new Error(`'git diff' should be empty. Following files changed:\n${stdout}`);
  }
  log.info(`Using local DefinitelyTyped at ${options.definitelyTypedPath}`);
  return new DiskFS(`${options.definitelyTypedPath}/`);
}
Example #6
Source File: index.ts    From cli with MIT License 6 votes vote down vote up
async cleanup() {
    if (!this.core.config.specFile) {
      this.core.config.specFile = getSpecFile(this.servicePath);
    }
    process.chdir(this.servicePath);
    // 修改构建目标目录
    if (this.options.buildDir) {
      this.options.buildDir = this.transformToRelative(
        this.servicePath,
        this.options.buildDir
      );
      this.core.config.buildPath = join(
        this.servicePath,
        this.options.buildDir,
        '.serverless'
      );
      this.midwayBuildPath = this.core.config.buildPath;
    }

    if (this.options.bundle) {
      // bundle 时默认跳过依赖安装
      this.options.skipInstallDep = this.options.skipInstallDep ?? true;
    }
    await remove(this.midwayBuildPath);
    await ensureDir(this.midwayBuildPath);
    this.setStore('defaultTmpFaaSOut', this.defaultTmpFaaSOut);
  }
Example #7
Source File: index.ts    From cli with MIT License 6 votes vote down vote up
// generate api/function.js
  async gengerateVercelEntry() {
    this.core.cli.log('Generate entry file...');
    this.setGlobalDependencies('@midwayjs/serverless-vercel-starter');
    this.setGlobalDependencies('raw-body');
    const apiDir = join(this.midwayBuildPath, 'api');
    await ensureDir(apiDir);

    // strip other trigger except http
    const functionList = this.getFunctionList();
    const functions = {};
    for (const func of functionList) {
      functions[func.funcName] = func.funcInfo;
    }

    writeWrapper({
      baseDir: this.servicePath,
      service: {
        ...this.core.service,
        functions,
      },
      distDir: apiDir,
      isDefaultFunc: true,
      skipInitializer: true,
      starter: '@midwayjs/serverless-vercel-starter',
      entryAppDir: "require('path').join(__dirname, '../')",
      entryBaseDir: "baseDir: require('path').join(__dirname, '../dist')",
    });
  }
Example #8
Source File: packaging-manager.ts    From nx-plugins with MIT License 5 votes vote down vote up
async pack(functions: ReadonlyArray<FunctionDecorator>, outputAbsolutePath: string) {
    await ensureDir(join(this.originalServicePath, '.serverless'));
    if (this.serverless.service.package.individually === true) {
      await this.packIndividually(functions, outputAbsolutePath);
    } else {
      await this.packCombined(functions, outputAbsolutePath);
    }
  }
Example #9
Source File: index.ts    From farrow with MIT License 5 votes vote down vote up
writeFile = async (filename: string, content: string) => {
  try {
    await ensureDir(dirname(filename))
  } finally {
    await fs.writeFile(filename, content)
  }
}
Example #10
Source File: data-file.ts    From DefinitelyTyped-tools with MIT License 5 votes vote down vote up
export async function writeDataFile(filename: string, content: {}, formatted = true): Promise<void> {
  await ensureDir(dataDirPath);
  await writeJson(dataFilePath(filename), content, formatted);
}
Example #11
Source File: logging.ts    From DefinitelyTyped-tools with MIT License 5 votes vote down vote up
export async function writeLog(logName: string, contents: readonly string[]): Promise<void> {
  await ensureDir(logDir);
  await writeFile(logPath(logName), contents.join("\r\n"));
}
Example #12
Source File: AppUpdater.ts    From electron-differential-updater with MIT License 4 votes vote down vote up
protected async executeDownload(
    taskOptions: DownloadExecutorTask
  ): Promise<Array<string>> {
    const fileInfo = taskOptions.fileInfo;
    const downloadOptions: DownloadOptions = {
      headers: taskOptions.downloadUpdateOptions.requestHeaders,
      cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,
      sha2: (fileInfo.info as any).sha2,
      sha512: fileInfo.info.sha512
    };

    if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {
      downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it);
    }

    const updateInfo =
      taskOptions.downloadUpdateOptions.updateInfoAndProvider.info;
    const version = updateInfo.version;
    const packageInfo = fileInfo.packageInfo;
    const {
      configuration
    } = taskOptions.downloadUpdateOptions.updateInfoAndProvider.provider;
    function getCacheUpdateFileName(): string {
      // NodeJS URL doesn't decode automatically
      const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname);
      if (urlPath.endsWith(`.${taskOptions.fileExtension}`)) {
        return path.posix.basename(urlPath);
      } else {
        // url like /latest, generate name
        return `update.${taskOptions.fileExtension}`;
      }
    }
    const useAppSupportCache = configuration ? configuration.useAppSupportCache : false;
    const downloadedUpdateHelper = await this.getOrCreateDownloadHelper(
      useAppSupportCache
    );
    const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate;
    await ensureDir(cacheDir);
    const updateFileName = getCacheUpdateFileName();
    let updateFile = path.join(cacheDir, updateFileName);
    const packageFile =
      packageInfo == null
        ? null
        : path.join(
            cacheDir,
            `package-${version}${path.extname(packageInfo.path) || ".7z"}`
          );

    const done = async (isSaveCache: boolean) => {
      await downloadedUpdateHelper.setDownloadedFile(
        updateFile,
        packageFile,
        updateInfo,
        fileInfo,
        updateFileName,
        isSaveCache
      );
      await taskOptions.done!!({
        ...updateInfo,
        downloadedFile: updateFile
      });
      return packageFile == null ? [updateFile] : [updateFile, packageFile];
    };

    const log = this._logger;
    const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(
      updateFile,
      updateInfo,
      fileInfo,
      log
    );
    if (cachedUpdateFile != null) {
      updateFile = cachedUpdateFile;
      return await done(false);
    }

    const removeFileIfAny = async () => {
      await downloadedUpdateHelper.clear().catch(() => {
        // ignore
      });
      return await unlink(updateFile).catch(() => {
        // ignore
      });
    };

    const tempUpdateFile = await createTempUpdateFile(
      `temp-${updateFileName}`,
      cacheDir,
      log
    );
    try {
      await taskOptions.task(
        tempUpdateFile,
        downloadOptions,
        packageFile,
        removeFileIfAny
      );
      await rename(tempUpdateFile, updateFile);
    } catch (e) {
      await removeFileIfAny();

      if (e instanceof CancellationError) {
        log.info("cancelled");
        this.emit("update-cancelled", updateInfo);
      }
      throw e;
    }

    log.info(`New version ${version} has been downloaded to ${updateFile}`);
    return await done(true);
  }
Example #13
Source File: faas.test.ts    From cli with MIT License 4 votes vote down vote up
describe('test/faas.test.ts', () => {
  it('check', async () => {
    const cwd = join(__dirname, 'fixtures/faas');
    const logs = await runCheck(cwd);
    const logStr = logs.join('\n');
    assert(logStr.includes('no tsCodeRoot'));
    assert(logStr.includes('can not check project type'));
    assert(logStr.includes('can not check project type'));
    assert(logStr.includes('not exist package.json'));
    assert(logStr.includes('Yaml should have service config'));
    assert(logStr.includes('Yaml should have provider config'));
  });
  it('passed', async () => {
    const cwd = join(__dirname, 'fixtures/faas-passed');
    const logs = await runCheck(cwd);
    const logStr = logs.join('\n');
    if (/v10/.test(process.version)) {
      assert(logStr.includes('Node Version'));
    } else {
      assert(logStr.includes('All Check Passed'));
    }
  });
  it('configuration', async () => {
    const cwd = join(__dirname, 'fixtures/faas-configuration');
    const logs = await runCheck(cwd);
    const logStr = logs.join('\n');
    assert(logStr.includes("'./config/') to import config"));
    assert(logStr.includes('tsconfig target need ≤ es2018'));
    assert(logStr.includes('YAML package.include type should be Array'));
    assert(logStr.includes("function 'test' http.trigger need path attribute"));
    assert(logStr.includes('class A can not export "default" in index.ts'));
  });
  it('configuration', async () => {
    const cwd = join(__dirname, 'fixtures/faas-config');
    const logs = await runCheck(cwd);
    const logStr = logs.join('\n');
    assert(logStr.includes('no prod or default config'));
    assert(
      logStr.includes(
        'there is a duplicate class name(A) in index.ts and index2.ts'
      )
    );
    assert(
      logStr.includes('configNotA') &&
        logStr.includes('configNotB') &&
        !logStr.includes('configA') &&
        !logStr.includes('configB') &&
        !logStr.includes('configC') &&
        !logStr.includes('configD')
    );
  });

  it('migrate to faas', async () => {
    const baseDir = join(__dirname, 'fixtures/migrate-to-faas');
    const migrateType = [
      { mod: '@midwayjs/koa', type: 'koa', deployType: '' },
      { mod: '@midwayjs/koa', type: 'koa', deployType: 'koa' },
      { mod: 'koa', type: 'koa' },
      { mod: 'koa', type: 'koa', deployType: 'koa' },
      { mod: '@midwayjs/express', type: 'express' },
      { mod: '@midwayjs/express', type: 'express', deployType: 'express' },
      { mod: 'express', type: 'express' },
      { mod: 'express', type: 'express', deployType: 'express' },
      { mod: '@midwayjs/web', type: 'egg' },
      { mod: '@midwayjs/web', type: 'egg', deployType: 'egg' },
      { mod: 'egg', type: 'egg' },
      { mod: 'egg', type: 'egg', deployType: 'egg' },
    ];

    for (const typeInfo of migrateType) {
      const testDir = join(baseDir, 'run');
      if (existsSync(testDir)) {
        await remove(testDir);
      }
      await ensureDir(testDir);
      writeFileSync(
        join(testDir, 'package.json'),
        JSON.stringify({ dependencies: { [typeInfo.mod]: '*' } })
      );
      writeFileSync(
        join(testDir, 'f.yml'),
        YAML.dump(
          typeInfo.deployType ? { deployType: typeInfo.deployType } : {}
        )
      );
      const logs = await runCheck(testDir);
      const logStr = logs.join('\n');
      if (!typeInfo.deployType) {
        assert(
          logStr.includes(
            `Deploying ${typeInfo.type} as FAAS requires configuring the deployType as ${typeInfo.type} in the f.yml file`
          )
        );
      } else {
        assert(!logStr.includes(`Deploying ${typeInfo.type} as FAAS`));
      }
    }
  });
});
Example #14
Source File: index.ts    From cli with MIT License 4 votes vote down vote up
async deployUseServerlessDev() {
    const profDirPath = join(homedir(), '.s');
    await ensureDir(profDirPath);
    const profPath = join(profDirPath, 'access.yaml');
    let isExists = existsSync(profPath);
    let defaultRegion = process.env.SERVERLESS_DEPLOY_ENDPOINT || 'cn-hangzhou';
    let sDefaultYaml;
    let access = this.options.access || 'default';

    const funcraftConfigPath = join(homedir(), '.fcli/config.yaml');

    if (
      process.env.SERVERLESS_DEPLOY_ID &&
      process.env.SERVERLESS_DEPLOY_AK &&
      process.env.SERVERLESS_DEPLOY_SECRET
    ) {
      sDefaultYaml = {
        AccountID: this.encode(process.env.SERVERLESS_DEPLOY_ID),
        AccessKeyID: this.encode(process.env.SERVERLESS_DEPLOY_AK),
        AccessKeySecret: this.encode(process.env.SERVERLESS_DEPLOY_SECRET),
      };
      isExists = false;
    } else if (existsSync(funcraftConfigPath)) {
      const yamlContent = readFileSync(funcraftConfigPath).toString();
      const yaml: any = YAML.load(yamlContent);
      const endpointInfo = yaml.endpoint
        .replace(/^https:\/\/|fc\.aliyuncs\.com/g, '')
        .split('.');
      defaultRegion = endpointInfo[1];
      sDefaultYaml = {
        AccountID: this.encode(endpointInfo[0]),
        AccessKeyID: this.encode(yaml.access_key_id),
        AccessKeySecret: this.encode(yaml.access_key_secret),
      };
    }

    if (!isExists) {
      if (sDefaultYaml) {
        const syaml = {
          [access]: sDefaultYaml,
        };
        const text = YAML.dump(syaml, {
          skipInvalid: true,
        });
        writeFileSync(profPath, text);
        isExists = true;
      }
    }

    if (!isExists || this.options.resetConfig) {
      // aliyun config
      await setCredential();
    }

    const syaml: any = YAML.load(readFileSync(profPath).toString());
    if (!syaml[access]) {
      access = Object.keys(syaml)[0] || access;
    }
    // 执行 package 打包
    await this.core.invoke(['package'], true, {
      ...this.options,
    });

    const artifactFile =
      this.getStore('artifactFile', 'global') ||
      join(this.servicePath, 'serverless.zip');

    const akId = Crypto.AES.decrypt(
      syaml[access].AccountID,
      'SecretKey123'
    ).toString(Crypto.enc.Utf8);
    this.core.cli.log('');
    this.core.cli.log('Start deploy by @serverless-devs');
    this.core.cli.log(` - access: ${access}`);
    this.core.cli.log(
      ` - access key id: ${akId.slice(0, 4) + '*********' + akId.slice(-4)}`
    );

    const cwd = process.cwd();
    process.chdir(this.midwayBuildPath);
    let fcDeploy;
    if (!this.options.skipDeploy) {
      // https://github.com/devsapp/fc-deploy/
      fcDeploy = await loadComponent('fc-deploy');
    }
    if (!this.core.service) {
      this.core.service = {};
    }
    if (!this.core.service.provider) {
      this.core.service.provider = {};
    }

    const region = this.core.service.provider.region || defaultRegion;

    if (!this.options.serverlessDev) {
      this.options.serverlessDev = {
        access,
        region,
      };
    }
    if (typeof this.options.serverlessDev === 'object') {
      Object.assign(this.core.service.provider, this.options.serverlessDev);
    }
    const functions = generateComponentSpec(this.core.service);

    try {
      for (const fcDeployInputs of functions) {
        Object.assign(fcDeployInputs, this.options.serverlessDev);
        delete fcDeployInputs.access;
        fcDeployInputs.path = { configPath: this.midwayBuildPath };
        fcDeployInputs.props.function.codeUri = artifactFile;
        if (!this.options.skipDeploy) {
          const args = [];
          if (!this.options.useRemoteConfig) {
            args.push('--use-local');
          }
          if (this.options.yes) {
            args.push('--assume-yes');
          }
          fcDeployInputs.args = args.join(' ');
          await fcDeploy.deploy(fcDeployInputs);
        }
        const funcName = fcDeployInputs.props.function.name;

        if (fcDeployInputs?.props?.customDomains?.[0]?.domainName === 'auto') {
          this.core.cli.log('');
          for (const functionDomainInfo of fcDeployInputs.props.customDomains) {
            if (
              functionDomainInfo.domainName === 'auto' &&
              functionDomainInfo.routeConfigs?.length
            ) {
              for (const router of functionDomainInfo.routeConfigs) {
                const name =
                  `${router.functionName}.${router.serviceName}`.replace(
                    /_/g,
                    '-'
                  );
                this.core.cli.log(
                  `Auto Domain: http://${name}.${akId}.${region}.fc.devsapp.net/${(
                    router.path || ''
                  ).replace(/^\/|\*+$/g, '')}`
                );
              }
            }
          }
        }

        this.core.cli.log('');
        this.core.cli.log(`Function '${funcName}' deploy success`);
      }
    } catch (e) {
      this.core.cli.log(`Deploy error: ${e.message}`);
    }
    process.chdir(cwd);
  }
Example #15
Source File: index.ts    From cli with MIT License 4 votes vote down vote up
hooks = {
    'before:package:cleanup': async () => {
      // 跳过zip打包
      this.options.skipZip = true;
      this.options.skipInstallDep = true;
      if (!this.core.service.package) {
        this.core.service.package = {};
      }
      this.core.service.package.include = (
        this.core.service?.package?.include || []
      ).concat(['config.json', 'sitemap.json']);
    },
    'package:generateEntry': async () => {
      this.core.cli.log('Generate entry file...');
      this.setGlobalDependencies('@midwayjs/serverless-scf-starter');
      writeWrapper({
        baseDir: this.servicePath,
        service: this.core.service,
        distDir: this.midwayBuildPath,
        starter: '@midwayjs/serverless-scf-starter',
      });
    },
    'package:package': async () => {
      // 拷贝到 cloudfunctions 目录
      let projectPkgJson: any = {};
      try {
        const json: string = readFileSync(
          join(this.servicePath, 'package.json')
        ).toString();
        projectPkgJson = JSON.parse(json);
      } catch {
        // ignore
      }
      const functions = this.core.service.functions || {};
      if (existsSync(this.wechatFunctionBuildPath)) {
        this.core.cli.log('Clear old cloud functions directory');
        await remove(this.wechatFunctionBuildPath);
      }
      await ensureDir(this.wechatFunctionBuildPath);
      for (const func in functions) {
        const handlerConf = functions[func];
        const [originFileName, handlerName] = handlerConf.handler.split('.');
        const cloudFunctionName = func;
        this.core.cli.log('Create function: ' + cloudFunctionName);

        const functionDir = join(
          this.wechatFunctionBuildPath,
          cloudFunctionName
        );
        await copy(this.midwayBuildPath, functionDir);

        await this.safeRemove(join(functionDir, 'src'));
        await this.safeRemove(join(functionDir, 'f.yml'));
        await this.safeRemove(join(functionDir, 'f.origin.yml'));
        await this.safeRemove(join(functionDir, 'tsconfig.json'));
        await this.safeRemove(join(functionDir, 'dist/midway.build.json'));
        await this.safeRemove(join(functionDir, 'dist/.mwcc-cache'));

        if (originFileName !== 'index') {
          const main = 'index.js';
          const originFile = originFileName + '.js';
          writeFileSync(
            join(functionDir, main),
            `exports.main = require('./${originFile}').${handlerName};`
          );
        }

        const pkgJsonFile = join(functionDir, 'package.json');
        let pkgJson: any = {};

        if (existsSync(pkgJsonFile)) {
          pkgJson = JSON.parse(readFileSync(pkgJsonFile).toString());
        }

        pkgJson.name = `${cloudFunctionName}`;
        pkgJson.version = projectPkgJson.version || '1.0.0';
        pkgJson.main = 'index.js';
        delete pkgJson.devDependencies;
        writeFileSync(pkgJsonFile, JSON.stringify(pkgJson, null, 2));
      }
    },
  };
Example #16
Source File: cli.test.ts    From cli with MIT License 4 votes vote down vote up
describe('command-core / cli.test.ts', () => {
  it('cli no command err', async () => {
    let err;
    class TestCli extends CoreBaseCLI {
      error(e) {
        err = e;
      }
    }
    try {
      const cli = new TestCli(['', '', 'nocommand']);
      await cli.start();
    } catch {
      //
    }
    assert(err.info.command === 'nocommand');
    assert(err.message === 'command nocommand not found');
  });
  it('cli help', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      async loadPlatformPlugin() {
        this.core.addPlugin(NoCommand);
        this.core.addPlugin(TestPlugin);
      }
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli(['', '', '-h']);
    await cli.start();
    const logStr = logList.join('\n');
    assert(logStr.includes('common command'));
    assert(logStr.includes('x xChild/abc'));
    assert(logStr.includes('x xChild/abc xChildChild/def'));
    assert(logStr.includes('--xn, --name'));
    assert(logStr.includes('xChild name option'));
  });
  it('cli child help', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      async loadPlatformPlugin() {
        this.core.addPlugin(NoCommand);
        this.core.addPlugin(TestPlugin);
      }
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli(['', '', 'x', 'xChild', '-h']);
    await cli.start();
    const logStr = logList.join('\n');
    assert(logStr.includes('x xChild'));
    assert(logStr.includes('--name'));
    assert(logStr.includes('super child age'));
  });
  it('cli auto load plugin success', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli(['', '', '-h', '-V']);
    const baseDir = resolve(__dirname, './fixtures/auto-plugin');
    await ensureDir(baseDir);
    const pluginName = 'test' + Math.ceil(Date.now());
    const pkjJson = resolve(baseDir, 'package.json');
    writeFileSync(
      pkjJson,
      JSON.stringify({
        'midway-cli': {
          plugins: [pluginName],
        },
      })
    );
    const nm = resolve(baseDir, 'node_modules/' + pluginName);
    await ensureDir(nm);
    writeFileSync(
      resolve(nm, 'index.js'),
      `class Test {
        constructor() {
          this.commands = { 
            ${pluginName}: {
              lifecycleEvents: ['main'],
              options: {
                mwtest123: {
                  usage: 'xxx'
                }
              }
            }
          };
        }
      };
      exports.Test = Test;`
    );
    cli.cwd = baseDir;
    await cli.start();
    await remove(nm);
    await remove(pkjJson);
    const logContext = logList.join('\n');
    assert(logContext.indexOf(pluginName) !== -1);
    assert(logContext.indexOf('mwtest123') !== -1);
  });
  it('cli auto load plugin error', async () => {
    const cli = new CoreBaseCLI(['', '', '-h']);
    const baseDir = resolve(__dirname, './fixtures/auto-plugin');
    await ensureDir(baseDir);
    const pluginName = 'test' + Math.ceil(Date.now());
    const pkjJson = resolve(baseDir, 'package.json');
    writeFileSync(
      pkjJson,
      JSON.stringify({
        'midway-cli': {
          plugins: [pluginName],
        },
      })
    );
    const nm = resolve(baseDir, 'node_modules/' + pluginName);
    await ensureDir(nm);
    writeFileSync(
      resolve(nm, 'index.js'),
      "throw new Error('plugin error 123');"
    );
    cli.cwd = baseDir;
    try {
      await cli.start();
      assert(false);
    } catch (e) {
      assert(e.message.indexOf('Auto load mw plugin error') !== -1);
      assert(e.message.indexOf('plugin error 123') !== -1);
    }
    await remove(nm);
    await remove(pkjJson);
  });
  it('cli auto load plugin not exists', async () => {
    const cli = new CoreBaseCLI(['', '', '-h']);
    const baseDir = resolve(__dirname, './fixtures/auto-plugin');
    await ensureDir(baseDir);
    const pkjJson = resolve(baseDir, 'package.json');
    writeFileSync(
      pkjJson,
      JSON.stringify({
        'midway-cli': {
          plugins: ['test'],
        },
      })
    );
    cli.cwd = baseDir;
    try {
      await cli.start();
      assert(false);
    } catch (e) {
      assert(/'test' not install/.test(e.message));
    }
    await remove(pkjJson);
  });
  it('cli auto load plugin no pacakge.json', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli(['', '', '-h', '-V']);
    const baseDir = resolve(__dirname, './fixtures/auto-plugin');
    await ensureDir(baseDir);
    const pkjJson = resolve(baseDir, 'package.json');
    if (existsSync(pkjJson)) {
      await remove(pkjJson);
    }
    cli.cwd = baseDir;
    await cli.start();
    const logContext = logList.join('\n');
    assert(logContext.indexOf('no user package.json') !== -1);
  });
  it('cli auto load plugin no auto plugins', async () => {
    const cli = new CoreBaseCLI(['', '', '-h']);
    const baseDir = resolve(__dirname, './fixtures/auto-plugin');
    await ensureDir(baseDir);
    const pkjJson = resolve(baseDir, 'package.json');
    writeFileSync(pkjJson, JSON.stringify({}));
    cli.cwd = baseDir;
    await cli.start();
    await remove(pkjJson);
  });
  it('cli argv', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      async loadPlatformPlugin() {
        this.core.addPlugin(TestPlugin);
      }
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli({ _: [], h: true });
    await cli.start();
    assert(logList.join('\n').indexOf('common command') !== -1);
  });
  it('cli load relative plugin', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli({ _: ['noLifecycleEvents'], h: true });
    cli.loadRelativePlugin(
      relative(process.cwd(), resolve(__dirname, './plugins')),
      'no-provider.ts'
    );
    await cli.start();
    assert(logList.join('\n').indexOf('noLifecycleEvents') !== -1);
  });
  it('cli load relative plugin error', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli({ _: [], h: true });
    cli.loadRelativePlugin('./', 'no-provider.ts');
    await cli.start();
    assert(logList.join('\n').indexOf('noLifecycleEvents') === -1);
  });
  it('cli verbose', async () => {
    const logList = [];
    class TestCli extends CoreBaseCLI {
      loadLog() {
        const log = super.loadLog();
        log.log = (...args) => {
          logList.push(...args);
        };
        return log;
      }
    }
    const cli = new TestCli({ _: ['common'], h: true, V: true });
    cli.loadRelativePlugin(
      relative(process.cwd(), resolve(__dirname, './plugins')),
      'no-provider.ts'
    );
    await cli.start();
    assert(logList.join('\n').indexOf('[Verbose]') !== -1);
  });

  it('cli error', async () => {
    const originExit = process.exit;
    let exitCode;
    process.exit = (code => {
      exitCode = code;
    }) as any;
    class TestCli extends CoreBaseCLI {
      async loadPlatformPlugin() {
        this.core.addPlugin(TestPlugin);
      }
    }
    try {
      const cli = new TestCli({ _: ['common'] });
      await cli.start();
    } catch {
      //
    }
    process.exit = originExit;
    assert(exitCode === 1);
  });
});