-
Notifications
You must be signed in to change notification settings - Fork 396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Partial GraphQL types #688
Comments
You've basically used a non-public API to accomplish this. I suppose there's a way to achieve something similar, but using a different technique (without accessing a private API). I'll think about how we can make it more straightforward for everyone. |
Yes I did because I had no alternatives. Maybe this could be accomplished using directives? |
@Carlovan I had the same issue, I had to do the following to get the fields loaded. getGraphqlFieldsForType<T>(objType: Class<T>): PropertyMetadata[] | undefined {
LazyMetadataStorage.load([objType]);
TypeMetadataStorage.compile();
let graphqlObjType = this.getGraphqlObjectMetadata(objType);
if (!graphqlObjType) {
graphqlObjType = TypeMetadataStorage.getInputTypesMetadata().find(o => o.target === objType);
}
return graphqlObjType?.properties;
} export function PartialType<T>(TClass: Class<T>): Class<Partial<T>> {
const graphQLFields = getMetadataStorage().getGraphqlFieldsForType(TClass);
if (!(graphQLFields && graphQLFields.length)) {
throw new Error(`Unable to find fields for graphql type ${TClass.name}`);
}
@ObjectType({ isAbstract: true })
abstract class PartialObjectType {}
graphQLFields.forEach(f => Field(f.typeFn, { ...f.options, nullable: true })(PartialObjectType.prototype, f.name));
return PartialObjectType as Class<Partial<T>>;
} |
We have also added Example: @InputType()
class CreateUserInput {
@Field()
email: string;
@Field()
password: string;
@Field()
firstName: string
} and to create the @InputType()
export class UpdateUserInput extends PartialType(CreateUserInput) {} If you want to exclude, let's say, the @InputType()
export class UpdateUserInput extends PartialType(OmitType(CreateUserInput, ['email'])) {} |
@kamilmysliwiec thanks for the quick turn around on this. Unfortunately this doesnt work for my use case :( In my use case someone can provide a Here is what I had. import { Class } from '@nestjs-query/core';
import { Field, ObjectType, InputType } from '@nestjs/graphql';
import { getMetadataStorage } from '../metadata';
export function PartialType<T>(TClass: Class<T>): Class<Partial<T>> {
const graphQLFields = getMetadataStorage().getGraphqlFieldsForType(TClass);
if (!(graphQLFields && graphQLFields.length)) {
throw new Error(`Unable to find fields for graphql type ${TClass.name}`);
}
@ObjectType({ isAbstract: true })
abstract class PartialObjectType {}
graphQLFields.forEach(f => Field(f.typeFn, { ...f.options, nullable: true })(PartialObjectType.prototype, f.name));
return PartialObjectType as Class<Partial<T>>;
}
export function PartialInputType<T>(TClass: Class<T>): Class<Partial<T>> {
// the getGraphqlFieldsForType uses the code snippet I provided earlier.
const graphQLFields = getMetadataStorage().getGraphqlFieldsForType(TClass);
if (!(graphQLFields && graphQLFields.length)) {
throw new Error(`Unable to find fields for graphql type ${TClass.name}`);
}
@InputType({ isAbstract: true })
class PartialInptType {}
graphQLFields.forEach(f => Field(f.typeFn, { ...f.options, nullable: true })(PartialInptType.prototype, f.name));
return PartialInptType as Class<Partial<T>>;
} I see in your new implementation you preserve the original type decorator, and it find the fields just fine, however its annotated with Thank you again for the work you are putting into this! |
In 7.1.2, all utility functions ( Example (where @InputType()
export class CreateUserInput extends PartialType(User, InputType) {} |
@kamilmysliwiec that was the exact solution I was thinking :) I cant thank you enough for fixing this, your awesome! |
@kamilmysliwiec Is there any way to allow partial types to also include fields from extended abstract types (which use For example: @ObjectType()
export class User extends BaseType {
@Field()
email: string
@Field()
name: string
} @ObjectType({ isAbstract: true })
export abstract class BaseType {
@Field(type => ID)
id: string
@Field(type => GraphQLISODateTime)
createdAt: Date
@Field(type => GraphQLISODateTime)
updatedAt: Date
} When creating a partial user input type, like so: @InputType()
export class UserPartialInput extends PartialType(User, InputType) {} The resulting partial input type will only include fields from input UserPartialInput {
email: String
name: String
} |
@amille14 fixed in 7.3.4 :) |
This might be an issue of its own, but reading this conversation and the documentation on docs.nestjs.com gives two very different impressions regarding the decorator argument. On this thread I read it basically as "you should pass in the decorator you want the type to act as" where as the docs say pretty much the opposite, that you should provide the decorator that is being used. I might be misunderstanding something, but I thought it's worth bringing up nonetheless as this thread helped me solve an issue I couldn't quite grasp from reading the docs. Quote from the docs that mislead me:
|
@dotellie docs are wrong. We're tracking the update here nestjs/docs.nestjs.com#1167 |
I'm submitting a...
Current behavior
Now it's not possible to create a "partial" type from a GraphQL type; here with "partial type" I mean a type with all fields nullable.
Expected behavior
I'd like to be able to create a partial version of an existing GraphQL type, that is a copy of that type with the only difference that all fields are nullable.
What is the motivation / use case for changing the behavior?
In my API I need to handle various complex entities with CRUD operations; specifically the input Create and Update operations are the same but for Create the fields are all mandatory and for Update they are all nullable (I may want to update only some of them).
I managed to get this in
type-graphql
by accessing the MetadataStorage and actually copying all the FieldMetadata with thenullable
option set, but with the new LazyMetadataStorage this is not possible anymore.Environment
The text was updated successfully, but these errors were encountered: