From 59738f88c299665fe4e239d3d8d25edad8ee5eb9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 5 Feb 2025 14:50:24 -0500 Subject: [PATCH] collab: Store features provided by extensions in the database (#24303) This PR adds new columns to the `extension_versions` table to record which features an extension provides. These `provides_*` columns are populated from the `provides` field on the extension manifest. We'll be able to leverage this data in the future for showing what an extension provides in the extensions UI, as well as allowing to filter by extensions that provide a certain feature. Release Notes: - N/A --- .../20221109000000_test_schema.sql | 9 ++++ ..._provides_fields_to_extension_versions.sql | 10 ++++ crates/collab/src/api/extensions.rs | 1 + crates/collab/src/db.rs | 4 +- crates/collab/src/db/queries/extensions.rs | 38 ++++++++++++- .../collab/src/db/tables/extension_version.rs | 54 +++++++++++++++++++ crates/collab/src/db/tests/extension_tests.rs | 28 +++++++++- 7 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 crates/collab/migrations/20250205192813_add_provides_fields_to_extension_versions.sql diff --git a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql index 185bd45cd3..dbd63cf679 100644 --- a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql +++ b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql @@ -401,6 +401,15 @@ CREATE TABLE extension_versions ( schema_version INTEGER NOT NULL DEFAULT 0, wasm_api_version TEXT, download_count INTEGER NOT NULL DEFAULT 0, + provides_themes BOOLEAN NOT NULL DEFAULT FALSE, + provides_icon_themes BOOLEAN NOT NULL DEFAULT FALSE, + provides_languages BOOLEAN NOT NULL DEFAULT FALSE, + provides_grammars BOOLEAN NOT NULL DEFAULT FALSE, + provides_language_servers BOOLEAN NOT NULL DEFAULT FALSE, + provides_context_servers BOOLEAN NOT NULL DEFAULT FALSE, + provides_slash_commands BOOLEAN NOT NULL DEFAULT FALSE, + provides_indexed_docs_providers BOOLEAN NOT NULL DEFAULT FALSE, + provides_snippets BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (extension_id, version) ); diff --git a/crates/collab/migrations/20250205192813_add_provides_fields_to_extension_versions.sql b/crates/collab/migrations/20250205192813_add_provides_fields_to_extension_versions.sql new file mode 100644 index 0000000000..50dcb0508f --- /dev/null +++ b/crates/collab/migrations/20250205192813_add_provides_fields_to_extension_versions.sql @@ -0,0 +1,10 @@ +alter table extension_versions +add column provides_themes bool not null default false, +add column provides_icon_themes bool not null default false, +add column provides_languages bool not null default false, +add column provides_grammars bool not null default false, +add column provides_language_servers bool not null default false, +add column provides_context_servers bool not null default false, +add column provides_slash_commands bool not null default false, +add column provides_indexed_docs_providers bool not null default false, +add column provides_snippets bool not null default false; diff --git a/crates/collab/src/api/extensions.rs b/crates/collab/src/api/extensions.rs index deeb0bb56e..e132acaf0b 100644 --- a/crates/collab/src/api/extensions.rs +++ b/crates/collab/src/api/extensions.rs @@ -391,6 +391,7 @@ async fn fetch_extension_manifest( repository: manifest.repository, schema_version: manifest.schema_version.unwrap_or(0), wasm_api_version: manifest.wasm_api_version, + provides: manifest.provides, published_at, }) } diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index 857c54ac99..908e488af6 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -6,10 +6,11 @@ pub mod tests; use crate::{executor::Executor, Error, Result}; use anyhow::anyhow; -use collections::{BTreeMap, HashMap, HashSet}; +use collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use dashmap::DashMap; use futures::StreamExt; use rand::{prelude::StdRng, Rng, SeedableRng}; +use rpc::ExtensionProvides; use rpc::{ proto::{self}, ConnectionId, ExtensionMetadata, @@ -781,6 +782,7 @@ pub struct NewExtensionVersion { pub repository: String, pub schema_version: i32, pub wasm_api_version: Option, + pub provides: BTreeSet, pub published_at: PrimitiveDateTime, } diff --git a/crates/collab/src/db/queries/extensions.rs b/crates/collab/src/db/queries/extensions.rs index 51c6395632..54f47ae45e 100644 --- a/crates/collab/src/db/queries/extensions.rs +++ b/crates/collab/src/db/queries/extensions.rs @@ -1,4 +1,3 @@ -use std::collections::BTreeSet; use std::str::FromStr; use chrono::Utc; @@ -283,6 +282,39 @@ impl Database { description: ActiveValue::Set(version.description.clone()), schema_version: ActiveValue::Set(version.schema_version), wasm_api_version: ActiveValue::Set(version.wasm_api_version.clone()), + provides_themes: ActiveValue::Set( + version.provides.contains(&ExtensionProvides::Themes), + ), + provides_icon_themes: ActiveValue::Set( + version.provides.contains(&ExtensionProvides::IconThemes), + ), + provides_languages: ActiveValue::Set( + version.provides.contains(&ExtensionProvides::Languages), + ), + provides_grammars: ActiveValue::Set( + version.provides.contains(&ExtensionProvides::Grammars), + ), + provides_language_servers: ActiveValue::Set( + version + .provides + .contains(&ExtensionProvides::LanguageServers), + ), + provides_context_servers: ActiveValue::Set( + version + .provides + .contains(&ExtensionProvides::ContextServers), + ), + provides_slash_commands: ActiveValue::Set( + version.provides.contains(&ExtensionProvides::SlashCommands), + ), + provides_indexed_docs_providers: ActiveValue::Set( + version + .provides + .contains(&ExtensionProvides::IndexedDocsProviders), + ), + provides_snippets: ActiveValue::Set( + version.provides.contains(&ExtensionProvides::Snippets), + ), download_count: ActiveValue::NotSet, } })) @@ -357,6 +389,8 @@ fn metadata_from_extension_and_version( extension: extension::Model, version: extension_version::Model, ) -> ExtensionMetadata { + let provides = version.provides(); + ExtensionMetadata { id: extension.external_id.into(), manifest: rpc::ExtensionApiManifest { @@ -371,7 +405,7 @@ fn metadata_from_extension_and_version( repository: version.repository, schema_version: Some(version.schema_version), wasm_api_version: version.wasm_api_version, - provides: BTreeSet::default(), + provides, }, published_at: convert_time_to_chrono(version.published_at), diff --git a/crates/collab/src/db/tables/extension_version.rs b/crates/collab/src/db/tables/extension_version.rs index 60e3e5c7da..8c41c41a65 100644 --- a/crates/collab/src/db/tables/extension_version.rs +++ b/crates/collab/src/db/tables/extension_version.rs @@ -1,4 +1,6 @@ use crate::db::ExtensionId; +use collections::BTreeSet; +use rpc::ExtensionProvides; use sea_orm::entity::prelude::*; use time::PrimitiveDateTime; @@ -16,6 +18,58 @@ pub struct Model { pub schema_version: i32, pub wasm_api_version: Option, pub download_count: i64, + pub provides_themes: bool, + pub provides_icon_themes: bool, + pub provides_languages: bool, + pub provides_grammars: bool, + pub provides_language_servers: bool, + pub provides_context_servers: bool, + pub provides_slash_commands: bool, + pub provides_indexed_docs_providers: bool, + pub provides_snippets: bool, +} + +impl Model { + pub fn provides(&self) -> BTreeSet { + let mut provides = BTreeSet::default(); + if self.provides_themes { + provides.insert(ExtensionProvides::Themes); + } + + if self.provides_icon_themes { + provides.insert(ExtensionProvides::IconThemes); + } + + if self.provides_languages { + provides.insert(ExtensionProvides::Languages); + } + + if self.provides_grammars { + provides.insert(ExtensionProvides::Grammars); + } + + if self.provides_language_servers { + provides.insert(ExtensionProvides::LanguageServers); + } + + if self.provides_context_servers { + provides.insert(ExtensionProvides::ContextServers); + } + + if self.provides_slash_commands { + provides.insert(ExtensionProvides::SlashCommands); + } + + if self.provides_indexed_docs_providers { + provides.insert(ExtensionProvides::IndexedDocsProviders); + } + + if self.provides_snippets { + provides.insert(ExtensionProvides::Snippets); + } + + provides + } } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/collab/src/db/tests/extension_tests.rs b/crates/collab/src/db/tests/extension_tests.rs index 84e53c5cab..f7a5398d3c 100644 --- a/crates/collab/src/db/tests/extension_tests.rs +++ b/crates/collab/src/db/tests/extension_tests.rs @@ -1,6 +1,8 @@ use std::collections::BTreeSet; use std::sync::Arc; +use rpc::ExtensionProvides; + use super::Database; use crate::db::ExtensionVersionConstraints; use crate::{ @@ -39,6 +41,7 @@ async fn test_extensions(db: &Arc) { repository: "ext1/repo".into(), schema_version: 1, wasm_api_version: None, + provides: BTreeSet::default(), published_at: t0, }, NewExtensionVersion { @@ -49,6 +52,7 @@ async fn test_extensions(db: &Arc) { repository: "ext1/repo".into(), schema_version: 1, wasm_api_version: None, + provides: BTreeSet::default(), published_at: t0, }, ], @@ -63,6 +67,7 @@ async fn test_extensions(db: &Arc) { repository: "ext2/repo".into(), schema_version: 0, wasm_api_version: None, + provides: BTreeSet::default(), published_at: t0, }], ), @@ -214,6 +219,7 @@ async fn test_extensions(db: &Arc) { repository: "ext1/repo".into(), schema_version: 1, wasm_api_version: None, + provides: BTreeSet::default(), published_at: t0, }], ), @@ -227,6 +233,7 @@ async fn test_extensions(db: &Arc) { repository: "ext2/repo".into(), schema_version: 0, wasm_api_version: None, + provides: BTreeSet::default(), published_at: t0, }], ), @@ -320,6 +327,10 @@ async fn test_extensions_by_id(db: &Arc) { repository: "ext1/repo".into(), schema_version: 1, wasm_api_version: Some("0.0.4".into()), + provides: BTreeSet::from_iter([ + ExtensionProvides::Grammars, + ExtensionProvides::Languages, + ]), published_at: t0, }, NewExtensionVersion { @@ -330,6 +341,11 @@ async fn test_extensions_by_id(db: &Arc) { repository: "ext1/repo".into(), schema_version: 1, wasm_api_version: Some("0.0.4".into()), + provides: BTreeSet::from_iter([ + ExtensionProvides::Grammars, + ExtensionProvides::Languages, + ExtensionProvides::LanguageServers, + ]), published_at: t0, }, NewExtensionVersion { @@ -340,6 +356,11 @@ async fn test_extensions_by_id(db: &Arc) { repository: "ext1/repo".into(), schema_version: 1, wasm_api_version: Some("0.0.5".into()), + provides: BTreeSet::from_iter([ + ExtensionProvides::Grammars, + ExtensionProvides::Languages, + ExtensionProvides::LanguageServers, + ]), published_at: t0, }, ], @@ -354,6 +375,7 @@ async fn test_extensions_by_id(db: &Arc) { repository: "ext2/repo".into(), schema_version: 0, wasm_api_version: None, + provides: BTreeSet::default(), published_at: t0, }], ), @@ -387,7 +409,11 @@ async fn test_extensions_by_id(db: &Arc) { repository: "ext1/repo".into(), schema_version: Some(1), wasm_api_version: Some("0.0.4".into()), - provides: BTreeSet::default(), + provides: BTreeSet::from_iter([ + ExtensionProvides::Grammars, + ExtensionProvides::Languages, + ExtensionProvides::LanguageServers, + ]), }, published_at: t0_chrono, download_count: 0,