Skip to content

Commit

Permalink
refactor(config): remove explicit interface flag (#1872)
Browse files Browse the repository at this point in the history
  • Loading branch information
meskill authored May 6, 2024
1 parent dd2114d commit 4c4b5ba
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 25 deletions.
4 changes: 0 additions & 4 deletions generated/.tailcallrc.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1247,10 +1247,6 @@
},
"uniqueItems": true
},
"interface": {
"description": "Flag to indicate if the type is an interface.",
"type": "boolean"
},
"protected": {
"description": "Marks field as protected by auth providers",
"default": null,
Expand Down
2 changes: 1 addition & 1 deletion src/blueprint/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ pub fn to_definitions<'a>() -> TryFold<'a, ConfigModule, Vec<Definition>, String
Definition::Object(object_type_definition) => {
if config_module.input_types.contains(name) {
to_input_object_type_definition(object_type_definition).trace(name)
} else if type_.interface {
} else if config_module.interface_types.contains(name) {
to_interface_type_definition(object_type_definition).trace(name)
} else {
Valid::succeed(definition)
Expand Down
23 changes: 15 additions & 8 deletions src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,6 @@ pub struct Type {
pub doc: Option<String>,
#[serde(default, skip_serializing_if = "is_default")]
///
/// Flag to indicate if the type is an interface.
pub interface: bool,
#[serde(default, skip_serializing_if = "is_default")]
///
/// Interfaces that the type implements.
pub implements: BTreeSet<String>,
#[serde(rename = "enum", default, skip_serializing_if = "is_default")]
Expand Down Expand Up @@ -731,9 +727,8 @@ impl Config {
}

for (type_name, type_of) in self.types.iter() {
if (type_of.interface || !type_of.fields.is_empty()) && !input_types.contains(type_name)
{
for (_, field) in type_of.fields.iter() {
if !input_types.contains(type_name) {
for field in type_of.fields.values() {
types.insert(field.type_of.clone());
}
}
Expand All @@ -742,11 +737,23 @@ impl Config {
types
}

/// Returns a list of all the types that are used as interface
pub fn interface_types(&self) -> HashSet<String> {
let mut types = HashSet::new();

for ty in self.types.values() {
for interface in ty.implements.iter() {
types.insert(interface.clone());
}
}

types
}

/// Returns a list of all the arguments in the configuration
fn arguments(&self) -> Vec<(&String, &Arg)> {
self.types
.iter()
.filter(|(_, value)| !value.interface)
.flat_map(|(_, type_of)| type_of.fields.iter())
.flat_map(|(_, field)| field.args.iter())
.collect::<Vec<_>>()
Expand Down
12 changes: 10 additions & 2 deletions src/config/config_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub struct ConfigModule {
pub extensions: Extensions,
pub input_types: HashSet<String>,
pub output_types: HashSet<String>,
pub interface_types: HashSet<String>,
}

#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -202,8 +203,15 @@ impl From<Config> for ConfigModule {
fn from(config: Config) -> Self {
let input_types = config.input_types();
let output_types = config.output_types();

ConfigModule { config, input_types, output_types, ..Default::default() }
let interface_types = config.interface_types();

ConfigModule {
config,
input_types,
output_types,
interface_types,
..Default::default()
}
}
}

Expand Down
9 changes: 0 additions & 9 deletions src/config/from_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ where
{
let fields = object.fields();
let implements = object.implements();
let interface = object.is_interface();

Cache::from_directives(directives.iter())
.fuse(to_fields(fields))
Expand All @@ -224,7 +223,6 @@ where
fields,
added_fields,
doc,
interface,
implements,
cache,
protected,
Expand Down Expand Up @@ -451,7 +449,6 @@ impl Fieldlike for InputValueDefinition {
trait ObjectLike {
fn fields(&self) -> &Vec<Positioned<FieldDefinition>>;
fn implements(&self) -> &Vec<Positioned<Name>>;
fn is_interface(&self) -> bool;
}
impl ObjectLike for ObjectType {
fn fields(&self) -> &Vec<Positioned<FieldDefinition>> {
Expand All @@ -460,9 +457,6 @@ impl ObjectLike for ObjectType {
fn implements(&self) -> &Vec<Positioned<Name>> {
&self.implements
}
fn is_interface(&self) -> bool {
false
}
}
impl ObjectLike for InterfaceType {
fn fields(&self) -> &Vec<Positioned<FieldDefinition>> {
Expand All @@ -471,7 +465,4 @@ impl ObjectLike for InterfaceType {
fn implements(&self) -> &Vec<Positioned<Name>> {
&self.implements
}
fn is_interface(&self) -> bool {
true
}
}
2 changes: 1 addition & 1 deletion src/config/into_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn config_document(config: &ConfigModule) -> ServiceDocument {
};
definitions.push(TypeSystemDefinition::Schema(pos(schema_definition)));
for (type_name, type_def) in config.types.iter() {
let kind = if type_def.interface {
let kind = if config.interface_types.contains(type_name) {
TypeKind::Interface(InterfaceType {
implements: type_def
.implements
Expand Down
32 changes: 32 additions & 0 deletions tests/core/snapshots/test-interface-from-json.md_client.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
source: tests/core/spec.rs
expression: client
---
type B implements IA {
a: String
b: String
}

scalar Date

scalar Email

scalar Empty

interface IA {
a: String
}

scalar JSON

scalar PhoneNumber

type Query {
bar: B
}

scalar Url

schema {
query: Query
}
20 changes: 20 additions & 0 deletions tests/core/snapshots/test-interface-from-json.md_merged.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: tests/core/spec.rs
expression: merged
---
schema @server @upstream(baseURL: "http://jsonplaceholder.typicode.com") {
query: Query
}

interface IA {
a: String
}

type B implements IA {
a: String
b: String
}

type Query {
bar: B @http(path: "/posts")
}
42 changes: 42 additions & 0 deletions tests/execution/test-interface-from-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Interfaces defined in json

```json @server
{
"upstream": {
"baseURL": "http://jsonplaceholder.typicode.com"
},
"schema": {
"query": "Query"
},
"types": {
"IA": {
"fields": {
"a": {
"type": "String"
}
}
},
"B": {
"implements": ["IA"],
"fields": {
"a": {
"type": "String"
},
"b": {
"type": "String"
}
}
},
"Query": {
"fields": {
"bar": {
"type": "B",
"http": {
"path": "/posts"
}
}
}
}
}
}
```

1 comment on commit 4c4b5ba

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running 30s test @ http://localhost:8000/graphql

4 threads and 100 connections

Thread Stats Avg Stdev Max +/- Stdev
Latency 8.88ms 5.74ms 110.06ms 83.44%
Req/Sec 3.01k 661.41 3.69k 84.75%

359221 requests in 30.01s, 1.80GB read

Requests/sec: 11969.53

Transfer/sec: 61.44MB

Please sign in to comment.