Browse Source

add collection api

nameczz 4 years ago
parent
commit
169ce1e897

+ 1 - 0
server/package.json

@@ -29,6 +29,7 @@
     "@nestjs/serve-static": "^2.1.4",
     "@types/passport-jwt": "^3.0.5",
     "@types/passport-local": "^1.0.33",
+    "@zilliz/milvus-sdk-node-dev": "^0.1.0",
     "class-transformer": "^0.4.0",
     "class-validator": "^0.13.1",
     "passport": "^0.4.1",

+ 32 - 1
server/src/collections/collections.controller.ts

@@ -1,5 +1,15 @@
-import { Controller, Get } from '@nestjs/common';
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  Post,
+  UsePipes,
+  ValidationPipe,
+} from '@nestjs/common';
 import { CollectionsService } from './collections.service';
+import { CreateCollection } from './dto';
 
 @Controller('collections')
 export class CollectionsController {
@@ -9,4 +19,25 @@ export class CollectionsController {
   async getCollections() {
     return await this.collectionsService.showCollections();
   }
+
+  @Post()
+  @UsePipes(new ValidationPipe())
+  async createCollection(@Body() data: CreateCollection) {
+    return await this.collectionsService.createCollection(data);
+  }
+
+  @Delete(':name')
+  // todo: need check some special symbols
+  async deleteCollection(@Param('name') name: string) {
+    return await this.collectionsService.dropCollection({
+      collection_name: name,
+    });
+  }
+
+  @Get(':name')
+  async describeCollection(@Param('name') name: string) {
+    return await this.collectionsService.describeCollection({
+      collection_name: name,
+    });
+  }
 }

+ 65 - 3
server/src/collections/collections.service.ts

@@ -1,11 +1,73 @@
 import { Injectable } from '@nestjs/common';
 import { MilvusService } from '../milvus/milvus.service';
-
+import {
+  CreateCollectionReq,
+  DescribeCollectionReq,
+  DropCollectionReq,
+  HasCollectionReq,
+  GetCollectionStatisticsReq,
+} from '@zilliz/milvus-sdk-node-dev/dist/milvus/types/Collection'; // todo: need improve like export types in root file.
+import { throwErrorFromSDK } from 'src/utils/Error';
 @Injectable()
 export class CollectionsService {
   constructor(private milvusService: MilvusService) {}
 
-  showCollections() {
-    return { address: this.milvusService.milvusAddressGetter };
+  get milvusClient() {
+    return this.milvusService.milvusClientGetter;
+  }
+
+  async showCollections() {
+    const data = [];
+    const res = await this.milvusClient.showCollections();
+    throwErrorFromSDK(res.status);
+    if (res.collection_names.length > 0) {
+      for (const name of res.collection_names) {
+        const collectionInfo = await this.describeCollection({
+          collection_name: name,
+        });
+        throwErrorFromSDK(collectionInfo.status);
+        const collectionStatistics = await this.getCollectionStatistics({
+          collection_name: name,
+        });
+        throwErrorFromSDK(collectionStatistics.status);
+        data.push({
+          collection_name: name,
+          schema: collectionInfo.schema,
+          rowCount: collectionStatistics.stats.find(
+            (v) => v.key === 'row_count',
+          ).value,
+          // id: collectionInfo.collectionId
+        });
+      }
+    }
+    return data;
+  }
+
+  async createCollection(data: CreateCollectionReq) {
+    try {
+      const res = await this.milvusClient.createCollection(data);
+      throwErrorFromSDK(res);
+      return res;
+    } catch (error) {
+      throw new Error(error);
+    }
+  }
+
+  async describeCollection(data: DescribeCollectionReq) {
+    const res = await this.milvusClient.describeCollection(data);
+    throwErrorFromSDK(res.status);
+    return res;
+  }
+
+  async dropCollection(data: DropCollectionReq) {
+    const res = await this.milvusClient.dropCollection(data);
+    throwErrorFromSDK(res);
+    return res;
+  }
+
+  async getCollectionStatistics(data: GetCollectionStatisticsReq) {
+    const res = await this.milvusClient.getCollectionStatistics(data);
+    throwErrorFromSDK(res.status);
+    return res;
   }
 }

+ 28 - 0
server/src/collections/dto.ts

@@ -0,0 +1,28 @@
+import {
+  IsNotEmpty,
+  IsString,
+  IsBoolean,
+  IsOptional,
+  IsArray,
+  ArrayNotEmpty,
+} from 'class-validator';
+import { FieldType } from '@zilliz/milvus-sdk-node-dev/dist/milvus/types/Collection'; // todo: need improve like export types in root file.
+
+export class CreateCollection {
+  @IsString()
+  @IsNotEmpty({
+    message: 'collection_name is empty',
+  })
+  readonly collection_name: string;
+
+  @IsBoolean()
+  @IsOptional()
+  readonly autoID: boolean;
+
+  @IsArray()
+  @ArrayNotEmpty()
+  @IsNotEmpty({
+    message: 'fields is empty',
+  })
+  readonly fields: FieldType[];
+}

+ 8 - 24
server/src/interceptors/index.ts

@@ -5,13 +5,12 @@ import {
   CallHandler,
   HttpStatus,
   BadRequestException,
-  NotFoundException,
 } from '@nestjs/common';
 import { map, catchError } from 'rxjs/operators';
 import { Observable, throwError } from 'rxjs';
 
 export interface Response<T> {
-  code: number;
+  statusCode: number;
   data: T;
 }
 
@@ -26,7 +25,9 @@ export class TransformResInterceptor<T>
     context: ExecutionContext,
     next: CallHandler,
   ): Observable<Response<T>> {
-    return next.handle().pipe(map((data) => ({ code: HttpStatus.OK, data })));
+    return next
+      .handle()
+      .pipe(map((data) => ({ statusCode: HttpStatus.OK, data })));
   }
 }
 
@@ -39,28 +40,11 @@ export class ErrorInterceptor implements NestInterceptor {
   intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
     return next.handle().pipe(
       catchError((err) => {
-        console.error(err);
-
-        if (err.isAxiosError && err.response) {
-          const errContent = err.response.data || 'Bad Request';
-          // from milvus http service
-          const status = err.response.status || 400;
-
-          // operationId is milvus operation id, client need it in response
-          err.operationId &&
-            errContent instanceof Object &&
-            (errContent.operationId = err.operationId);
-          switch (status) {
-            case 400:
-              return throwError(new BadRequestException(errContent));
-            case 404:
-              return throwError(new NotFoundException('Not Found Api'));
-            default:
-              return throwError(new BadRequestException(errContent));
-          }
+        console.error('---error interceptor---', err.response);
+        if (err.response) {
+          return throwError(err);
         }
-
-        return throwError(err);
+        return throwError(new BadRequestException(err.toString()));
       }),
     );
   }

+ 8 - 0
server/src/milvus/dto.ts

@@ -7,3 +7,11 @@ export class ConnectMilvus {
   })
   readonly address: string;
 }
+
+export class CheckMilvus {
+  @IsString()
+  @IsNotEmpty({
+    message: 'address is empty',
+  })
+  readonly address: string;
+}

+ 7 - 13
server/src/milvus/milvus.controller.ts

@@ -1,25 +1,19 @@
-import {
-  Body,
-  Controller,
-  Post,
-  UseGuards,
-  UseInterceptors,
-  UsePipes,
-} from '@nestjs/common';
-import { ErrorInterceptor } from 'src/interceptors';
+import { Body, Controller, Get, Post, Query, UsePipes } from '@nestjs/common';
 import { ValidationPipe } from 'src/pipe/validation.pipe';
-import { ConnectMilvus } from './dto';
+import { CheckMilvus, ConnectMilvus } from './dto';
 import { MilvusService } from './milvus.service';
-import { AuthGuard } from '@nestjs/passport';
 @Controller('milvus')
 export class MilvusController {
   constructor(private milvusService: MilvusService) {}
 
-  @UseGuards(AuthGuard('jwt'))
   @Post('connect')
   @UsePipes(new ValidationPipe())
-  @UseInterceptors(new ErrorInterceptor())
   async connect(@Body() body: ConnectMilvus): Promise<any> {
     return await this.milvusService.connectMilvus(body.address);
   }
+
+  @Get('check')
+  async checkConnect(@Query() query: CheckMilvus): Promise<any> {
+    return await this.milvusService.checkConnect(query.address);
+  }
 }

+ 25 - 4
server/src/milvus/milvus.service.ts

@@ -1,19 +1,40 @@
 import { Injectable } from '@nestjs/common';
-
+import { MilvusNode } from '@zilliz/milvus-sdk-node-dev';
 @Injectable()
 export class MilvusService {
   private milvusAddress: string;
+  private milvusClient: MilvusNode;
 
   constructor() {
     this.milvusAddress = '';
+    // todo: this is easy for test. need delete it before publish
+    this.milvusClient = new MilvusNode('127.0.0.1:19530');
   }
 
   get milvusAddressGetter() {
     return this.milvusAddress;
   }
 
-  connectMilvus(address: string) {
-    this.milvusAddress = address;
-    return { address: this.milvusAddress };
+  get milvusClientGetter() {
+    return this.milvusClient;
+  }
+
+  async connectMilvus(address: string) {
+    try {
+      this.milvusClient = new MilvusNode(address);
+      this.milvusAddress = address;
+      await this.milvusClient.hasCollection({
+        collection_name: 'not_exist',
+      });
+      return { address: this.milvusAddress };
+    } catch (error) {
+      throw new Error('Connect milvus failed, check your milvus address.');
+    }
+  }
+
+  async checkConnect(address: string) {
+    return {
+      connected: this.milvusAddress ? this.milvusAddress === address : false,
+    };
   }
 }

+ 10 - 0
server/src/utils/Error.ts

@@ -0,0 +1,10 @@
+import {
+  ErrorCode,
+  ResStatus,
+} from '@zilliz/milvus-sdk-node-dev/dist/milvus/types/Response';
+
+export const throwErrorFromSDK = (res: ResStatus) => {
+  if (res.error_code !== ErrorCode.SUCCESS) {
+    throw res.reason;
+  }
+};

+ 157 - 2
server/yarn.lock

@@ -370,6 +370,24 @@
     minimatch "^3.0.4"
     strip-json-comments "^3.1.1"
 
+"@grpc/grpc-js@^1.2.12":
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.3.2.tgz#eae97e6daf5abd49a7818aadeca0744dfb1ebca1"
+  integrity sha512-UXepkOKCATJrhHGsxt+CGfpZy9zUn1q9mop5kfcXq1fBkTePxVNPOdnISlCbJFlCtld+pSLGyZCzr9/zVprFKA==
+  dependencies:
+    "@types/node" ">=12.12.47"
+
+"@grpc/proto-loader@^0.6.0":
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.2.tgz#412575f3ff5ef0a9b79d4ea12c08cba5601041cb"
+  integrity sha512-q2Qle60Ht2OQBCp9S5hv1JbI4uBBq6/mqSevFNK3ZEgRDBCAkWqZPUhD/K9gXOHrHKluliHiVq2L9sw1mVyAIg==
+  dependencies:
+    "@types/long" "^4.0.1"
+    lodash.camelcase "^4.3.0"
+    long "^4.0.0"
+    protobufjs "^6.10.0"
+    yargs "^16.1.1"
+
 "@istanbuljs/load-nyc-config@^1.0.0":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@@ -687,6 +705,59 @@
     consola "^2.15.0"
     node-fetch "^2.6.1"
 
+"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
+  integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
+
+"@protobufjs/base64@^1.1.2":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
+  integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
+
+"@protobufjs/codegen@^2.0.4":
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
+  integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
+
+"@protobufjs/eventemitter@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
+  integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
+
+"@protobufjs/fetch@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
+  integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
+  dependencies:
+    "@protobufjs/aspromise" "^1.1.1"
+    "@protobufjs/inquire" "^1.1.0"
+
+"@protobufjs/float@^1.0.2":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
+  integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
+
+"@protobufjs/inquire@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
+  integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
+
+"@protobufjs/path@^1.1.2":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
+  integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
+
+"@protobufjs/pool@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
+  integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
+
+"@protobufjs/utf8@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
+  integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
+
 "@schematics/schematics@0.1102.6":
   version "0.1102.6"
   resolved "https://registry.yarnpkg.com/@schematics/schematics/-/schematics-0.1102.6.tgz#2ce02f7c11558471628eafeb34faaa7f5ab4b22c"
@@ -870,6 +941,11 @@
   dependencies:
     "@types/node" "*"
 
+"@types/long@^4.0.1":
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
+  integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
+
 "@types/mime@^1":
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
@@ -880,6 +956,11 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.1.tgz#9b60797dee1895383a725f828a869c86c6caa5c2"
   integrity sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==
 
+"@types/node@>=12.12.47", "@types/node@>=13.7.0":
+  version "15.12.2"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d"
+  integrity sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==
+
 "@types/node@^14.14.36":
   version "14.17.2"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.2.tgz#1e94476db57ec93a372c7f7d29aa5707cfb92339"
@@ -1189,6 +1270,15 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
+"@zilliz/milvus-sdk-node-dev@^0.1.0":
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/@zilliz/milvus-sdk-node-dev/-/milvus-sdk-node-dev-0.1.0.tgz#eed13482cdb6bf275238c8473d25ff435bd78060"
+  integrity sha512-Sq9XLQsoNMK01po3bahnbIbn4P7t8Psu0oJz78ZVBaAu21KWQ+UL3JiismUorCR17hKzkJaew6PwC5eWZSWG0w==
+  dependencies:
+    "@grpc/grpc-js" "^1.2.12"
+    "@grpc/proto-loader" "^0.6.0"
+    protobufjs "^6.11.2"
+
 abab@^2.0.3, abab@^2.0.5:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
@@ -1779,6 +1869,15 @@ cliui@^6.0.0:
     strip-ansi "^6.0.0"
     wrap-ansi "^6.2.0"
 
+cliui@^7.0.2:
+  version "7.0.4"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+  integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
+  dependencies:
+    string-width "^4.2.0"
+    strip-ansi "^6.0.0"
+    wrap-ansi "^7.0.0"
+
 clone@^1.0.2:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
@@ -2737,7 +2836,7 @@ gensync@^1.0.0-beta.2:
   resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
   integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
 
-get-caller-file@^2.0.1:
+get-caller-file@^2.0.1, get-caller-file@^2.0.5:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
   integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
@@ -3892,6 +3991,11 @@ locate-path@^5.0.0:
   dependencies:
     p-locate "^4.1.0"
 
+lodash.camelcase@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+  integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
+
 lodash.clonedeep@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
@@ -3960,6 +4064,11 @@ log-symbols@^4.0.0, log-symbols@^4.1.0:
     chalk "^4.1.0"
     is-unicode-supported "^0.1.0"
 
+long@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
+  integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
+
 lru-cache@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -4642,6 +4751,25 @@ prompts@^2.0.1:
     kleur "^3.0.3"
     sisteransi "^1.0.5"
 
+protobufjs@^6.10.0, protobufjs@^6.11.2:
+  version "6.11.2"
+  resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
+  integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
+  dependencies:
+    "@protobufjs/aspromise" "^1.1.2"
+    "@protobufjs/base64" "^1.1.2"
+    "@protobufjs/codegen" "^2.0.4"
+    "@protobufjs/eventemitter" "^1.1.0"
+    "@protobufjs/fetch" "^1.1.0"
+    "@protobufjs/float" "^1.0.2"
+    "@protobufjs/inquire" "^1.1.0"
+    "@protobufjs/path" "^1.1.2"
+    "@protobufjs/pool" "^1.1.0"
+    "@protobufjs/utf8" "^1.1.0"
+    "@types/long" "^4.0.1"
+    "@types/node" ">=13.7.0"
+    long "^4.0.0"
+
 proxy-addr@~2.0.5:
   version "2.0.7"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
@@ -5951,6 +6079,15 @@ wrap-ansi@^6.2.0:
     string-width "^4.1.0"
     strip-ansi "^6.0.0"
 
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
 wrappy@1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
@@ -5991,6 +6128,11 @@ y18n@^4.0.0:
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
   integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
 
+y18n@^5.0.5:
+  version "5.0.8"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+  integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
 yallist@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
@@ -6001,7 +6143,7 @@ yaml@^1.7.2:
   resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
   integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
 
-yargs-parser@20.x:
+yargs-parser@20.x, yargs-parser@^20.2.2:
   version "20.2.7"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
   integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
@@ -6031,6 +6173,19 @@ yargs@^15.4.1:
     y18n "^4.0.0"
     yargs-parser "^18.1.2"
 
+yargs@^16.1.1:
+  version "16.2.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+  integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
+  dependencies:
+    cliui "^7.0.2"
+    escalade "^3.1.1"
+    get-caller-file "^2.0.5"
+    require-directory "^2.1.1"
+    string-width "^4.2.0"
+    y18n "^5.0.5"
+    yargs-parser "^20.2.2"
+
 yn@3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"