예제 #1
0
        private static ObjectFieldDefinition CreateDefinition(
            IDescriptorContext context)
        {
            var descriptor = ObjectFieldDescriptor.New(context, _node);

            IIdSerializer?serializer = null;

            descriptor
            .Argument(_id, a => a.Type <NonNullType <IdType> >())
            .Type <NodeType>()
            .Resolve(async ctx =>
            {
                IServiceProvider services = ctx.Service <IServiceProvider>();

                serializer ??= services.GetService(typeof(IIdSerializer)) is IIdSerializer s
                        ? s
                        : new IdSerializer();

                var id = ctx.ArgumentValue <string>(_id);
                IdValue deserializedId = serializer.Deserialize(id);

                ctx.LocalContextData = ctx.LocalContextData
                                       .SetItem(WellKnownContextData.Id, deserializedId.Value)
                                       .SetItem(WellKnownContextData.Type, deserializedId.TypeName);

                if (ctx.Schema.TryGetType(deserializedId.TypeName,
                                          out ObjectType type) &&
                    type.ContextData.TryGetValue(
                        RelayConstants.NodeResolverFactory,
                        out object?o) &&
                    o is Func <IServiceProvider, INodeResolver> factory)
                {
                    INodeResolver resolver = factory.Invoke(services);
                    return(await resolver.ResolveAsync(ctx, deserializedId.Value)
                           .ConfigureAwait(false));
                }

                return(null);
            });

            return(descriptor.CreateDefinition());
        }
예제 #2
0
        private static ObjectFieldDefinition CreateDefinition(
            IDescriptorContext context)
        {
            var descriptor = ObjectFieldDescriptor
                             .New(context, IntrospectionFields.Type);

            descriptor.Description(
                TypeResources.TypeField_Description)
            .Argument("name", a => a.Type <NonNullType <StringType> >())
            .Type <__Type>()
            .Resolver(ctx =>
            {
                string name = ctx.Argument <string>("name");
                if (ctx.Schema.TryGetType(name, out INamedType type))
                {
                    return(type);
                }
                return(null);
            });

            return(descriptor.CreateDefinition());
        }
        public void OnBeforeCompleteType(ICompletionContext context, DefinitionBase definition, IDictionary <string, object> contextData)
        {
            var def = (ObjectTypeDefinition)definition;

            var autoList = ((List <ObjectFieldDefinition>)context.ContextData[AutoSubscriptionContext]);

            foreach (var mutationDef in autoList)
            {
                string         subscriptionName = $"on{mutationDef.Name.Value.ToPascalCase()}";
                ITypeReference mutationType     = mutationDef.Type;
                IOutputType    type             = context.GetType <IOutputType>(mutationType);
                var            descriptor       = ObjectFieldDescriptor.New(context.DescriptorContext, subscriptionName);
                descriptor
                .Type(type)
                .Description($"Subscription for the {mutationDef.Name.Value} mutation.")
                .Resolver(ctx =>
                {
                    return(ctx.GetEventMessage().Payload);
                });
                def.Fields.Add(descriptor.CreateDefinition());
            }
            def.Description +=
                @"

Snowflake provides two types of definition in its framework queries:
  * `onVerbObject`
  * `onObjectVerb(Uuid!)`

`onVerbObject` subscriptions are global, and are broadcast whenever the corresponding mutation occurs. These can be used to subscribe to mutations that are triggered by the client.
`onObjectVerb(Uuid!)` subscriptions are primarily used by scraping, installation, and orchestration mutations. These are used to subscribe to events happening on a specific long-existing object that may or may not be the result of a client request.

There is some subtlely in the different types of subscriptions that one should be aware about.

For example, `onStopEmulation` is broadcast when the `stopEmulation` mutation responds to some client. However, `onEmulationStop` is broadcast when the emulation process exits. Hence, `onStopEmulation` may never be broadcast, even if `onEmulationStop` was.

In most cases, it is more useful to subscribe to the `onObjectVerb` subscription for an object whenever feasible.
";
        }
    protected override void OnCompleteFields(
        IDictionary <NameString, ObjectFieldDefinition> fields,
        ISet <MemberInfo> handledMembers)
    {
        HashSet <string> subscribeResolver = null;

        if (Definition.Fields.IsImplicitBinding() &&
            Definition.FieldBindingType is not null)
        {
            FieldDescriptorUtilities.AddImplicitFields(
                this,
                Definition.FieldBindingType,
                p =>
            {
                var descriptor = ObjectFieldDescriptor.New(
                    Context, p, Definition.RuntimeType, Definition.FieldBindingType);

                if (Definition.IsExtension && Context.TypeInspector.IsMemberIgnored(p))
                {
                    descriptor.Ignore();
                }

                Fields.Add(descriptor);
                return(descriptor.CreateDefinition());
            },
                fields,
                handledMembers,
                include: IncludeField,
                includeIgnoredMembers
                : Definition.IsExtension);
        }

        base.OnCompleteFields(fields, handledMembers);

        bool IncludeField(IReadOnlyList <MemberInfo> all, MemberInfo current)
        {
            NameString name = Context.Naming.GetMemberName(current, MemberKind.ObjectField);

            if (Fields.Any(t => t.Definition.Name.Equals(name)))
            {
                return(false);
            }

            if (subscribeResolver is null)
            {
                subscribeResolver = new HashSet <string>();

                foreach (MemberInfo member in all)
                {
                    HandlePossibleSubscribeMember(member);
                }
            }

            return(!subscribeResolver.Contains(current.Name));
        }

        void HandlePossibleSubscribeMember(MemberInfo member)
        {
            if (member.IsDefined(typeof(SubscribeAttribute)))
            {
                if (member.GetCustomAttribute <SubscribeAttribute>() is { With : not null } attr)
                {
                    subscribeResolver.Add(attr.With);
                }
            }
        }
    }