Move extension API DTOs into `cloud_api_types` (#48689)

Marshall Bowers created

This PR moves the DTOs for the extension API from the `rpc` crate into
the `cloud_api_types` crate.

Release Notes:

- N/A

Change summary

Cargo.lock                                                  |  7 +
crates/cloud_api_types/Cargo.toml                           |  1 
crates/cloud_api_types/src/cloud_api_types.rs               |  2 
crates/cloud_api_types/src/extension.rs                     |  0 
crates/collab/Cargo.toml                                    |  1 
crates/collab/src/api/extensions.rs                         |  2 
crates/collab/src/db.rs                                     |  4 
crates/collab/src/db/queries/extensions.rs                  |  2 
crates/collab/src/db/tables/extension_version.rs            |  2 
crates/collab/tests/integration/db_tests/extension_tests.rs | 24 +++---
crates/extension_cli/Cargo.toml                             |  2 
crates/extension_cli/src/main.rs                            |  4 
crates/extension_host/Cargo.toml                            |  1 
crates/extension_host/src/extension_host.rs                 |  4 
crates/extensions_ui/Cargo.toml                             |  1 
crates/extensions_ui/src/extension_version_selector.rs      |  2 
crates/extensions_ui/src/extensions_ui.rs                   |  3 
crates/rpc/Cargo.toml                                       |  1 
crates/rpc/src/rpc.rs                                       |  2 
19 files changed, 36 insertions(+), 29 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -3174,6 +3174,7 @@ dependencies = [
  "pretty_assertions",
  "serde",
  "serde_json",
+ "strum 0.27.2",
 ]
 
 [[package]]
@@ -3335,6 +3336,7 @@ dependencies = [
  "chrono",
  "client",
  "clock",
+ "cloud_api_types",
  "collab",
  "collab_ui",
  "collections",
@@ -6056,6 +6058,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "clap",
+ "cloud_api_types",
  "env_logger 0.11.8",
  "extension",
  "fs",
@@ -6063,7 +6066,6 @@ dependencies = [
  "language",
  "log",
  "reqwest_client",
- "rpc",
  "serde",
  "serde_json",
  "serde_json_lenient",
@@ -6084,6 +6086,7 @@ dependencies = [
  "async-tar",
  "async-trait",
  "client",
+ "cloud_api_types",
  "collections",
  "criterion",
  "ctor",
@@ -6134,6 +6137,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "client",
+ "cloud_api_types",
  "collections",
  "db",
  "editor",
@@ -14161,7 +14165,6 @@ dependencies = [
  "anyhow",
  "async-tungstenite",
  "base64 0.22.1",
- "chrono",
  "collections",
  "futures 0.3.31",
  "gpui",

crates/cloud_api_types/Cargo.toml 🔗

@@ -17,6 +17,7 @@ chrono.workspace = true
 ciborium.workspace = true
 cloud_llm_client.workspace = true
 serde.workspace = true
+strum.workspace = true
 
 [dev-dependencies]
 pretty_assertions.workspace = true

crates/cloud_api_types/src/cloud_api_types.rs 🔗

@@ -1,3 +1,4 @@
+mod extension;
 mod known_or_unknown;
 mod plan;
 mod timestamp;
@@ -5,6 +6,7 @@ pub mod websocket_protocol;
 
 use serde::{Deserialize, Serialize};
 
+pub use crate::extension::*;
 pub use crate::known_or_unknown::*;
 pub use crate::plan::*;
 pub use crate::timestamp::Timestamp;

crates/collab/Cargo.toml 🔗

@@ -37,6 +37,7 @@ axum-extra = { version = "0.4", features = ["erased-json"] }
 base64.workspace = true
 chrono.workspace = true
 clock.workspace = true
+cloud_api_types.workspace = true
 collections.workspace = true
 dashmap.workspace = true
 envy = "0.4.2"

crates/collab/src/api/extensions.rs 🔗

@@ -9,8 +9,8 @@ use axum::{
     response::Redirect,
     routing::get,
 };
+use cloud_api_types::{ExtensionApiManifest, ExtensionProvides, GetExtensionsResponse};
 use collections::{BTreeSet, HashMap};
-use rpc::{ExtensionApiManifest, ExtensionProvides, GetExtensionsResponse};
 use semver::Version as SemanticVersion;
 use serde::Deserialize;
 use std::str::FromStr;

crates/collab/src/db.rs 🔗

@@ -4,13 +4,13 @@ mod tables;
 
 use crate::{Error, Result};
 use anyhow::{Context as _, anyhow};
+use cloud_api_types::{ExtensionMetadata, ExtensionProvides};
 use collections::{BTreeMap, BTreeSet, HashMap, HashSet};
 use dashmap::DashMap;
 use futures::StreamExt;
 use project_repository_statuses::StatusKind;
-use rpc::ExtensionProvides;
 use rpc::{
-    ConnectionId, ExtensionMetadata,
+    ConnectionId,
     proto::{self},
 };
 use sea_orm::{

crates/collab/src/db/queries/extensions.rs 🔗

@@ -455,7 +455,7 @@ fn metadata_from_extension_and_version(
 
     ExtensionMetadata {
         id: extension.external_id.into(),
-        manifest: rpc::ExtensionApiManifest {
+        manifest: cloud_api_types::ExtensionApiManifest {
             name: extension.name,
             version: version.version.into(),
             authors: version

crates/collab/tests/integration/db_tests/extension_tests.rs 🔗

@@ -1,13 +1,13 @@
 use std::collections::BTreeSet;
 use std::sync::Arc;
 
-use rpc::ExtensionProvides;
-
-use crate::test_both_dbs;
+use cloud_api_types::{ExtensionMetadata, ExtensionProvides};
 use collab::db::Database;
 use collab::db::ExtensionVersionConstraints;
 use collab::db::{NewExtensionVersion, queries::extensions::convert_time_to_chrono};
-use rpc::ExtensionMetadata;
+
+use crate::test_both_dbs;
+
 test_both_dbs!(
     test_extensions,
     test_extensions_postgres,
@@ -160,7 +160,7 @@ async fn test_extensions(db: &Arc<Database>) {
         &[
             ExtensionMetadata {
                 id: "ext1".into(),
-                manifest: rpc::ExtensionApiManifest {
+                manifest: cloud_api_types::ExtensionApiManifest {
                     name: "Extension One".into(),
                     version: "0.0.2".into(),
                     authors: vec!["max".into(), "marshall".into()],
@@ -175,7 +175,7 @@ async fn test_extensions(db: &Arc<Database>) {
             },
             ExtensionMetadata {
                 id: "ext2".into(),
-                manifest: rpc::ExtensionApiManifest {
+                manifest: cloud_api_types::ExtensionApiManifest {
                     name: "Extension Two".into(),
                     version: "0.2.0".into(),
                     authors: vec!["marshall".into()],
@@ -197,7 +197,7 @@ async fn test_extensions(db: &Arc<Database>) {
         extensions,
         &[ExtensionMetadata {
             id: "ext2".into(),
-            manifest: rpc::ExtensionApiManifest {
+            manifest: cloud_api_types::ExtensionApiManifest {
                 name: "Extension Two".into(),
                 version: "0.2.0".into(),
                 authors: vec!["marshall".into()],
@@ -239,7 +239,7 @@ async fn test_extensions(db: &Arc<Database>) {
         &[
             ExtensionMetadata {
                 id: "ext2".into(),
-                manifest: rpc::ExtensionApiManifest {
+                manifest: cloud_api_types::ExtensionApiManifest {
                     name: "Extension Two".into(),
                     version: "0.2.0".into(),
                     authors: vec!["marshall".into()],
@@ -254,7 +254,7 @@ async fn test_extensions(db: &Arc<Database>) {
             },
             ExtensionMetadata {
                 id: "ext1".into(),
-                manifest: rpc::ExtensionApiManifest {
+                manifest: cloud_api_types::ExtensionApiManifest {
                     name: "Extension One".into(),
                     version: "0.0.2".into(),
                     authors: vec!["max".into(), "marshall".into()],
@@ -329,7 +329,7 @@ async fn test_extensions(db: &Arc<Database>) {
         &[
             ExtensionMetadata {
                 id: "ext2".into(),
-                manifest: rpc::ExtensionApiManifest {
+                manifest: cloud_api_types::ExtensionApiManifest {
                     name: "Extension Two".into(),
                     version: "0.2.0".into(),
                     authors: vec!["marshall".into()],
@@ -344,7 +344,7 @@ async fn test_extensions(db: &Arc<Database>) {
             },
             ExtensionMetadata {
                 id: "ext1".into(),
-                manifest: rpc::ExtensionApiManifest {
+                manifest: cloud_api_types::ExtensionApiManifest {
                     name: "Extension One".into(),
                     version: "0.0.3".into(),
                     authors: vec!["max".into(), "marshall".into()],
@@ -466,7 +466,7 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
         extensions,
         &[ExtensionMetadata {
             id: "ext1".into(),
-            manifest: rpc::ExtensionApiManifest {
+            manifest: cloud_api_types::ExtensionApiManifest {
                 name: "Extension 1".into(),
                 version: "0.0.2".into(),
                 authors: vec!["max".into()],

crates/extension_cli/Cargo.toml 🔗

@@ -15,6 +15,7 @@ path = "src/main.rs"
 [dependencies]
 anyhow.workspace = true
 clap = { workspace = true, features = ["derive"] }
+cloud_api_types.workspace = true
 env_logger.workspace = true
 extension.workspace = true
 fs.workspace = true
@@ -22,7 +23,6 @@ gpui.workspace = true
 language.workspace = true
 log.workspace = true
 reqwest_client.workspace = true
-rpc.workspace = true
 serde.workspace = true
 serde_json.workspace = true
 serde_json_lenient.workspace = true

crates/extension_cli/src/main.rs 🔗

@@ -7,11 +7,11 @@ use std::sync::Arc;
 use ::fs::{CopyOptions, Fs, RealFs, copy_recursive};
 use anyhow::{Context as _, Result, anyhow, bail};
 use clap::Parser;
+use cloud_api_types::ExtensionProvides;
 use extension::extension_builder::{CompileExtensionOptions, ExtensionBuilder};
 use extension::{ExtensionManifest, ExtensionSnippets};
 use language::LanguageConfig;
 use reqwest_client::ReqwestClient;
-use rpc::ExtensionProvides;
 use snippet_provider::file_to_snippets;
 use snippet_provider::format::VsSnippetsFile;
 use tokio::process::Command;
@@ -108,7 +108,7 @@ async fn main() -> Result<()> {
         );
     }
 
-    let manifest_json = serde_json::to_string(&rpc::ExtensionApiManifest {
+    let manifest_json = serde_json::to_string(&cloud_api_types::ExtensionApiManifest {
         name: manifest.name,
         version: manifest.version,
         description: manifest.description,

crates/extension_host/Cargo.toml 🔗

@@ -21,6 +21,7 @@ async-compression.workspace = true
 async-tar.workspace = true
 async-trait.workspace = true
 client.workspace = true
+cloud_api_types.workspace = true
 collections.workspace = true
 dap.workspace = true
 extension.workspace = true

crates/extension_host/src/extension_host.rs 🔗

@@ -9,8 +9,8 @@ mod extension_store_test;
 use anyhow::{Context as _, Result, anyhow, bail};
 use async_compression::futures::bufread::GzipDecoder;
 use async_tar::Archive;
-use client::ExtensionProvides;
-use client::{Client, ExtensionMetadata, GetExtensionsResponse, proto, telemetry::Telemetry};
+use client::{Client, proto, telemetry::Telemetry};
+use cloud_api_types::{ExtensionMetadata, ExtensionProvides, GetExtensionsResponse};
 use collections::{BTreeMap, BTreeSet, HashSet, btree_map};
 pub use extension::ExtensionManifest;
 use extension::extension_builder::{CompileExtensionOptions, ExtensionBuilder};

crates/extensions_ui/Cargo.toml 🔗

@@ -14,6 +14,7 @@ path = "src/extensions_ui.rs"
 [dependencies]
 anyhow.workspace = true
 client.workspace = true
+cloud_api_types.workspace = true
 collections.workspace = true
 db.workspace = true
 editor.workspace = true

crates/extensions_ui/src/extension_version_selector.rs 🔗

@@ -1,7 +1,7 @@
 use std::str::FromStr;
 use std::sync::Arc;
 
-use client::ExtensionMetadata;
+use cloud_api_types::ExtensionMetadata;
 use extension_host::ExtensionStore;
 use fs::Fs;
 use fuzzy::{StringMatch, StringMatchCandidate, match_strings};

crates/extensions_ui/src/extensions_ui.rs 🔗

@@ -7,7 +7,8 @@ use std::time::Duration;
 use std::{ops::Range, sync::Arc};
 
 use anyhow::Context as _;
-use client::{ExtensionMetadata, ExtensionProvides, zed_urls};
+use client::zed_urls;
+use cloud_api_types::{ExtensionMetadata, ExtensionProvides};
 use collections::{BTreeMap, BTreeSet};
 use editor::{Editor, EditorElement, EditorStyle};
 use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};

crates/rpc/Cargo.toml 🔗

@@ -21,7 +21,6 @@ test-support = ["collections/test-support", "gpui/test-support", "proto/test-sup
 anyhow.workspace = true
 async-tungstenite.workspace = true
 base64.workspace = true
-chrono.workspace = true
 collections.workspace = true
 futures.workspace = true
 gpui = { workspace = true, optional = true }

crates/rpc/src/rpc.rs 🔗

@@ -1,12 +1,10 @@
 pub mod auth;
 mod conn;
-mod extension;
 mod message_stream;
 mod notification;
 mod peer;
 
 pub use conn::Connection;
-pub use extension::*;
 pub use notification::*;
 pub use peer::*;
 pub use proto;