add deprecated config for opendd metadata (#372)

Add an optional `deprecated` key to the following OpenDD metadata
- Object type field definitions
- Model select unique and select many graphql API
- Command GraphQL API
- Relationship

The `deprecated` value is an object with an optional `reason` key.
```
"deprecated": {
  "reason": "Optional reason"
}
```
Produce `@deprecated` against GraphQL fields generated from
aforementioned OpenDD metadata using `deprecated` config.

V3_GIT_ORIGIN_REV_ID: b26fe8a8b62de24d04820578b8201d3ff8585375
This commit is contained in:
Rakesh Emmadi 2024-03-20 14:52:56 +05:30 committed by hasura-bot
parent 0b69370cc9
commit 1895e87e84
22 changed files with 1434 additions and 26 deletions

View File

@ -16,7 +16,7 @@ use open_dds::commands::{
};
use open_dds::data_connector::DataConnectorName;
use open_dds::permissions::{CommandPermissionsV1, Role, ValueExpression};
use open_dds::types::{BaseType, CustomTypeName, TypeName, TypeReference};
use open_dds::types::{BaseType, CustomTypeName, Deprecated, TypeName, TypeReference};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
@ -30,6 +30,7 @@ use super::types::{
pub struct CommandGraphQlApi {
pub root_field_kind: GraphQlRootFieldKind,
pub root_field_name: ast::Name,
pub deprecated: Option<Deprecated>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
@ -122,6 +123,7 @@ pub fn resolve_command(
Some(CommandGraphQlApi {
root_field_kind: graphql_definition.root_field_kind.clone(),
root_field_name: f,
deprecated: graphql_definition.deprecated.clone(),
})
})
}

View File

@ -20,6 +20,7 @@ use lang_graphql::ast::common::{self as ast, Name};
use ndc::models::ComparisonOperatorDefinition;
use ndc_client as ndc;
use open_dds::permissions::{NullableModelPredicate, RelationshipPredicate};
use open_dds::types::Deprecated;
use open_dds::{
arguments::ArgumentName,
data_connector::DataConnectorName,
@ -52,12 +53,14 @@ pub struct SelectUniqueGraphQlDefinition {
pub query_root_field: ast::Name,
pub unique_identifier: IndexMap<FieldName, UniqueIdentifierField>,
pub description: Option<String>,
pub deprecated: Option<Deprecated>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct SelectManyGraphQlDefinition {
pub query_root_field: ast::Name,
pub description: Option<String>,
pub deprecated: Option<Deprecated>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
@ -926,6 +929,7 @@ pub fn resolve_model_graphql_api(
query_root_field: select_unique_field_name,
unique_identifier: unique_identifier_fields,
description: select_unique_description,
deprecated: select_unique.deprecated.clone(),
});
}
@ -1105,6 +1109,7 @@ pub fn resolve_model_graphql_api(
Some(SelectManyGraphQlDefinition {
query_root_field: f,
description: select_many_description,
deprecated: gql_definition.deprecated.clone(),
})
}),
}?;

View File

@ -19,6 +19,7 @@ use open_dds::relationships::{
self, FieldAccess, RelationshipName, RelationshipType, RelationshipV1,
};
use open_dds::types::CustomTypeName;
use open_dds::types::Deprecated;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::collections::HashSet;
@ -70,6 +71,7 @@ pub struct Relationship {
pub target: RelationshipTarget,
pub target_capabilities: Option<RelationshipCapabilities>,
pub description: Option<String>,
pub deprecated: Option<Deprecated>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
@ -463,5 +465,6 @@ pub fn resolve_relationship(
target: relationship_target,
target_capabilities,
description: relationship.description.clone(),
deprecated: relationship.deprecated.clone(),
})
}

View File

@ -13,8 +13,8 @@ use open_dds::identifier;
use open_dds::models::EnableAllOrSpecific;
use open_dds::permissions::{Role, TypeOutputPermission, TypePermissionsV1};
use open_dds::types::{
self, CustomTypeName, DataConnectorTypeMapping, FieldName, ObjectBooleanExpressionTypeV1,
ObjectTypeV1, TypeName,
self, CustomTypeName, DataConnectorTypeMapping, Deprecated, FieldName,
ObjectBooleanExpressionTypeV1, ObjectTypeV1, TypeName,
};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap, HashSet};
@ -101,6 +101,7 @@ impl<'a> ScalarTypeInfo<'a> {
pub struct FieldDefinition {
pub field_type: QualifiedTypeReference,
pub description: Option<String>,
pub deprecated: Option<Deprecated>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
@ -153,6 +154,7 @@ pub fn resolve_field(
Ok(FieldDefinition {
field_type: mk_qualified_type_reference(&field.field_type, subgraph),
description: field.description.clone(),
deprecated: field.deprecated.clone(),
})
}

View File

@ -1,8 +1,11 @@
use lang_graphql::ast::common as ast;
use lang_graphql::schema as gql_schema;
use open_dds::{
commands::CommandName, models::ModelName, permissions::Role, relationships::RelationshipName,
types::CustomTypeName,
commands::CommandName,
models::ModelName,
permissions::Role,
relationships::RelationshipName,
types::{CustomTypeName, Deprecated},
};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
@ -274,3 +277,14 @@ pub fn mk_typename(name: &str) -> Result<ast::TypeName, Error> {
}),
}
}
pub(crate) fn mk_deprecation_status(
deprecated: &Option<Deprecated>,
) -> gql_schema::DeprecationStatus {
match deprecated {
Some(Deprecated { reason }) => gql_schema::DeprecationStatus::Deprecated {
reason: reason.clone(),
},
None => gql_schema::DeprecationStatus::NotDeprecated,
}
}

View File

@ -86,6 +86,7 @@ pub(crate) fn command_field(
command: &resolved::command::Command,
command_field_name: ast::Name,
command_annotation: Annotation,
deprecation_status: gql_schema::DeprecationStatus,
) -> Result<
(
ast::Name,
@ -102,7 +103,6 @@ pub(crate) fn command_field(
generate_command_argument(gds, builder, command, argument_name, argument_type)?;
arguments.insert(field_name, input_field);
}
let field = builder.conditional_namespaced(
gql_schema::Field::new(
command_field_name.clone(),
@ -110,7 +110,7 @@ pub(crate) fn command_field(
command_annotation,
output_typename,
arguments,
gql_schema::DeprecationStatus::NotDeprecated,
deprecation_status,
),
permissions::get_command_namespace_annotations(command)?,
);
@ -122,6 +122,7 @@ pub(crate) fn function_command_field(
builder: &mut gql_schema::Builder<GDS>,
command: &resolved::command::Command,
command_field_name: ast::Name,
deprecation_status: gql_schema::DeprecationStatus,
) -> Result<
(
ast::Name,
@ -165,6 +166,7 @@ pub(crate) fn function_command_field(
command,
command_field_name,
command_annotation,
deprecation_status,
)
}
@ -173,6 +175,7 @@ pub(crate) fn procedure_command_field(
builder: &mut gql_schema::Builder<GDS>,
command: &resolved::command::Command,
command_field_name: ast::Name,
deprecation_status: gql_schema::DeprecationStatus,
) -> Result<
(
ast::Name,
@ -216,5 +219,6 @@ pub(crate) fn procedure_command_field(
command,
command_field_name,
command_annotation,
deprecation_status,
)
}

View File

@ -23,8 +23,15 @@ pub fn mutation_root_schema(
open_dds::commands::GraphQlRootFieldKind::Mutation
) {
let command_field_name: ast::Name = command_graphql_api.root_field_name.clone();
let (field_name, field) =
commands::procedure_command_field(gds, builder, command, command_field_name)?;
let deprecation_status =
super::mk_deprecation_status(&command_graphql_api.deprecated);
let (field_name, field) = commands::procedure_command_field(
gds,
builder,
command,
command_field_name,
deprecation_status,
)?;
fields.insert(field_name, field);
}
}

View File

@ -54,8 +54,15 @@ pub fn query_root_schema(
GraphQlRootFieldKind::Query
) {
let command_field_name = command_graphql_api.root_field_name.clone();
let (field_name, field) =
commands::function_command_field(gds, builder, command, command_field_name)?;
let deprecation_status =
super::mk_deprecation_status(&command_graphql_api.deprecated);
let (field_name, field) = commands::function_command_field(
gds,
builder,
command,
command_field_name,
deprecation_status,
)?;
fields.insert(field_name, field);
}

View File

@ -8,6 +8,7 @@ use lang_graphql::schema as gql_schema;
use std::collections::HashMap;
use crate::metadata::resolved;
use crate::schema::mk_deprecation_status;
use crate::schema::{
model_arguments,
model_filter::get_where_expression_input_field,
@ -143,7 +144,7 @@ pub(crate) fn select_many_field(
)),
field_type,
arguments,
gql_schema::DeprecationStatus::NotDeprecated,
mk_deprecation_status(&select_many.deprecated),
),
permissions::get_select_permissions_namespace_annotations(model),
);

View File

@ -8,7 +8,7 @@ use std::collections::HashMap;
use crate::metadata::resolved;
use crate::metadata::resolved::types::mk_name;
use crate::schema::types::output_type::get_object_type_representation;
use crate::schema::GDS;
use crate::schema::{mk_deprecation_status, GDS};
use crate::schema::{
model_arguments, permissions,
types::{
@ -93,7 +93,7 @@ pub(crate) fn select_one_field(
)),
ast::TypeContainer::named_null(output_typename),
arguments,
gql_schema::DeprecationStatus::NotDeprecated,
mk_deprecation_status(&select_unique.deprecated),
),
field_annotations,
);

View File

@ -22,8 +22,8 @@ use crate::metadata::resolved::{
types::{mk_name, TypeRepresentation},
};
use crate::schema::commands::generate_command_argument;
use crate::schema::permissions;
use crate::schema::query_root::select_many::generate_select_many_arguments;
use crate::schema::{mk_deprecation_status, permissions};
use crate::schema::{Role, GDS};
type Error = crate::schema::Error;
@ -176,7 +176,7 @@ fn object_type_fields(
}),
get_output_type(gds, builder, &field_definition.field_type)?,
HashMap::new(),
gql_schema::DeprecationStatus::NotDeprecated,
mk_deprecation_status(&field_definition.deprecated),
);
// if output permissions are defined for this type, we conditionally
// include fields
@ -198,6 +198,7 @@ fn object_type_fields(
.map(
|(relationship_field_name, relationship)| -> Result<_, Error> {
let graphql_field_name = relationship_field_name.clone();
let deprecation_status = mk_deprecation_status(&relationship.deprecated);
let relationship_field = match &relationship.target {
resolved::relationship::RelationshipTarget::Command {
@ -254,7 +255,7 @@ fn object_type_fields(
)),
relationship_output_type,
arguments,
gql_schema::DeprecationStatus::NotDeprecated,
deprecation_status,
),
permissions::get_command_relationship_namespace_annotations(
command,
@ -325,7 +326,7 @@ fn object_type_fields(
)),
relationship_output_type,
arguments,
gql_schema::DeprecationStatus::NotDeprecated,
deprecation_status,
),
permissions::get_model_relationship_namespace_annotations(
model,

View File

@ -0,0 +1,729 @@
[
{
"data": {
"__schema": {
"types": [
{
"name": "Actor",
"description": "Object to identify an actor.",
"fields": [
{
"name": "actor_id",
"isDeprecated": true,
"deprecationReason": "actor_id is deprecated"
},
{
"name": "movie_id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "Article",
"description": null,
"fields": [
{
"name": "article_id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "author_id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "title",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "Author",
"description": null,
"fields": [
{
"name": "Articles_relationship",
"isDeprecated": true,
"deprecationReason": "This relationship is deprecated"
},
{
"name": "author_id",
"isDeprecated": true,
"deprecationReason": null
},
{
"name": "first_name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "last_name",
"isDeprecated": true,
"deprecationReason": "last_name is deprecated"
}
]
},
{
"name": "AuthorArgs",
"description": null,
"fields": null
},
{
"name": "Boolean",
"description": null,
"fields": null
},
{
"name": "Float",
"description": null,
"fields": null
},
{
"name": "ID",
"description": null,
"fields": null
},
{
"name": "Int",
"description": null,
"fields": null
},
{
"name": "Mutation",
"description": null,
"fields": [
{
"name": "_no_fields_accessible",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "NameFilterOpaqueSurname",
"description": null,
"fields": null
},
{
"name": "Opaque",
"description": "Opaque scalar type description.",
"fields": null
},
{
"name": "Query",
"description": null,
"fields": [
{
"name": "AuthorByID",
"isDeprecated": true,
"deprecationReason": "Selecting an author by ID is deprecated"
},
{
"name": "AuthorMany",
"isDeprecated": true,
"deprecationReason": null
},
{
"name": "getActorsByNameOpaqueSurname",
"isDeprecated": true,
"deprecationReason": "This command is deprecated"
},
{
"name": "getActorsByOpaqueName",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "String",
"description": null,
"fields": null
},
{
"name": "__Directive",
"description": null,
"fields": [
{
"name": "args",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isRepeatable",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "locations",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__DirectiveLocation",
"description": null,
"fields": null
},
{
"name": "__EnumValue",
"description": null,
"fields": [
{
"name": "deprecationReason",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isDeprecated",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__Field",
"description": null,
"fields": [
{
"name": "args",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deprecationReason",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isDeprecated",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "type",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__InputValue",
"description": null,
"fields": [
{
"name": "defaultValue",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deprecationReason",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isDeprecated",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "type",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__Schema",
"description": null,
"fields": [
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "directives",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mutationType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "queryType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "subscriptionType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "types",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__Type",
"description": null,
"fields": [
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "enumValues",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "fields",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "inputFields",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "interfaces",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "kind",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ofType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "possibleTypes",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "specifiedByURL",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__TypeKind",
"description": null,
"fields": null
}
]
}
}
},
{
"data": {
"__schema": {
"types": [
{
"name": "Article",
"description": null,
"fields": [
{
"name": "article_id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "author_id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "title",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "Author",
"description": null,
"fields": [
{
"name": "Articles_relationship",
"isDeprecated": true,
"deprecationReason": "This relationship is deprecated"
},
{
"name": "author_id",
"isDeprecated": true,
"deprecationReason": null
},
{
"name": "first_name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "last_name",
"isDeprecated": true,
"deprecationReason": "last_name is deprecated"
}
]
},
{
"name": "AuthorArgs",
"description": null,
"fields": null
},
{
"name": "Boolean",
"description": null,
"fields": null
},
{
"name": "Float",
"description": null,
"fields": null
},
{
"name": "ID",
"description": null,
"fields": null
},
{
"name": "Int",
"description": null,
"fields": null
},
{
"name": "Mutation",
"description": null,
"fields": [
{
"name": "_no_fields_accessible",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "Query",
"description": null,
"fields": [
{
"name": "AuthorByID",
"isDeprecated": true,
"deprecationReason": "Selecting an author by ID is deprecated"
},
{
"name": "AuthorMany",
"isDeprecated": true,
"deprecationReason": null
}
]
},
{
"name": "String",
"description": null,
"fields": null
},
{
"name": "__Directive",
"description": null,
"fields": [
{
"name": "args",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isRepeatable",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "locations",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__DirectiveLocation",
"description": null,
"fields": null
},
{
"name": "__EnumValue",
"description": null,
"fields": [
{
"name": "deprecationReason",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isDeprecated",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__Field",
"description": null,
"fields": [
{
"name": "args",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deprecationReason",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isDeprecated",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "type",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__InputValue",
"description": null,
"fields": [
{
"name": "defaultValue",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deprecationReason",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isDeprecated",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "type",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__Schema",
"description": null,
"fields": [
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "directives",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mutationType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "queryType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "subscriptionType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "types",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__Type",
"description": null,
"fields": [
{
"name": "description",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "enumValues",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "fields",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "inputFields",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "interfaces",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "kind",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ofType",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "possibleTypes",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "specifiedByURL",
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "__TypeKind",
"description": null,
"fields": null
}
]
}
}
}
]

View File

@ -0,0 +1,17 @@
query TypeIntrospectionDescription {
__schema {
types {
...FullType
}
}
}
fragment FullType on __Type {
name
description
fields(includeDeprecated: true) {
name
isDeprecated
deprecationReason
}
}

View File

@ -0,0 +1,492 @@
{
"version": "v2",
"subgraphs": [
{
"name": "default",
"objects": [
{
"kind": "ObjectType",
"version": "v1",
"definition": {
"name": "Actor",
"description": "Object to identify an actor.",
"fields": [
{
"name": "actor_id",
"description": "Unique ID to identify an actor.",
"type": "Int!",
"deprecated": {
"reason": "actor_id is deprecated"
}
},
{
"name": "name",
"description": "Name of the actor.",
"type": "String!"
},
{
"name": "movie_id",
"description": "Movie ID.",
"type": "Int!",
"deprecated": null
}
],
"graphql": {
"typeName": "Actor"
},
"dataConnectorTypeMapping": [
{
"dataConnectorName": "custom",
"dataConnectorObjectType": "actor",
"fieldMapping": {
"actor_id": {
"column": {
"name": "id"
}
},
"name": {
"column": {
"name": "name"
}
},
"movie_id": {
"column": {
"name": "movie_id"
}
}
}
}
]
}
},
{
"kind": "ObjectType",
"version": "v1",
"definition": {
"name": "author",
"fields": [
{
"name": "author_id",
"description": "Identifier to uniquely identify an author",
"type": "Int!",
"deprecated": {
"reason": null
}
},
{
"name": "first_name",
"type": "String!"
},
{
"name": "last_name",
"type": "String!",
"deprecated": {
"reason": "last_name is deprecated"
}
}
],
"graphql": {
"typeName": "Author"
}
}
},
{
"kind": "TypePermissions",
"version": "v1",
"definition": {
"typeName": "author",
"permissions": [
{
"role": "admin",
"output": {
"allowedFields": [
"author_id",
"first_name",
"last_name"
]
}
},
{
"role": "user",
"output": {
"allowedFields": [
"author_id",
"first_name",
"last_name"
]
}
}
]
}
},
{
"kind": "Model",
"version": "v1",
"definition": {
"name": "Authors",
"objectType": "author",
"arguments": [
{
"name": "authors_arg",
"type": "Int!",
"description": "Authors argument description"
}
],
"graphql": {
"selectUniques": [
{
"queryRootField": "AuthorByID",
"description": "Selecting an author by ID",
"uniqueIdentifier": [
"author_id"
],
"deprecated": {
"reason": "Selecting an author by ID is deprecated"
}
}
],
"selectMany": {
"queryRootField": "AuthorMany",
"deprecated": {}
},
"orderByExpressionType": "AuthorOrderBy",
"argumentsInputType": "AuthorArgs"
},
"orderableFields": [
{
"fieldName": "author_id",
"orderByDirections": {
"enableAll": true
}
},
{
"fieldName": "first_name",
"orderByDirections": {
"enableAll": true
}
},
{
"fieldName": "last_name",
"orderByDirections": {
"enableAll": true
}
}
]
}
},
{
"kind": "ModelPermissions",
"version": "v1",
"definition": {
"modelName": "Authors",
"permissions": [
{
"role": "admin",
"select": {
"filter": null
}
},
{
"role": "user",
"select": {
"filter": null
}
}
]
}
},
{
"kind": "TypePermissions",
"version": "v1",
"definition": {
"typeName": "Actor",
"permissions": [
{
"role": "admin",
"output": {
"allowedFields": [
"actor_id",
"name",
"movie_id"
]
}
}
]
}
},
{
"kind": "ScalarType",
"version": "v1",
"definition": {
"description": "Opaque scalar type description.",
"name": "Opaque",
"graphql": {
"typeName": "Opaque"
}
}
},
{
"kind": "ObjectType",
"version": "v1",
"definition": {
"name": "NameFilterOpaqueSurname",
"fields": [
{
"name": "first_name",
"type": "String"
},
{
"name": "surname",
"type": "Opaque"
}
],
"graphql": {
"inputTypeName": "NameFilterOpaqueSurname"
},
"dataConnectorTypeMapping": [
{
"dataConnectorName": "custom",
"dataConnectorObjectType": "name_query",
"fieldMapping": {
"first_name": {
"column": {
"name": "first_name"
}
},
"surname": {
"column": {
"name": "last_name"
}
}
}
}
]
}
},
{
"kind": "Command",
"version": "v1",
"definition": {
"name": "get_actors_by_name_opaque_surname",
"arguments": [
{
"name": "name_filter",
"type": "NameFilterOpaqueSurname!"
}
],
"outputType": "[Actor!]!",
"source": {
"dataConnectorName": "custom",
"dataConnectorCommand": {
"function": "get_actors_by_name"
},
"argumentMapping": {
"name_filter": "name"
}
},
"graphql": {
"rootFieldName": "getActorsByNameOpaqueSurname",
"rootFieldKind": "Query",
"deprecated": {
"reason": "This command is deprecated"
}
}
}
},
{
"kind": "CommandPermissions",
"version": "v1",
"definition": {
"commandName": "get_actors_by_name_opaque_surname",
"permissions": [
{
"role": "admin",
"allowExecution": true
}
]
}
},
{
"kind": "Command",
"version": "v1",
"definition": {
"name": "get_actors_by_opaque_name",
"description": "Command to get the actors matching a given name.",
"arguments": [
{
"name": "name_filter",
"description": "name_filter command argument description",
"type": "Opaque!"
}
],
"outputType": "[Actor!]!",
"source": {
"dataConnectorName": "custom",
"dataConnectorCommand": {
"function": "get_actors_by_name"
},
"argumentMapping": {
"name_filter": "name"
}
},
"graphql": {
"rootFieldName": "getActorsByOpaqueName",
"rootFieldKind": "Query"
}
}
},
{
"kind": "CommandPermissions",
"version": "v1",
"definition": {
"commandName": "get_actors_by_opaque_name",
"permissions": [
{
"role": "admin",
"allowExecution": true
}
]
}
},
{
"kind": "ObjectType",
"version": "v1",
"definition": {
"name": "article",
"fields": [
{
"name": "article_id",
"type": "Int!"
},
{
"name": "title",
"type": "String!"
},
{
"name": "author_id",
"type": "Int!"
}
],
"graphql": {
"typeName": "Article"
}
}
},
{
"kind": "TypePermissions",
"version": "v1",
"definition": {
"typeName": "article",
"permissions": [
{
"role": "admin",
"output": {
"allowedFields": [
"article_id",
"title",
"author_id"
]
}
},
{
"role": "user",
"output": {
"allowedFields": [
"title",
"author_id",
"article_id"
]
}
}
]
}
},
{
"kind": "Model",
"version": "v1",
"definition": {
"name": "Articles",
"objectType": "article",
"orderableFields": [
{
"fieldName": "article_id",
"orderByDirections": {
"enableAll": true
}
},
{
"fieldName": "title",
"orderByDirections": {
"enableAll": true
}
},
{
"fieldName": "author_id",
"orderByDirections": {
"enableAll": true
}
}
]
}
},
{
"kind": "ModelPermissions",
"version": "v1",
"definition": {
"modelName": "Articles",
"permissions": [
{
"role": "admin",
"select": {
"filter": null
}
},
{
"role": "user",
"select": {
"filter": null
}
}
]
}
},
{
"kind": "Relationship",
"version": "v1",
"definition": {
"source": "author",
"name": "Articles_relationship",
"description": "Gets the corresponding articles of the author.",
"deprecated": {
"reason": "This relationship is deprecated"
},
"target": {
"model": {
"name": "Articles",
"relationshipType": "Array"
}
},
"mapping": [
{
"source": {
"fieldPath": [
{
"fieldName": "author_id"
}
]
},
"target": {
"modelField": [
{
"fieldName": "author_id"
}
]
}
}
]
}
}
]
}
]
}

View File

@ -0,0 +1,8 @@
[
{
"x-hasura-role": "admin"
},
{
"x-hasura-role": "user"
}
]

View File

@ -42,3 +42,13 @@ fn test_introspect_model_with_preset_arguments_select_one() {
],
);
}
#[test]
fn test_graphql_deprecated() {
let common_custom_connector_path_string =
"execute/common_metadata/custom_connector_schema.json";
common::test_introspection_expectation(
"execute/deprecated",
&[common_custom_connector_path_string],
);
}

View File

@ -720,6 +720,17 @@
"string",
"null"
]
},
"deprecated": {
"description": "Whether this field is deprecated. If set, the deprecation status is added to the field's graphql schema.",
"anyOf": [
{
"$ref": "#/definitions/Deprecated"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@ -737,6 +748,21 @@
"description": "A reference to an Open DD type including nullable values and arrays.\nSuffix '!' to indicate a non-nullable reference, and wrap in '[]' to indicate an array.\nEg: '[String!]!' is a non-nullable array of non-nullable strings.",
"type": "string"
},
"Deprecated": {
"$id": "https://hasura.io/jsonschemas/metadata/Deprecated",
"title": "Deprecated",
"description": "OpenDd configuration to indicate whether an object type field, relationship, model root field or command root field is deprecated.",
"type": "object",
"properties": {
"reason": {
"description": "The reason for deprecation.",
"type": [
"string",
"null"
]
}
}
},
"ObjectTypeGraphQLConfiguration": {
"$id": "https://hasura.io/jsonschemas/metadata/ObjectTypeGraphQLConfiguration",
"title": "ObjectTypeGraphQLConfiguration",
@ -1543,6 +1569,17 @@
"string",
"null"
]
},
"deprecated": {
"description": "Whether this select unique query field is deprecated. If set, the deprecation status is added to the select unique root field's graphql schema.",
"anyOf": [
{
"$ref": "#/definitions/Deprecated"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@ -1576,6 +1613,17 @@
"string",
"null"
]
},
"deprecated": {
"description": "Whether this select many query field is deprecated. If set, the deprecation status is added to the select many root field's graphql schema.",
"anyOf": [
{
"$ref": "#/definitions/Deprecated"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@ -1765,7 +1813,10 @@
"examples": [
{
"rootFieldName": "getLatestArticle",
"rootFieldKind": "Query"
"rootFieldKind": "Query",
"deprecated": {
"reason": "Use getLatestArticleV2 instead"
}
}
],
"type": "object",
@ -1789,6 +1840,17 @@
"$ref": "#/definitions/GraphQlRootFieldKind"
}
]
},
"deprecated": {
"description": "Whether this command root field is deprecated. If set, this will be added to the graphql schema as a deprecated field.",
"anyOf": [
{
"$ref": "#/definitions/Deprecated"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@ -1836,7 +1898,8 @@
}
}
],
"description": "Articles written by an author"
"description": "Articles written by an author",
"deprecated": {}
}
],
"type": "object",
@ -1884,6 +1947,17 @@
"string",
"null"
]
},
"deprecated": {
"description": "Whether this relationship is deprecated. If set, the deprecation status is added to the relationship field's graphql schema.",
"anyOf": [
{
"$ref": "#/definitions/Deprecated"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false

View File

@ -8,7 +8,7 @@ use crate::{
data_connector::DataConnectorName,
identifier::Identifier,
impl_JsonSchema_with_OpenDd_for,
types::{GraphQlFieldName, TypeReference},
types::{Deprecated, GraphQlFieldName, TypeReference},
};
/// The name of a command.
@ -163,13 +163,19 @@ pub struct CommandGraphQlDefinition {
pub root_field_name: GraphQlFieldName,
/// Whether to put this command in the Query or Mutation root of the GraphQL API.
pub root_field_kind: GraphQlRootFieldKind,
/// Whether this command root field is deprecated.
/// If set, this will be added to the graphql schema as a deprecated field.
pub deprecated: Option<Deprecated>,
}
impl CommandGraphQlDefinition {
fn example() -> serde_json::Value {
serde_json::json!({
"rootFieldName": "getLatestArticle",
"rootFieldKind": "Query"
"rootFieldKind": "Query",
"deprecated": {
"reason": "Use getLatestArticleV2 instead"
}
})
}
}

View File

@ -9,7 +9,7 @@ use crate::{
identifier::Identifier,
impl_JsonSchema_with_OpenDd_for,
traits::{OpenDd, OpenDdDeserializeError},
types::{CustomTypeName, FieldName, GraphQlFieldName, GraphQlTypeName},
types::{CustomTypeName, Deprecated, FieldName, GraphQlFieldName, GraphQlTypeName},
};
/// The name of data model.
@ -209,6 +209,9 @@ pub struct SelectUniqueGraphQlDefinition {
/// The description of the select unique graphql definition of the model.
/// Gets added to the description of the select unique root field of the model in the graphql schema.
pub description: Option<String>,
/// Whether this select unique query field is deprecated.
/// If set, the deprecation status is added to the select unique root field's graphql schema.
pub deprecated: Option<Deprecated>,
}
/// The definition of the GraphQL API for selecting rows from a model.
@ -221,6 +224,9 @@ pub struct SelectManyGraphQlDefinition {
/// The description of the select many graphql definition of the model.
/// Gets added to the description of the select many root field of the model in the graphql schema.
pub description: Option<String>,
/// Whether this select many query field is deprecated.
/// If set, the deprecation status is added to the select many root field's graphql schema.
pub deprecated: Option<Deprecated>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, opendds_derive::OpenDd)]

View File

@ -8,7 +8,7 @@ use crate::{
impl_JsonSchema_with_OpenDd_for,
models::ModelName,
permissions::ValueExpression,
types::{CustomTypeName, FieldName},
types::{CustomTypeName, Deprecated, FieldName},
};
/// The name of the GraphQL relationship field.
@ -218,6 +218,9 @@ pub struct RelationshipV1 {
/// The description of the relationship.
/// Gets added to the description of the relationship in the graphql schema.
pub description: Option<String>,
/// Whether this relationship is deprecated.
/// If set, the deprecation status is added to the relationship field's graphql schema.
pub deprecated: Option<Deprecated>,
}
impl RelationshipV1 {
@ -252,7 +255,8 @@ impl RelationshipV1 {
}
}
],
"description": "Articles written by an author"
"description": "Articles written by an author",
"deprecated": {}
}
)
}

View File

@ -413,6 +413,10 @@ pub struct FieldDefinition {
/// The description of this field.
/// Gets added to the description of the field's definition in the graphql schema.
pub description: Option<String>,
/// Whether this field is deprecated.
/// If set, the deprecation status is added to the field's graphql schema.
pub deprecated: Option<Deprecated>,
}
/// GraphQL configuration of an Open DD scalar type
@ -638,3 +642,15 @@ pub struct ObjectBooleanExpressionTypeGraphQlConfiguration {
/// The name to use for the GraphQL type representation of this boolean expression type.
pub type_name: GraphQlTypeName,
}
/// OpenDd configuration to indicate whether an object type field, relationship, model
/// root field or command root field is deprecated.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "camelCase")]
#[schemars(title = "Deprecated")]
pub struct Deprecated {
/// The reason for deprecation.
pub reason: Option<String>,
}
impl_OpenDd_default_for!(Deprecated);