Documentation ¶
Index ¶
- Constants
- Variables
- func AnalyzePlanKind(operation, definition *ast.Document, operationName string) (operationType ast.OperationType, streaming bool, error error)
- func RequiredFieldsFragment(typeName, requiredFields string, includeTypename bool) (*ast.Document, *operationreport.Report)
- type ArgumentConfiguration
- type ArgumentRenderConfig
- type ArgumentUsageInfo
- type ArgumentsConfigurations
- type Configuration
- type DSHash
- type DataSourceConfiguration
- func (d *DataSourceConfiguration) HasChildNode(typeName, fieldName string) bool
- func (d *DataSourceConfiguration) HasChildNodeWithTypename(typeName string) bool
- func (d *DataSourceConfiguration) HasKeyRequirement(typeName, requiresFields string) bool
- func (d *DataSourceConfiguration) HasRootNode(typeName, fieldName string) bool
- func (d *DataSourceConfiguration) HasRootNodeWithTypename(typeName string) bool
- func (d *DataSourceConfiguration) Hash() DSHash
- func (d *DataSourceConfiguration) RequiredFieldsByKey(typeName string) []FederationFieldConfiguration
- func (d *DataSourceConfiguration) RequiredFieldsByRequires(typeName, fieldName string) []FederationFieldConfiguration
- type DataSourceDebugger
- type DataSourceFilter
- type DataSourcePlanner
- type DataSourcePlannerConfiguration
- type DataSourcePlanningBehavior
- type DebugConfiguration
- type DirectiveConfiguration
- type DirectiveConfigurations
- type EntityInterfaceConfiguration
- type FederationFieldConfiguration
- type FederationFieldConfigurations
- func (f FederationFieldConfigurations) FilterByType(typeName string) (out []FederationFieldConfiguration)
- func (f FederationFieldConfigurations) FilterByTypeAndField(typeName, fieldName string) (out []FederationFieldConfiguration)
- func (f FederationFieldConfigurations) HasSelectionSet(typeName, fieldName, selectionSet string) bool
- func (f FederationFieldConfigurations) UniqueTypes() (out []string)
- type FederationMetaData
- type FieldConfiguration
- type FieldConfigurations
- type InputTypeFieldUsageInfo
- type Kind
- type NodeSuggestion
- type NodeSuggestionHint
- type NodeSuggestions
- type PathType
- type Plan
- type Planner
- type PlannerFactory
- type PlannerPathType
- type SchemaUsageInfo
- type SourceType
- type SubscriptionConfiguration
- type SubscriptionResponsePlan
- type SynchronousResponsePlan
- type TypeConfiguration
- type TypeConfigurations
- type TypeField
- type TypeFieldSource
- type TypeFieldUsageInfo
- type TypeFields
- type Visitor
- func (v *Visitor) AllowVisitor(kind astvisitor.VisitorKind, ref int, visitor interface{}, ...) bool
- func (v *Visitor) EnterDirective(ref int)
- func (v *Visitor) EnterDocument(operation, definition *ast.Document)
- func (v *Visitor) EnterField(ref int)
- func (v *Visitor) EnterInlineFragment(ref int)
- func (v *Visitor) EnterOperationDefinition(ref int)
- func (v *Visitor) EnterSelectionSet(ref int)
- func (v *Visitor) LeaveDocument(_, _ *ast.Document)
- func (v *Visitor) LeaveField(ref int)
- func (v *Visitor) LeaveInlineFragment(ref int)
- func (v *Visitor) LeaveSelectionSet(ref int)
Constants ¶
const ( ReasonStage1Uniq = "stage1: uniq" ReasonStage1SameSourceParent = "stage1: same source parent of uniq node" ReasonStage1SameSourceLeafChild = "stage1: same source leaf child of uniq node" ReasonStage1SameSourceLeafSibling = "stage1: same source leaf sibling of uniq node" ReasonStage2SameSourceNodeOfSelectedParent = "stage2: node on the same source as selected parent" ReasonStage2SameSourceNodeOfSelectedChild = "stage2: node on the same source as selected child" ReasonStage2SameSourceNodeOfSelectedSibling = "stage2: node on the same source as selected sibling" ReasonStage3SelectAvailableNode = "stage3: select first available node" ReasonKeyRequirementProvidedByPlanner = "provided by planner as required by @key" )
Variables ¶
var ( FieldDoesntHaveSelectionSetErr = errors.New("unexpected error: field does not have a selection set") InlineFragmentDoesntHaveSelectionSetErr = errors.New("unexpected error: inline fragment does not have a selection set") InlineFragmentTypeIsNotExistsErr = errors.New("unexpected error: inline fragment type condition does not exists") )
Functions ¶
func AnalyzePlanKind ¶
func RequiredFieldsFragment ¶
Types ¶
type ArgumentConfiguration ¶
type ArgumentConfiguration struct { Name string SourceType SourceType SourcePath []string RenderConfig ArgumentRenderConfig RenameTypeTo string }
type ArgumentRenderConfig ¶
type ArgumentRenderConfig string
ArgumentRenderConfig is used to determine how an argument should be rendered
const ( RenderArgumentDefault ArgumentRenderConfig = "" RenderArgumentAsArrayCSV ArgumentRenderConfig = "render_argument_as_array_csv" RenderArgumentAsGraphQLValue ArgumentRenderConfig = "render_argument_as_graphql_value" RenderArgumentAsJSONValue ArgumentRenderConfig = "render_argument_as_json_value" )
type ArgumentUsageInfo ¶
type ArgumentsConfigurations ¶
type ArgumentsConfigurations []ArgumentConfiguration
func (ArgumentsConfigurations) ForName ¶
func (a ArgumentsConfigurations) ForName(argName string) *ArgumentConfiguration
type Configuration ¶
type Configuration struct { DefaultFlushIntervalMillis int64 DataSources []DataSourceConfiguration Fields FieldConfigurations Types TypeConfigurations // DisableResolveFieldPositions should be set to true for testing purposes // This setting removes position information from all fields // In production, this should be set to false so that error messages are easier to understand DisableResolveFieldPositions bool CustomResolveMap map[string]resolve.CustomResolve // Debug - configure debug options Debug DebugConfiguration // IncludeInfo will add additional information to the plan, // e.g. the origin of a field, possible types, etc. // This information is required to compute the schema usage info from a plan IncludeInfo bool }
type DataSourceConfiguration ¶
type DataSourceConfiguration struct { // ID is a unique identifier for the DataSource ID string // RootNodes - defines the nodes where the responsibility of the DataSource begins // When you enter a node, and it is not a child node // when you have entered into a field which representing data source - it means that we are starting a new planning stage RootNodes TypeFields // ChildNodes - describes additional fields which will be requested along with fields which has a datasources // They are always required for the Graphql datasources cause each field could have its own datasource // For any single point datasource like HTTP/REST or GRPC we could not request fewer fields, as we always get a full response ChildNodes TypeFields Directives DirectiveConfigurations Factory PlannerFactory Custom json.RawMessage FederationMetaData FederationMetaData // contains filtered or unexported fields }
func (*DataSourceConfiguration) HasChildNode ¶
func (d *DataSourceConfiguration) HasChildNode(typeName, fieldName string) bool
func (*DataSourceConfiguration) HasChildNodeWithTypename ¶
func (d *DataSourceConfiguration) HasChildNodeWithTypename(typeName string) bool
func (*DataSourceConfiguration) HasKeyRequirement ¶
func (d *DataSourceConfiguration) HasKeyRequirement(typeName, requiresFields string) bool
func (*DataSourceConfiguration) HasRootNode ¶
func (d *DataSourceConfiguration) HasRootNode(typeName, fieldName string) bool
func (*DataSourceConfiguration) HasRootNodeWithTypename ¶
func (d *DataSourceConfiguration) HasRootNodeWithTypename(typeName string) bool
func (*DataSourceConfiguration) Hash ¶
func (d *DataSourceConfiguration) Hash() DSHash
func (*DataSourceConfiguration) RequiredFieldsByKey ¶
func (d *DataSourceConfiguration) RequiredFieldsByKey(typeName string) []FederationFieldConfiguration
func (*DataSourceConfiguration) RequiredFieldsByRequires ¶
func (d *DataSourceConfiguration) RequiredFieldsByRequires(typeName, fieldName string) []FederationFieldConfiguration
type DataSourceDebugger ¶
type DataSourceDebugger interface { astvisitor.VisitorIdentifier DebugPrint(args ...interface{}) EnableDebug() EnableQueryPlanLogging() }
type DataSourceFilter ¶
type DataSourceFilter struct {
// contains filtered or unexported fields
}
func NewDataSourceFilter ¶
func NewDataSourceFilter(operation, definition *ast.Document, report *operationreport.Report) *DataSourceFilter
func (*DataSourceFilter) FilterDataSources ¶
func (f *DataSourceFilter) FilterDataSources(dataSources []DataSourceConfiguration, existingNodes NodeSuggestions, hints ...NodeSuggestionHint) (used []DataSourceConfiguration, suggestions NodeSuggestions)
type DataSourcePlanner ¶
type DataSourcePlanner interface { Register(visitor *Visitor, configuration DataSourceConfiguration, dataSourcePlannerConfiguration DataSourcePlannerConfiguration) error ConfigureFetch() resolve.FetchConfiguration ConfigureSubscription() SubscriptionConfiguration DataSourcePlanningBehavior() DataSourcePlanningBehavior // DownstreamResponseFieldAlias allows the DataSourcePlanner to overwrite the response path with an alias // It's required to set OverrideFieldPathFromAlias to true // This function is useful in the following scenario // 1. The downstream Query doesn't contain an alias // 2. The path configuration rewrites the field to an existing field // 3. The DataSourcePlanner is using an alias to the upstream // Example: // // type Query { // country: Country // countryAlias: Country // } // // Both, country and countryAlias have a path in the FieldConfiguration of "country" // In theory, they would be treated as the same field // However, by using DownstreamResponseFieldAlias, it's possible for the DataSourcePlanner to use an alias for countryAlias. // In this case, the response would contain both, country and countryAlias fields in the response. // At the same time, the downstream Query would only expect the response on the path "country", // as both country and countryAlias have a mapping to the path "country". // The DataSourcePlanner could keep track that it rewrites the upstream query and use DownstreamResponseFieldAlias // to indicate to the Planner to expect the response for countryAlias on the path "countryAlias" instead of "country". DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool) UpstreamSchema(dataSourceConfig DataSourceConfiguration) *ast.Document }
type DataSourcePlannerConfiguration ¶
type DataSourcePlannerConfiguration struct { RequiredFields FederationFieldConfigurations ProvidedFields NodeSuggestions ParentPath string PathType PlannerPathType IsNested bool }
func (*DataSourcePlannerConfiguration) HasRequiredFields ¶
func (c *DataSourcePlannerConfiguration) HasRequiredFields() bool
type DataSourcePlanningBehavior ¶
type DataSourcePlanningBehavior struct { // MergeAliasedRootNodes will reuse a data source for multiple root fields with aliases if true. // Example: // { // rootField // alias: rootField // } // On dynamic data sources (e.g. GraphQL, SQL, ...) this should return true and for // static data sources (e.g. REST, static, GRPC...) it should be false. MergeAliasedRootNodes bool // OverrideFieldPathFromAlias will let the planner know if the response path should also be aliased (= true) // or not (= false) // Example: // { // rootField // alias: original // } // When true expected response will be { "rootField": ..., "alias": ... } // When false expected response will be { "rootField": ..., "original": ... } OverrideFieldPathFromAlias bool // IncludeTypeNameFields should be set to true if the planner wants to get EnterField & LeaveField events // for __typename fields IncludeTypeNameFields bool }
type DebugConfiguration ¶
type DirectiveConfiguration ¶
type DirectiveConfigurations ¶
type DirectiveConfigurations []DirectiveConfiguration
func (*DirectiveConfigurations) RenameTypeNameOnMatchBytes ¶
func (d *DirectiveConfigurations) RenameTypeNameOnMatchBytes(directiveName []byte) []byte
func (*DirectiveConfigurations) RenameTypeNameOnMatchStr ¶
func (d *DirectiveConfigurations) RenameTypeNameOnMatchStr(directiveName string) string
type FederationFieldConfigurations ¶
type FederationFieldConfigurations []FederationFieldConfiguration
func (FederationFieldConfigurations) FilterByType ¶
func (f FederationFieldConfigurations) FilterByType(typeName string) (out []FederationFieldConfiguration)
func (FederationFieldConfigurations) FilterByTypeAndField ¶
func (f FederationFieldConfigurations) FilterByTypeAndField(typeName, fieldName string) (out []FederationFieldConfiguration)
func (FederationFieldConfigurations) HasSelectionSet ¶
func (f FederationFieldConfigurations) HasSelectionSet(typeName, fieldName, selectionSet string) bool
func (FederationFieldConfigurations) UniqueTypes ¶
func (f FederationFieldConfigurations) UniqueTypes() (out []string)
type FederationMetaData ¶
type FederationMetaData struct { Keys FederationFieldConfigurations Requires FederationFieldConfigurations Provides FederationFieldConfigurations EntityInterfaces []EntityInterfaceConfiguration InterfaceObjects []EntityInterfaceConfiguration }
type FieldConfiguration ¶
type FieldConfiguration struct { TypeName string FieldName string // DisableDefaultMapping - instructs planner whether to use path mapping coming from Path field DisableDefaultMapping bool // Path - represents a json path to lookup for a field value in response json Path []string Arguments ArgumentsConfigurations // deprecated: use DataSourceConfiguration.FederationMetaData instead RequiresFields []string // UnescapeResponseJson set to true will allow fields (String,List,Object) // to be resolved from an escaped JSON string // e.g. {"response":"{\"foo\":\"bar\"}"} will be returned as {"foo":"bar"} when path is "response" // This way, it is possible to resolve a JSON string as part of the response without extra String encoding of the JSON UnescapeResponseJson bool // HasAuthorizationRule needs to be set to true if the Authorizer should be called for this field HasAuthorizationRule bool }
type FieldConfigurations ¶
type FieldConfigurations []FieldConfiguration
func (FieldConfigurations) ForTypeField ¶
func (f FieldConfigurations) ForTypeField(typeName, fieldName string) *FieldConfiguration
type InputTypeFieldUsageInfo ¶
type InputTypeFieldUsageInfo struct { // IsRootVariable is true if the field is a root variable, e.g. $id IsRootVariable bool // Count is the number of times this field usage was captured, it's usually 1 but can be higher if the field is used multiple times Count int // FieldName is the name of the field, e.g. "id" for this selection set: { id } FieldName string // FieldTypeName is the name of the field type, e.g. "ID" for this selection set: { id } FieldTypeName string // EnclosingTypeNames is a list of all possible enclosing types, e.g. ["User"] for the "id" field: { user { id } } EnclosingTypeNames []string // IsEnumField is true if the field is an enum IsEnumField bool // EnumValues is a list of all enum values that were used for this field EnumValues []string }
func (*InputTypeFieldUsageInfo) Equals ¶
func (t *InputTypeFieldUsageInfo) Equals(other InputTypeFieldUsageInfo) bool
type NodeSuggestion ¶
type NodeSuggestion struct { TypeName string FieldName string DataSourceHash DSHash Path string ParentPath string IsRootNode bool // contains filtered or unexported fields }
func (*NodeSuggestion) String ¶
func (n *NodeSuggestion) String() string
type NodeSuggestionHint ¶
type NodeSuggestionHint struct {
// contains filtered or unexported fields
}
type NodeSuggestions ¶
type NodeSuggestions []NodeSuggestion
func (NodeSuggestions) HasSuggestionForPath ¶
func (f NodeSuggestions) HasSuggestionForPath(typeName, fieldName, path string) (dsHash DSHash, ok bool)
func (NodeSuggestions) SuggestionsForPath ¶
func (f NodeSuggestions) SuggestionsForPath(typeName, fieldName, path string) (dsHashes []DSHash)
type Planner ¶
type Planner struct {
// contains filtered or unexported fields
}
func NewPlanner ¶
func NewPlanner(ctx context.Context, config Configuration) *Planner
NewPlanner creates a new Planner from the Configuration and a ctx object The context.Context object is used to determine the lifecycle of stateful DataSources It's important to note that stateful DataSources must be closed when they are no longer being used Stateful DataSources could be those that initiate a WebSocket connection to an origin, a database client, a streaming client, etc... All DataSources are initiated with the same context.Context object provided to the Planner. To ensure that there are no memory leaks, it's therefore important to add a cancel func or timeout to the context.Context At the time when the resolver and all operations should be garbage collected, ensure to first cancel or timeout the ctx object If you don't cancel the context.Context, the goroutines will run indefinitely and there's no reference left to stop them
func (*Planner) SetConfig ¶
func (p *Planner) SetConfig(config Configuration)
func (*Planner) SetDebugConfig ¶
func (p *Planner) SetDebugConfig(config DebugConfiguration)
type PlannerFactory ¶
type PlannerFactory interface { // Planner should return the DataSourcePlanner // closer is the closing channel for all stateful DataSources // At runtime, the Execution Engine will be instantiated with one global resolve.Closer. // Once the Closer gets closed, all stateful DataSources must close their connections and cleanup themselves. // They can do so by starting a goroutine on instantiation time that blocking reads on the resolve.Closer. // Once the Closer emits the close event, they have to terminate (e.g. close database connections). Planner(ctx context.Context) DataSourcePlanner }
type PlannerPathType ¶
type PlannerPathType int
const ( PlannerPathObject PlannerPathType = iota PlannerPathArrayItem PlannerPathNestedInArray )
type SchemaUsageInfo ¶
type SchemaUsageInfo struct { // OperationType is the type of the operation that was executed, e.g. query, mutation, subscription OperationType ast.OperationType // TypeFields is a list of all fields that were used to define the response shape TypeFields []TypeFieldUsageInfo // Arguments is a list of all arguments that were used on response fields Arguments []ArgumentUsageInfo // InputTypeFields is a list of all fields that were used to define the input shape InputTypeFields []InputTypeFieldUsageInfo }
func GetSchemaUsageInfo ¶
type SourceType ¶
type SourceType string
SourceType is used to determine the source of an argument
const ( ObjectFieldSource SourceType = "object_field" FieldArgumentSource SourceType = "field_argument" )
type SubscriptionConfiguration ¶
type SubscriptionConfiguration struct { Input string Variables resolve.Variables DataSource resolve.SubscriptionDataSource PostProcessing resolve.PostProcessingConfiguration }
type SubscriptionResponsePlan ¶
type SubscriptionResponsePlan struct { Response *resolve.GraphQLSubscription FlushInterval int64 }
func (*SubscriptionResponsePlan) PlanKind ¶
func (_ *SubscriptionResponsePlan) PlanKind() Kind
func (*SubscriptionResponsePlan) SetFlushInterval ¶
func (s *SubscriptionResponsePlan) SetFlushInterval(interval int64)
type SynchronousResponsePlan ¶
type SynchronousResponsePlan struct { Response *resolve.GraphQLResponse FlushInterval int64 }
func (*SynchronousResponsePlan) PlanKind ¶
func (_ *SynchronousResponsePlan) PlanKind() Kind
func (*SynchronousResponsePlan) SetFlushInterval ¶
func (s *SynchronousResponsePlan) SetFlushInterval(interval int64)
type TypeConfiguration ¶
type TypeConfiguration struct { TypeName string // RenameTo modifies the TypeName // so that a downstream Operation can contain a different TypeName than the upstream Schema // e.g. if the downstream Operation contains { ... on Human_api { height } } // the upstream Operation can be rewritten to { ... on Human { height }} // by setting RenameTo to Human // This way, Types can be suffixed / renamed in downstream Schemas while keeping the contract with the upstream ok RenameTo string }
type TypeConfigurations ¶
type TypeConfigurations []TypeConfiguration
func (*TypeConfigurations) RenameTypeNameOnMatchBytes ¶
func (t *TypeConfigurations) RenameTypeNameOnMatchBytes(typeName []byte) []byte
func (*TypeConfigurations) RenameTypeNameOnMatchStr ¶
func (t *TypeConfigurations) RenameTypeNameOnMatchStr(typeName string) string
type TypeFieldSource ¶
type TypeFieldSource struct { // IDs is a list of data source IDs that can be used to resolve the field IDs []string }
type TypeFieldUsageInfo ¶
type TypeFieldUsageInfo struct { // FieldName is the name of the field, e.g. "id" for this selection set: { id } FieldName string // FieldTypeName is the name of the field type, e.g. "ID" for this selection set: { id } FieldTypeName string // EnclosingTypeNames is a list of all possible enclosing types, e.g. ["User"] for the "id" field: { user { id } } EnclosingTypeNames []string // Path is a list of field names that lead to the field, e.g. ["user", "id"] for this selection set: { user { id } } Path []string // Source is a list of data source IDs that can be used to resolve the field Source TypeFieldSource }
func (*TypeFieldUsageInfo) Equals ¶
func (t *TypeFieldUsageInfo) Equals(other TypeFieldUsageInfo) bool
type TypeFields ¶
type TypeFields []TypeField
func (TypeFields) HasNode ¶
func (f TypeFields) HasNode(typeName, fieldName string) bool
func (TypeFields) HasNodeWithTypename ¶
func (f TypeFields) HasNodeWithTypename(typeName string) bool
type Visitor ¶
type Visitor struct {
Operation, Definition *ast.Document
Walker *astvisitor.Walker
Importer astimport.Importer
Config Configuration
OperationName string
// contains filtered or unexported fields
}
func (*Visitor) AllowVisitor ¶
func (v *Visitor) AllowVisitor(kind astvisitor.VisitorKind, ref int, visitor interface{}, skipFor astvisitor.SkipVisitors) bool
func (*Visitor) EnterDirective ¶
func (*Visitor) EnterDocument ¶
func (*Visitor) EnterField ¶
func (*Visitor) EnterInlineFragment ¶
func (*Visitor) EnterOperationDefinition ¶
func (*Visitor) EnterSelectionSet ¶
func (*Visitor) LeaveDocument ¶
func (*Visitor) LeaveField ¶
func (*Visitor) LeaveInlineFragment ¶
func (*Visitor) LeaveSelectionSet ¶
Source Files ¶
- abstract_selection_rewriter.go
- abstract_selection_rewriter_helpers.go
- abstract_selection_rewriter_info.go
- analyze_plan_kind.go
- configuration.go
- configuration_visitor.go
- datasource_configuration.go
- datasource_filter_visitor.go
- federation_metadata.go
- plan.go
- planner.go
- planner_configuration.go
- provides_fields_visitor.go
- required_fields_visitor.go
- schemausageinfo.go
- skip_include_visitor.go
- type_field.go
- visitor.go