Skip to content

Commit d8947cd

Browse files
authored
feat(link): add proto_paths support (#3222)
1 parent 76fc565 commit d8947cd

File tree

7 files changed

+73
-1
lines changed

7 files changed

+73
-1
lines changed

generated/.tailcallrc.schema.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@
269269
"meta": {
270270
"description": "Additional metadata pertaining to the linked resource."
271271
},
272+
"proto_paths": {
273+
"description": "The proto paths to be used when resolving dependencies. Only valid when [`Link::type_of`] is [`LinkType::Protobuf`]",
274+
"type": [
275+
"array",
276+
"null"
277+
],
278+
"items": {
279+
"type": "string"
280+
}
281+
},
272282
"src": {
273283
"description": "The source of the link. It can be a URL or a path to a file. If a path is provided, it is relative to the file that imports the link.",
274284
"type": "string"

src/core/config/directives/link.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,9 @@ pub struct Link {
9393
/// Additional metadata pertaining to the linked resource.
9494
#[serde(default, skip_serializing_if = "is_default")]
9595
pub meta: Option<serde_json::Value>,
96+
///
97+
/// The proto paths to be used when resolving dependencies.
98+
/// Only valid when [`Link::type_of`] is [`LinkType::Protobuf`]
99+
#[serde(default, skip_serializing_if = "is_default")]
100+
pub proto_paths: Option<Vec<String>>,
96101
}

src/core/config/reader.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ impl ConfigReader {
7979
});
8080
}
8181
LinkType::Protobuf => {
82-
let meta = self.proto_reader.read(path, None).await?;
82+
let proto_paths = link.proto_paths.as_ref().map(|paths| {
83+
paths
84+
.iter()
85+
.map(|p| Self::resolve_path(p, parent_dir))
86+
.collect::<Vec<_>>()
87+
});
88+
let meta = self.proto_reader.read(path, proto_paths.as_deref()).await?;
8389
extensions.add_proto(meta);
8490
}
8591
LinkType::Script => {

src/core/generator/generator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ impl Generator {
9999
type_of: LinkType::Protobuf,
100100
headers: None,
101101
meta: None,
102+
proto_paths: None,
102103
});
103104
Ok(config)
104105
}

src/core/grpc/data_loader_request.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ mod tests {
7474
type_of: LinkType::Protobuf,
7575
headers: None,
7676
meta: None,
77+
proto_paths: None,
7778
}]);
7879
let method = GrpcMethod {
7980
package: "greetings".to_string(),

src/core/grpc/protobuf.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,18 @@ pub mod tests {
254254
use crate::core::config::{Config, Field, Grpc, Link, LinkType, Resolver, Type};
255255

256256
pub async fn get_proto_file(path: &str) -> Result<FileDescriptorSet> {
257+
get_proto_file_with_config(path, LinkConfig::default()).await
258+
}
259+
260+
#[derive(Default)]
261+
pub struct LinkConfig {
262+
proto_paths: Option<Vec<String>>,
263+
}
264+
265+
pub async fn get_proto_file_with_config(
266+
path: &str,
267+
link_config: LinkConfig,
268+
) -> Result<FileDescriptorSet> {
257269
let runtime = crate::core::runtime::test::init(None);
258270
let reader = ConfigReader::init(runtime);
259271

@@ -268,6 +280,7 @@ pub mod tests {
268280
type_of: LinkType::Protobuf,
269281
headers: None,
270282
meta: None,
283+
proto_paths: link_config.proto_paths,
271284
}]);
272285

273286
let method = GrpcMethod { package: id, service: "a".to_owned(), name: "b".to_owned() };
@@ -395,6 +408,41 @@ pub mod tests {
395408
Ok(())
396409
}
397410

411+
#[tokio::test]
412+
async fn news_proto_file_with_proto_paths() -> Result<()> {
413+
let grpc_method = GrpcMethod::try_from("news.NewsService.GetNews").unwrap();
414+
415+
let path: &str = protobuf::NEWS_PROTO_PATHS;
416+
let proto_paths = Some(vec![Path::new(path)
417+
.ancestors()
418+
.nth(2)
419+
.unwrap()
420+
.to_string_lossy()
421+
.to_string()]);
422+
let file = ProtobufSet::from_proto_file(
423+
get_proto_file_with_config(path, LinkConfig { proto_paths }).await?,
424+
)?;
425+
let service = file.find_service(&grpc_method)?;
426+
let operation = service.find_operation(&grpc_method)?;
427+
428+
let input = operation.convert_input(r#"{ "id": 1 }"#)?;
429+
430+
assert_eq!(input, b"\0\0\0\0\x02\x08\x01");
431+
432+
let output = b"\0\0\0\x005\x08\x01\x12\x06Note 1\x1a\tContent 1\"\x0cPost image 1";
433+
434+
let parsed = operation.convert_output::<serde_json::Value>(output)?;
435+
436+
assert_eq!(
437+
serde_json::to_value(parsed)?,
438+
json!({
439+
"id": 1, "title": "Note 1", "body": "Content 1", "postImage": "Post image 1", "status": "PUBLISHED"
440+
})
441+
);
442+
443+
Ok(())
444+
}
445+
398446
#[tokio::test]
399447
async fn oneof_proto_file() -> Result<()> {
400448
let grpc_method = GrpcMethod::try_from("oneof.OneOfService.GetOneOf").unwrap();

src/core/grpc/request_template.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ mod tests {
160160
type_of: LinkType::Protobuf,
161161
headers: None,
162162
meta: None,
163+
proto_paths: None,
163164
}]);
164165
let method = GrpcMethod {
165166
package: id.to_string(),

0 commit comments

Comments
 (0)