Fix regression in names of the template-based projects (#3201)

This commit is contained in:
Ilya Bogdanov 2021-12-24 11:29:06 +03:00 committed by GitHub
parent 895291876c
commit fc953ec055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 185 additions and 117 deletions

View File

@ -233,6 +233,21 @@ impl ReferentName {
Self::validate(name.as_ref()).map(|_| ReferentName(name.into()))
}
/// Convert given string into a referent name.
///
/// First letter of each "word" (underscore-separated segment) will be capitalized. All other
/// letters will be turned into lower case.
///
/// Fails if the given string is empty.
pub fn from_identifier_text(name: impl Str) -> Result<Self, NotReferentName> {
let name = name.as_ref();
if name.is_empty() {
return Err(NotReferentName(name.into()));
}
let name = name.split('_').map(str::to_lowercase).map(capitalize_first).join("_");
Ok(Self(name))
}
/// Get a normalized version of this identifier.
pub fn normalized(&self) -> NormalizedName {
NormalizedName::new(self)
@ -363,3 +378,39 @@ pub fn generate_name(
.unwrap(); // It never yields `None`, as we iterate infinite sequence until we find match.
Identifier::from_text(name)
}
/// Capitalize the first letter of the passed string.
fn capitalize_first(string: String) -> String {
let mut chars = string.chars();
match chars.next() {
None => String::new(),
Some(first_char) => first_char.to_uppercase().to_string() + chars.as_str(),
}
}
// =============
// === Tests ===
// =============
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn referent_name_from_identifier_text() {
let cases = [
("identifier", "Identifier"),
("project_1", "Project_1"),
("muLti_Word_iDenTiFier", "Multi_Word_Identifier"),
];
for (input, expected) in cases {
let referent_name =
ReferentName::from_identifier_text(input).expect("ReferentName creation failed");
assert_eq!(referent_name, expected);
}
assert!(ReferentName::from_identifier_text("").is_err());
}
}

View File

@ -63,7 +63,7 @@ trait API {
#[MethodInput=CreateProjectInput,rpc_name="project/create"]
fn create_project
( &self
, name : String
, name : ProjectName
, project_template : Option<String>
, version : Option<String>
, missing_component_action : MissingComponentAction
@ -71,7 +71,7 @@ trait API {
/// Request project renaming.
#[MethodInput=RenameProject,rpc_name="project/rename"]
fn rename_project(&self, project_id:Uuid, name:String) -> ();
fn rename_project(&self, project_id:Uuid, name:ProjectName) -> ();
/// Request the deletion of a project.
#[MethodInput=DeleteProjectInput,rpc_name="project/delete"]
@ -104,13 +104,15 @@ impl Display for IpWithSocket {
}
/// Project name.
#[derive(Clone, Debug, Deserialize, Display, Eq, From, Hash, PartialEq, Serialize, Shrinkwrap)]
#[shrinkwrap(mutable)]
pub struct ProjectName(pub String);
#[derive(Clone, Debug, Deserialize, Display, Eq, From, Hash, PartialEq, Serialize)]
pub struct ProjectName(String);
impl ProjectName {
/// Create new ProjectName.
pub fn new(name: impl Str) -> Self {
/// Create new ProjectName without any validation.
///
/// The caller is responsible for making sure that provided string is a valid project name
/// (e.g. not empty and starts with a capital letter).
pub fn new_unchecked(name: impl Str) -> Self {
Self(name.into())
}
}
@ -235,13 +237,13 @@ mod mock_client_tests {
engine_version: "0.2.1".to_owned(),
language_server_json_address: language_server_address.clone(),
language_server_binary_address: language_server_address,
project_name: ProjectName::new("Test"),
project_name: ProjectName::new_unchecked("Test"),
project_namespace: "local".to_owned(),
};
let open_result = Ok(expected_open_result.clone());
let missing_component_action = MissingComponentAction::Fail;
expect_call!(mock_client.create_project(
name = "HelloWorld".to_string(),
name = ProjectName::new_unchecked("HelloWorld"),
project_template = None,
version = None,
missing_component_action = missing_component_action
@ -253,7 +255,7 @@ mod mock_client_tests {
let delete_result = mock_client.delete_project(&expected_uuid);
result(delete_result).expect_err("Project shouldn't exist.");
let name = String::from("HelloWorld");
let name = ProjectName::new_unchecked("HelloWorld");
let response = mock_client.create_project(&name, &None, &None, &missing_component_action);
let uuid = result(response).expect("Couldn't create project").project_id;
assert_eq!(uuid, expected_uuid);
@ -276,14 +278,14 @@ mod mock_client_tests {
fn list_projects() {
let mock_client = MockClient::default();
let project1 = ProjectMetadata {
name: ProjectName::new("project1"),
name: ProjectName::new_unchecked("project1"),
id: Uuid::default(),
last_opened: Some(DateTime::parse_from_rfc3339("2020-01-07T21:25:26Z").unwrap()),
engine_version: Some("0.2.21".to_owned()),
namespace: "local".to_owned(),
};
let project2 = ProjectMetadata {
name: ProjectName::new("project2"),
name: ProjectName::new_unchecked("project2"),
id: Uuid::default(),
last_opened: Some(DateTime::parse_from_rfc3339("2020-02-02T13:15:20Z").unwrap()),
engine_version: Some("0.2.22".to_owned()),
@ -291,14 +293,14 @@ mod mock_client_tests {
};
let expected_recent_projects = response::ProjectList { projects: vec![project1, project2] };
let sample1 = ProjectMetadata {
name: ProjectName::new("sample1"),
name: ProjectName::new_unchecked("sample1"),
id: Uuid::default(),
last_opened: Some(DateTime::parse_from_rfc3339("2019-11-23T05:30:12Z").unwrap()),
engine_version: Some("0.2.21".to_owned()),
namespace: "test".to_owned(),
};
let sample2 = ProjectMetadata {
name: ProjectName::new("sample2"),
name: ProjectName::new_unchecked("sample2"),
id: Uuid::default(),
last_opened: Some(DateTime::parse_from_rfc3339("2019-12-25T00:10:58Z").unwrap()),
engine_version: Some("0.2.21".to_owned()),
@ -403,7 +405,7 @@ mod remote_client_tests {
IpWithSocket { host: "localhost".to_string(), port: 27015 };
let language_server_binary_address =
IpWithSocket { host: "localhost".to_string(), port: 27016 };
let project_name = ProjectName::new("Test");
let project_name = ProjectName::new_unchecked("Test");
let project_namespace = "test_ns".to_owned();
let open_result = response::OpenProject {
engine_version,
@ -425,7 +427,7 @@ mod remote_client_tests {
"projectName" : "Test",
"projectNamespace" : "test_ns",
});
let project_name = String::from("HelloWorld");
let project_name = ProjectName::new_unchecked("HelloWorld");
let project_template = Some(String::from("template"));
let project_create_json = json!({
"name" : serde_json::to_value(&project_name).unwrap(),
@ -437,14 +439,14 @@ mod remote_client_tests {
let number_of_projects_json = json!({ "numberOfProjects": number_of_projects });
let num_projects_json = json!({ "numProjects": number_of_projects });
let project1 = ProjectMetadata {
name: ProjectName::new("project1"),
name: ProjectName::new_unchecked("project1"),
id: Uuid::default(),
last_opened: Some(DateTime::parse_from_rfc3339("2020-01-07T21:25:26Z").unwrap()),
engine_version: Some("0.2.21".to_owned()),
namespace: "local".to_owned(),
};
let project2 = ProjectMetadata {
name: ProjectName::new("project2"),
name: ProjectName::new_unchecked("project2"),
id: Uuid::default(),
last_opened: Some(DateTime::parse_from_rfc3339("2020-02-02T13:15:20Z").unwrap()),
engine_version: Some("0.2.22".to_owned()),

View File

@ -10,6 +10,7 @@ use crate::controller::ide::StatusNotificationPublisher;
use crate::controller::ide::API;
use crate::ide::initializer;
use crate::notification;
use double_representation::identifier::ReferentName;
use engine_protocol::project_manager;
use engine_protocol::project_manager::MissingComponentAction;
@ -123,12 +124,11 @@ impl ManagingProjectAPI for Handle {
use model::project::Synchronized as Project;
let list = self.project_manager.list_projects(&None).await?;
let names: HashSet<String> = list.projects.into_iter().map(|p| p.name.into()).collect();
let without_suffix = UNNAMED_PROJECT_NAME.to_owned();
let with_suffix = (1..).map(|i| format!("{}_{}", UNNAMED_PROJECT_NAME, i));
let mut candidates = std::iter::once(without_suffix).chain(with_suffix);
// The iterator have no end, so we can safely unwrap.
let name = candidates.find(|c| !names.contains(c)).unwrap();
let existing_names: HashSet<_> =
list.projects.into_iter().map(|p| p.name.into()).collect();
let name = template.clone().unwrap_or_else(|| UNNAMED_PROJECT_NAME.to_owned());
let name = choose_new_project_name(&existing_names, &name);
let name = ProjectName::new_unchecked(name);
let version = Some(enso_config::engine_version_supported.to_string());
let action = MissingComponentAction::Install;
@ -164,3 +164,15 @@ impl ManagingProjectAPI for Handle {
.boxed_local()
}
}
/// Select a new name for the project in a form of <suggested_name>_N, where N is a unique sequence
/// number.
fn choose_new_project_name(existing_names: &HashSet<String>, suggested_name: &str) -> ReferentName {
let first_candidate = suggested_name.to_owned();
let nth_project_name = |i| iformat!("{suggested_name}_{i}");
let candidates = (1..).map(nth_project_name);
let mut candidates = std::iter::once(first_candidate).chain(candidates);
// The iterator have no end, so we can safely unwrap.
let name = candidates.find(|c| !existing_names.contains(c)).unwrap();
ReferentName::from_identifier_text(name).expect("Empty project name provided")
}

View File

@ -221,7 +221,7 @@ impl WithProjectManager {
use project_manager::MissingComponentAction::Install;
info!(self.logger, "Creating a new project named '{self.project_name}'.");
let version = Some(enso_config::engine_version_supported.to_owned());
let ProjectName(name) = &self.project_name;
let name = &self.project_name;
let response = self.project_manager.create_project(name, &None, &version, &Install);
Ok(response.await?.project_id)
}
@ -280,7 +280,7 @@ mod test {
async fn get_project_or_create_new() {
let logger = Logger::new("test");
let mock_client = project_manager::MockClient::default();
let project_name = ProjectName::new("TestProject");
let project_name = ProjectName::new_unchecked("TestProject");
let project = project_manager::ProjectMetadata {
name: project_name.clone(),
id: uuid::Uuid::new_v4(),

View File

@ -22,6 +22,7 @@ use engine_protocol::language_server::ExpressionUpdates;
use engine_protocol::language_server::MethodPointer;
use engine_protocol::project_manager;
use engine_protocol::project_manager::MissingComponentAction;
use engine_protocol::project_manager::ProjectName;
use flo_stream::Subscriber;
use parser::Parser;
@ -610,7 +611,8 @@ impl model::project::API for Project {
let referent_name = name.as_str().try_into()?;
let project_manager = self.project_manager.as_ref().ok_or(ProjectManagerUnavailable)?;
let project_id = self.properties.borrow().id;
project_manager.rename_project(&project_id, &name).await?;
let project_name = ProjectName::new_unchecked(name);
project_manager.rename_project(&project_id, &project_name).await?;
self.properties.borrow_mut().name.project = referent_name;
Ok(())
}

View File

@ -28,7 +28,7 @@ fn failure_to_open_project_is_reported() {
fixture.run_test(async move {
let project_manager = Rc::new(project_manager::Client::new(transport));
executor::global::spawn(project_manager.runner());
let name = ProjectName(crate::constants::DEFAULT_PROJECT_NAME.to_owned());
let name = ProjectName::new_unchecked(crate::constants::DEFAULT_PROJECT_NAME.to_owned());
let initializer = ide::initializer::WithProjectManager::new(project_manager, name);
let result = initializer.initialize_project_model().await;
result.expect_err("Error should have been reported.");

View File

@ -9,6 +9,7 @@ mod tests {
use enso_gui::transport::web::WebSocket;
use engine_protocol::project_manager::MissingComponentAction::Install;
use engine_protocol::project_manager::ProjectName;
use wasm_bindgen_test::wasm_bindgen_test_configure;
wasm_bindgen_test_configure!(run_in_browser);
@ -25,7 +26,7 @@ mod tests {
executor::global::spawn(client.runner());
let name = "TestProject".to_string();
let name = ProjectName::new_unchecked("TestProject");
let creation = client.create_project(&name, &None, &None, &Install);
let created = creation.await.expect("Couldn't create project.");
let uuid = created.project_id;
@ -33,19 +34,19 @@ mod tests {
client.close_project(&uuid).await.expect("Couldn't close project.");
let list_response = client.list_projects(&None).await;
let list_response = list_response.expect("Couldn't list recent projects.");
assert!(list_response.projects.iter().any(|project| *project.name.deref() == name));
assert!(list_response.projects.iter().any(|project| project.name == name));
let new_name = "NewTestProject".to_string();
let new_name = ProjectName::new_unchecked("NewTestProject");
client.rename_project(&uuid, &new_name).await.expect("Couldn't rename project.");
let list_response = client.list_projects(&None).await;
let list_response = list_response.expect("Couldn't list recent projects.");
assert!(!list_response.projects.iter().any(|project| *project.name.deref() == name));
assert!(list_response.projects.iter().any(|project| *project.name.deref() == new_name));
assert!(!list_response.projects.iter().any(|project| project.name == name));
assert!(list_response.projects.iter().any(|project| project.name == new_name));
client.delete_project(&uuid).await.expect("Couldn't delete project.");
let list_response = client.list_projects(&None).await;
let list_response = list_response.expect("Couldn't list recent projects.");
assert!(!list_response.projects.iter().any(|project| *project.name.deref() == name));
assert!(!list_response.projects.iter().any(|project| project.name == name));
// FIXME[dg]: project/listSample isn't implemented on the server-side yet.
//client.list_samples(10).await.expect("Couldn't list samples.");
}

View File

@ -748,9 +748,9 @@
"integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A=="
},
"node_modules/@grpc/grpc-js": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.4.4.tgz",
"integrity": "sha512-a6222b7Dl6fIlMgzVl7e+NiRoLiZFbpcwvBH2Oli56Bn7W4/3Ld+86hK4ffPn5rx2DlDidmIcvIJiOQXyhv9gA==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.4.5.tgz",
"integrity": "sha512-A6cOzSu7dqXZ7rzvh/9JZf+Jg/MOpLEMP0IdT8pT8hrWJZ6TB4ydN/MRuqOtAugInJe/VQ9F8BPricUpYZSaZA==",
"dependencies": {
"@grpc/proto-loader": "^0.6.4",
"@types/node": ">=12.12.47"
@ -4841,9 +4841,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"node_modules/color-string": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.1.tgz",
"integrity": "sha512-AGfGNQbnXlYqPStIx3QB2XA3Wy8vjbreqklmCiGVwcoHSLN5KIpDZDflYnXlBliKHI8CTBX3PsCgG+xfZgqK8A==",
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
"integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@ -5014,9 +5014,9 @@
}
},
"node_modules/compression-webpack-plugin/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -6441,9 +6441,9 @@
}
},
"node_modules/dom-serializer/node_modules/domhandler": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"dependencies": {
"domelementtype": "^2.2.0"
},
@ -6515,9 +6515,9 @@
}
},
"node_modules/domutils/node_modules/domhandler": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"dependencies": {
"domelementtype": "^2.2.0"
},
@ -6834,28 +6834,28 @@
}
},
"node_modules/electron-builder/node_modules/yargs": {
"version": "17.2.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz",
"integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==",
"version": "17.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
"integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
"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",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/electron-builder/node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"node_modules/electron-is-dev": {
@ -8194,9 +8194,9 @@
}
},
"node_modules/fs-minipass/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -11735,9 +11735,9 @@
}
},
"node_modules/minipass-collect/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -11762,9 +11762,9 @@
}
},
"node_modules/minipass-flush/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -11789,9 +11789,9 @@
}
},
"node_modules/minipass-pipeline/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -11817,9 +11817,9 @@
}
},
"node_modules/minizlib/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -16152,9 +16152,9 @@
}
},
"node_modules/tar/node_modules/minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"dependencies": {
"yallist": "^4.0.0"
},
@ -19384,9 +19384,9 @@
"integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A=="
},
"@grpc/grpc-js": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.4.4.tgz",
"integrity": "sha512-a6222b7Dl6fIlMgzVl7e+NiRoLiZFbpcwvBH2Oli56Bn7W4/3Ld+86hK4ffPn5rx2DlDidmIcvIJiOQXyhv9gA==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.4.5.tgz",
"integrity": "sha512-A6cOzSu7dqXZ7rzvh/9JZf+Jg/MOpLEMP0IdT8pT8hrWJZ6TB4ydN/MRuqOtAugInJe/VQ9F8BPricUpYZSaZA==",
"requires": {
"@grpc/proto-loader": "^0.6.4",
"@types/node": ">=12.12.47"
@ -22745,9 +22745,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.1.tgz",
"integrity": "sha512-AGfGNQbnXlYqPStIx3QB2XA3Wy8vjbreqklmCiGVwcoHSLN5KIpDZDflYnXlBliKHI8CTBX3PsCgG+xfZgqK8A==",
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
"integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@ -22909,9 +22909,9 @@
}
},
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}
@ -24068,9 +24068,9 @@
},
"dependencies": {
"domhandler": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"requires": {
"domelementtype": "^2.2.0"
}
@ -24116,9 +24116,9 @@
},
"dependencies": {
"domhandler": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"requires": {
"domelementtype": "^2.2.0"
}
@ -24367,23 +24367,23 @@
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yargs": {
"version": "17.2.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz",
"integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==",
"version": "17.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
"integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.0.0"
}
},
"yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA=="
}
}
},
@ -25448,9 +25448,9 @@
},
"dependencies": {
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}
@ -28190,9 +28190,9 @@
},
"dependencies": {
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}
@ -28213,9 +28213,9 @@
},
"dependencies": {
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}
@ -28236,9 +28236,9 @@
},
"dependencies": {
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}
@ -28260,9 +28260,9 @@
},
"dependencies": {
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}
@ -31697,9 +31697,9 @@
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
},
"minipass": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"requires": {
"yallist": "^4.0.0"
}