diff --git a/examples/federation/go.mod b/examples/federation/go.mod index 882ee7fd46..99cc731858 100644 --- a/examples/federation/go.mod +++ b/examples/federation/go.mod @@ -49,7 +49,7 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect github.com/urfave/cli/v2 v2.27.7 // indirect - github.com/wundergraph/astjson v1.0.0 // indirect + github.com/wundergraph/astjson v1.1.0 // indirect github.com/wundergraph/cosmo/composition-go v0.0.0-20241020204711-78f240a77c99 // indirect github.com/wundergraph/cosmo/router v0.0.0-20251013094319-c611abf26b17 // indirect github.com/wundergraph/go-arena v1.1.0 // indirect diff --git a/examples/federation/go.sum b/examples/federation/go.sum index 4bcbb63885..df91a0612f 100644 --- a/examples/federation/go.sum +++ b/examples/federation/go.sum @@ -154,9 +154,8 @@ github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE= github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= -github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTBjW+SZK4mhxTTBVpxcqeBgWF1Rfmltbfk= -github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= -github.com/wundergraph/astjson v1.0.0/go.mod h1:h12D/dxxnedtLzsKyBLK7/Oe4TAoGpRVC9nDpDrZSWw= +github.com/wundergraph/astjson v1.1.0 h1:xORDosrZ87zQFJwNGe/HIHXqzpdHOFmqWgykCLVL040= +github.com/wundergraph/astjson v1.1.0/go.mod h1:h12D/dxxnedtLzsKyBLK7/Oe4TAoGpRVC9nDpDrZSWw= github.com/wundergraph/cosmo/composition-go v0.0.0-20241020204711-78f240a77c99 h1:TGXDYfDhwFLFTuNuCwkuqXT5aXGz47zcurXLfTBS9w4= github.com/wundergraph/cosmo/composition-go v0.0.0-20241020204711-78f240a77c99/go.mod h1:fUuOAUAXUFB/mlSkAaImGeE4A841AKR5dTMWhV4ibxI= github.com/wundergraph/cosmo/router v0.0.0-20251013094319-c611abf26b17 h1:GjO2E8LTf3U5JiQJCY4MmlRcAjVt7IvAbWFSgEjQdl8= diff --git a/execution/engine/execution_engine_cost_test.go b/execution/engine/execution_engine_cost_test.go new file mode 100644 index 0000000000..1e53d8a7a7 --- /dev/null +++ b/execution/engine/execution_engine_cost_test.go @@ -0,0 +1,1953 @@ +package engine + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/wundergraph/graphql-go-tools/execution/graphql" + "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource" + "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan" +) + +func TestExecutionEngine_Cost(t *testing.T) { + + t.Run("common on star wars scheme", func(t *testing.T) { + rootNodes := []plan.TypeField{ + {TypeName: "Query", FieldNames: []string{"hero", "droid"}}, + {TypeName: "Human", FieldNames: []string{"name", "height", "friends"}}, + {TypeName: "Droid", FieldNames: []string{"name", "primaryFunction", "friends"}}, + } + childNodes := []plan.TypeField{ + {TypeName: "Character", FieldNames: []string{"name", "friends"}}, + } + customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ + Fetch: &graphql_datasource.FetchConfiguration{ + URL: "https://example.com/", + Method: "GET", + }, + SchemaConfiguration: mustSchemaConfig( + t, + nil, + string(graphql.StarwarsSchema(t).RawSchema()), + ), + }) + + t.Run("droid with weighted plain fields", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + droid(id: "R2D2") { + name + primaryFunction + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, + }, + }}, + customConfig, + ), + }, + fields: []plan.FieldConfiguration{ + { + TypeName: "Query", FieldName: "droid", + Arguments: []plan.ArgumentConfiguration{ + { + Name: "id", + SourceType: plan.FieldArgumentSource, + RenderConfig: plan.RenderArgumentAsGraphQLValue, + }, + }, + }, + }, + expectedResponse: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, + expectedEstimatedCost: 18, // Query.droid (1) + droid.name (17) + }, + computeCosts(), + )) + + t.Run("droid with weighted plain fields and an argument", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + droid(id: "R2D2") { + name + primaryFunction + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Query", FieldName: "droid"}: { + ArgumentWeights: map[string]int{"id": 3}, + HasWeight: false, + }, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, + }, + }}, + customConfig, + ), + }, + fields: []plan.FieldConfiguration{ + { + TypeName: "Query", FieldName: "droid", + Arguments: []plan.ArgumentConfiguration{ + { + Name: "id", + SourceType: plan.FieldArgumentSource, + RenderConfig: plan.RenderArgumentAsGraphQLValue, + }, + }, + }, + }, + expectedResponse: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, + expectedEstimatedCost: 21, // Query.droid (1) + Query.droid.id (3) + droid.name (17) + }, + computeCosts(), + )) + + t.Run("negative weights - cost is never negative", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + droid(id: "R2D2") { + name + primaryFunction + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Query", FieldName: "droid"}: { + HasWeight: true, + Weight: -10, // Negative field weight + ArgumentWeights: map[string]int{"id": -5}, // Negative argument weight + }, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: -3}, + {TypeName: "Droid", FieldName: "primaryFunction"}: {HasWeight: true, Weight: -2}, + }, + Types: map[string]int{ + "Droid": -1, // Negative type weight + }, + }}, + customConfig, + ), + }, + fields: []plan.FieldConfiguration{ + { + TypeName: "Query", FieldName: "droid", + Arguments: []plan.ArgumentConfiguration{ + { + Name: "id", + SourceType: plan.FieldArgumentSource, + RenderConfig: plan.RenderArgumentAsGraphQLValue, + }, + }, + }, + }, + expectedResponse: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, + // All weights are negative. + // But cost should be floored to 0 (never negative) + expectedEstimatedCost: 0, + }, + computeCosts(), + )) + + t.Run("hero field has weight (returns interface) and with concrete fragment", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + name + ... on Human { height } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke Skywalker","height":"12"}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{RootNodes: rootNodes, ChildNodes: childNodes, CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Query", FieldName: "hero"}: {HasWeight: true, Weight: 2}, + {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 3}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 7}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, + }, + Types: map[string]int{ + "Human": 13, + }, + }}, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"name":"Luke Skywalker","height":"12"}}}`, + expectedEstimatedCost: 22, // Query.hero (2) + Human.height (3) + Droid.name (17=max(7, 17)) + }, + computeCosts(), + )) + + t.Run("hero field has no weight (returns interface) and with concrete fragment", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { name } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke Skywalker"}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{RootNodes: rootNodes, ChildNodes: childNodes, CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 7}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, + }, + Types: map[string]int{ + "Human": 13, + "Droid": 11, + }, + }}, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"name":"Luke Skywalker"}}}`, + expectedEstimatedCost: 30, // Query.Human (13) + Droid.name (17=max(7, 17)) + }, + computeCosts(), + )) + + t.Run("query hero without assumedSize on friends", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + friends { + ...on Droid { name primaryFunction } + ...on Human { name height } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ + {"__typename":"Human","name":"Luke Skywalker","height":"12"}, + {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} + ]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, + }, + Types: map[string]int{ + "Human": 7, + "Droid": 5, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, + expectedEstimatedCost: 127, // Query.hero(max(7,5))+10*(Human(max(7,5))+Human.name(2)+Human.height(1)+Droid.name(2)) + }, + computeCosts(), + )) + + t.Run("query hero with assumedSize on friends", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + friends { + ...on Droid { name primaryFunction } + ...on Human { name height } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ + {"__typename":"Human","name":"Luke Skywalker","height":"12"}, + {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} + ]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Human", FieldName: "friends"}: {AssumedSize: 5}, + {TypeName: "Droid", FieldName: "friends"}: {AssumedSize: 20}, + }, + Types: map[string]int{ + "Human": 7, + "Droid": 5, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, + expectedEstimatedCost: 247, // Query.hero(max(7,5))+ 20 * (7+2+2+1) + // We pick maximum on every path independently. This is to reveal the upper boundary. + // Query.hero: picked maximum weight (Human=7) out of two types (Human, Droid) + // Query.hero.friends: the max possible weight (7) is for implementing class Human + // of the returned type of Character; the multiplier picked for the Droid since + // it is the maximum possible value - we considered the enclosing type that contains it. + }, + computeCosts(), + )) + + t.Run("query hero with assumedSize on friends and weight defined", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + friends { + ...on Droid { name primaryFunction } + ...on Human { name height } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ + {"__typename":"Human","name":"Luke Skywalker","height":"12"}, + {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} + ]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Human", FieldName: "friends"}: {HasWeight: true, Weight: 3}, + {TypeName: "Droid", FieldName: "friends"}: {HasWeight: true, Weight: 4}, + {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Human", FieldName: "friends"}: {AssumedSize: 5}, + {TypeName: "Droid", FieldName: "friends"}: {AssumedSize: 20}, + }, + Types: map[string]int{ + "Human": 7, + "Droid": 5, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, + expectedEstimatedCost: 187, // Query.hero(max(7,5))+ 20 * (4+2+2+1) + }, + computeCosts(), + )) + + t.Run("query hero with empty cost structures", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + friends { + ...on Droid { name primaryFunction } + ...on Human { name height } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ + {"__typename":"Human","name":"Luke Skywalker","height":"12"}, + {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} + ]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{}, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, + expectedEstimatedCost: 11, // Query.hero(max(1,1))+ 10 * 1 + }, + computeCosts(), + )) + + // Actual cost tests - verifies that actual cost uses real list sizes from response + // rather than estimated/assumed sizes + + t.Run("actual cost with list field - 2 items instead of default 10", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + friends { + ...on Droid { name primaryFunction } + ...on Human { name height } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + // Response has 2 friends (not 10 as estimated) + sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ + {"__typename":"Human","name":"Luke Skywalker","height":"12"}, + {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} + ]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, + }, + Types: map[string]int{ + "Human": 7, + "Droid": 5, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, + // Estimated with default list size 10: hero(7) + 10 * (7 + 2 + 2 + 1) = 127 + expectedEstimatedCost: 127, + // Actual uses real list size 2: hero(7) + 2 * (7 + 2 + 2 + 1) = 31 + expectedActualCost: 31, + }, + computeCosts(), + )) + + t.Run("actual cost with empty list", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + hero { + friends { + ...on Droid { name } + ...on Human { name } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + // Response has empty friends array + sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, + }, + Types: map[string]int{ + "Human": 7, + "Droid": 5, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"friends":[]}}}`, + // Estimated with default list size 10: hero(7) + 10 * (7 + 2 + 2) = 117 + expectedEstimatedCost: 117, + // Actual with empty list: hero(7) + 1 * (7 + 2 + 2) = 18 + // We consider empty lists as lists containing one item to account for the + // resolver work. + expectedActualCost: 18, + }, + computeCosts(), + )) + + t.Run("named fragment on interface", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: ` + fragment CharacterFields on Character { + name + friends { name } + } + { hero { ...CharacterFields } } + `, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke","friends":[{"name":"Leia"}]}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Query", FieldName: "hero"}: {HasWeight: true, Weight: 2}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 3}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 5}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Human", FieldName: "friends"}: {AssumedSize: 4}, + {TypeName: "Droid", FieldName: "friends"}: {AssumedSize: 6}, + }, + Types: map[string]int{ + "Human": 2, + "Droid": 3, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"name":"Luke","friends":[{"name":"Leia"}]}}}`, + // Cost calculation: + // Query.hero: 2 + // Character.name: max(Human.name=3, Droid.name=5) = 5 + // friends listSize: max(4, 6) = 6 + // Character type: max(Human=2, Droid=3) = 3 + // name: max(Human.name=3, Droid.name=5) = 5 + // Total: 2 + 5 + 6 * (3 + 5) + expectedEstimatedCost: 55, + }, + computeCosts(), + )) + + t.Run("named fragment with concrete type", runWithoutError( + ExecutionEngineTestCase{ + schema: graphql.StarwarsSchema(t), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: ` + fragment HumanFields on Human { + name + height + } + { hero { ...HumanFields } } + `, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke","height":"1.72"}}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Query", FieldName: "hero"}: {HasWeight: true, Weight: 2}, + {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 3}, + {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 7}, + {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 5}, + }, + Types: map[string]int{ + "Human": 1, + "Droid": 1, + }, + }, + }, + customConfig, + ), + }, + expectedResponse: `{"data":{"hero":{"name":"Luke","height":"1.72"}}}`, + // Total: 2 + 3 + 7 + expectedEstimatedCost: 12, + }, + computeCosts(), + )) + + }) + + t.Run("union types", func(t *testing.T) { + unionSchema := ` + type Query { + search(term: String!): [SearchResult!] + } + union SearchResult = User | Post | Comment + type User @key(fields: "id") { + id: ID! + name: String! + email: String! + } + type Post @key(fields: "id") { + id: ID! + title: String! + body: String! + } + type Comment @key(fields: "id") { + id: ID! + text: String! + } + ` + schema, err := graphql.NewSchemaFromString(unionSchema) + require.NoError(t, err) + + rootNodes := []plan.TypeField{ + {TypeName: "Query", FieldNames: []string{"search"}}, + {TypeName: "User", FieldNames: []string{"id", "name", "email"}}, + {TypeName: "Post", FieldNames: []string{"id", "title", "body"}}, + {TypeName: "Comment", FieldNames: []string{"id", "text"}}, + } + childNodes := []plan.TypeField{} + customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ + Fetch: &graphql_datasource.FetchConfiguration{ + URL: "https://example.com/", + Method: "GET", + }, + SchemaConfiguration: mustSchemaConfig(t, nil, unionSchema), + }) + fieldConfig := []plan.FieldConfiguration{ + { + TypeName: "Query", + FieldName: "search", + Path: []string{"search"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "term", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + } + + t.Run("union with all member types", runWithoutError( + ExecutionEngineTestCase{ + schema: schema, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + search(term: "test") { + ... on User { name email } + ... on Post { title body } + ... on Comment { text } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"search":[{"__typename":"User","name":"John","email":"john@test.com"}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "User", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "User", FieldName: "email"}: {HasWeight: true, Weight: 3}, + {TypeName: "Post", FieldName: "title"}: {HasWeight: true, Weight: 4}, + {TypeName: "Post", FieldName: "body"}: {HasWeight: true, Weight: 5}, + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "search"}: {AssumedSize: 5}, + }, + Types: map[string]int{ + "User": 2, + "Post": 3, + "Comment": 1, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"search":[{"name":"John","email":"john@test.com"}]}}`, + // search listSize: 10 + // For each SearchResult, use max across all union members: + // Type weight: max(User=2, Post=3, Comment=1) = 3 + // Fields: all fields from all fragments are counted + // (2 + 3) + (4 + 5) + (1) = 15 + // TODO: this is not correct, we should pick a maximum sum among types implementing union. + // 9 should be used instead of 15 + // Total: 5 * (3 + 15) + expectedEstimatedCost: 90, + }, + computeCosts(), + )) + + t.Run("union with weighted search field", runWithoutError( + ExecutionEngineTestCase{ + schema: schema, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + search(term: "test") { + ... on User { name } + ... on Post { title } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"search":[{"__typename":"User","name":"John"}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "User", FieldName: "name"}: {HasWeight: true, Weight: 2}, + {TypeName: "Post", FieldName: "title"}: {HasWeight: true, Weight: 5}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "search"}: {AssumedSize: 3}, + }, + Types: map[string]int{ + "User": 6, + "Post": 10, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"search":[{"name":"John"}]}}`, + // Query.search: max(User=10, Post=6) + // search listSize: 3 + // Union members: + // All fields from all fragments: User.name(2) + Post.title(5) + // Total: 3 * (10+2+5) + // TODO: we might correct this by counting only members of one implementing types + // of a union when fragments are used. + expectedEstimatedCost: 51, + }, + computeCosts(), + )) + }) + + t.Run("listSize", func(t *testing.T) { + listSchema := ` + type Query { + items(first: Int, last: Int): [Item!] + } + type Item @key(fields: "id") { + id: ID + } + ` + schemaSlicing, err := graphql.NewSchemaFromString(listSchema) + require.NoError(t, err) + rootNodes := []plan.TypeField{ + {TypeName: "Query", FieldNames: []string{"items"}}, + {TypeName: "Item", FieldNames: []string{"id"}}, + } + childNodes := []plan.TypeField{} + customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ + Fetch: &graphql_datasource.FetchConfiguration{ + URL: "https://example.com/", + Method: "GET", + }, + SchemaConfiguration: mustSchemaConfig(t, nil, listSchema), + }) + fieldConfig := []plan.FieldConfiguration{ + { + TypeName: "Query", + FieldName: "items", + Path: []string{"items"}, + Arguments: []plan.ArgumentConfiguration{ + { + Name: "first", + SourceType: plan.FieldArgumentSource, + RenderConfig: plan.RenderArgumentAsGraphQLValue, + }, + { + Name: "last", + SourceType: plan.FieldArgumentSource, + RenderConfig: plan.RenderArgumentAsGraphQLValue, + }, + }, + }, + } + t.Run("multiple slicing arguments as literals", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaSlicing, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `query MultipleSlicingArguments { + items(first: 5, last: 12) { id } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"items":[ {"id":"2"}, {"id":"3"} ]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "items"}: { + AssumedSize: 8, + SlicingArguments: []string{"first", "last"}, + }, + }, + Types: map[string]int{ + "Item": 3, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"items":[{"id":"2"},{"id":"3"}]}}`, + expectedEstimatedCost: 48, // slicingArgument(12) * (Item(3)+Item.id(1)) + }, + computeCosts(), + )) + t.Run("slicing argument as a variable", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaSlicing, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `query SlicingWithVariable($limit: Int!) { + items(first: $limit) { id } + }`, + Variables: []byte(`{"limit": 25}`), + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"items":[ {"id":"2"}, {"id":"3"} ]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "items"}: { + AssumedSize: 8, + SlicingArguments: []string{"first", "last"}, + }, + }, + Types: map[string]int{ + "Item": 3, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"items":[{"id":"2"},{"id":"3"}]}}`, + expectedEstimatedCost: 100, // slicingArgument($limit=25) * (Item(3)+Item.id(1)) + }, + computeCosts(), + )) + t.Run("slicing argument not provided falls back to assumedSize", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaSlicing, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `query NoSlicingArg { + items { id } + }`, + // No slicing arguments provided - should fall back to assumedSize + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"items":[{"id":"1"},{"id":"2"}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "items"}: { + AssumedSize: 15, + SlicingArguments: []string{"first", "last"}, + }, + }, + Types: map[string]int{ + "Item": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"items":[{"id":"1"},{"id":"2"}]}}`, + expectedEstimatedCost: 45, // Total: 15 * (2 + 1) + }, + computeCosts(), + )) + t.Run("zero slicing argument falls back to assumedSize", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaSlicing, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `query ZeroSlicing { + items(first: 0) { id } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"items":[]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "items"}: { + AssumedSize: 20, + SlicingArguments: []string{"first", "last"}, + }, + }, + Types: map[string]int{ + "Item": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"items":[]}}`, + expectedEstimatedCost: 60, // 20 * (2 + 1) + }, + computeCosts(), + )) + t.Run("negative slicing argument falls back to assumedSize", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaSlicing, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `query NegativeSlicing { + items(first: -5) { id } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", expectedPath: "/", expectedBody: "", + sendResponseBody: `{"data":{"items":[]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "items"}: { + AssumedSize: 25, + SlicingArguments: []string{"first", "last"}, + }, + }, + Types: map[string]int{ + "Item": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"items":[]}}`, + expectedEstimatedCost: 75, // 25 * (2 + 1) + }, + computeCosts(), + )) + + }) + + t.Run("nested lists with compounding multipliers", func(t *testing.T) { + nestedSchema := ` + type Query { + users(first: Int): [User!] + } + type User @key(fields: "id") { + id: ID! + posts(first: Int): [Post!] + } + type Post @key(fields: "id") { + id: ID! + comments(first: Int): [Comment!] + } + type Comment @key(fields: "id") { + id: ID! + text: String! + } + ` + schemaNested, err := graphql.NewSchemaFromString(nestedSchema) + require.NoError(t, err) + + rootNodes := []plan.TypeField{ + {TypeName: "Query", FieldNames: []string{"users"}}, + {TypeName: "User", FieldNames: []string{"id", "posts"}}, + {TypeName: "Post", FieldNames: []string{"id", "comments"}}, + {TypeName: "Comment", FieldNames: []string{"id", "text"}}, + } + childNodes := []plan.TypeField{} + customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ + Fetch: &graphql_datasource.FetchConfiguration{ + URL: "https://example.com/", + Method: "GET", + }, + SchemaConfiguration: mustSchemaConfig(t, nil, nestedSchema), + }) + fieldConfig := []plan.FieldConfiguration{ + { + TypeName: "Query", FieldName: "users", Path: []string{"users"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + { + TypeName: "User", FieldName: "posts", Path: []string{"posts"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + { + TypeName: "Post", FieldName: "comments", Path: []string{"comments"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + } + + t.Run("nested lists with slicing arguments", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + users(first: 10) { + posts(first: 5) { + comments(first: 3) { text } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "User", FieldName: "posts"}: { + AssumedSize: 50, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Post", FieldName: "comments"}: { + AssumedSize: 20, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + "Post": 3, + "Comment": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, + // Cost calculation: + // users(first:10): multiplier 10 + // User type weight: 4 + // posts(first:5): multiplier 5 + // Post type weight: 3 + // comments(first:3): multiplier 3 + // Comment type weight: 2 + // text weight: 1 + // Total: 10 * (4 + 5 * (3 + 3 * (2 + 1))) + expectedEstimatedCost: 640, + }, + computeCosts(), + )) + + t.Run("nested lists fallback to assumedSize when slicing arg not provided", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + users(first: 2) { + posts { + comments(first: 4) { text } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"users":[{"posts":[{"comments":[{"text":"hi"}]}]}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "User", FieldName: "posts"}: { + AssumedSize: 50, // no slicing arg, should use this + }, + {TypeName: "Post", FieldName: "comments"}: { + AssumedSize: 20, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + "Post": 3, + "Comment": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"hi"}]}]}]}}`, + // Cost calculation: + // users(first:2): multiplier 2 + // User type weight: 4 + // posts (no arg): assumedSize 50 + // Post type weight: 3 + // comments(first:4): multiplier 4 + // Comment type weight: 2 + // text weight: 1 + // Total: 2 * (4 + 50 * (3 + 4 * (2 + 1))) + expectedEstimatedCost: 1508, + }, + computeCosts(), + )) + + t.Run("actual cost for nested lists - 1 item at each level", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + users(first: 10) { + posts(first: 5) { + comments(first: 3) { text } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + // Response has 1 user with 1 post with 1 comment + sendResponseBody: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "User", FieldName: "posts"}: { + AssumedSize: 50, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Post", FieldName: "comments"}: { + AssumedSize: 20, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + "Post": 3, + "Comment": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, + // Estimated cost with slicing arguments (10, 5, 3): + // Total: 10 * (4 + 5 * (3 + 3 * (2 + 1))) = 640 + expectedEstimatedCost: 640, + // Actual cost with 1 item at each level: + // Total: 1 * (4 + 1 * (3 + 1 * (2 + 1))) = 10 + expectedActualCost: 10, + }, + computeCosts(), + )) + + t.Run("actual cost for nested lists - varying sizes", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + users(first: 10) { + posts(first: 5) { + comments(first: 3) { text } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + // Response has 2 users, each with 2 posts, each with 3 comments + sendResponseBody: `{"data":{"users":[ + {"posts":[ + {"comments":[{"text":"a"},{"text":"b"},{"text":"c"}]}, + {"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]}, + {"posts":[ + {"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]}, + {"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "User", FieldName: "posts"}: { + AssumedSize: 50, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Post", FieldName: "comments"}: { + AssumedSize: 20, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + "Post": 3, + "Comment": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"a"},{"text":"b"},{"text":"c"}]},{"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]},{"posts":[{"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]},{"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, + expectedEstimatedCost: 640, + // Actual cost: 2 * (4 + 2 * (3 + 3 * (2 + 1))) = 56 + expectedActualCost: 56, + }, + computeCosts(), + )) + + t.Run("actual cost for nested lists - uneven sizes", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + users(first: 10) { + posts(first: 5) { + comments(first: 2) { text } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + // Response has 2 users, with 1.5 posts each, each with 3 comments + sendResponseBody: `{"data":{"users":[ + {"posts":[ + {"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]}, + {"posts":[ + {"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]}, + {"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "User", FieldName: "posts"}: { + AssumedSize: 50, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Post", FieldName: "comments"}: { + AssumedSize: 20, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + "Post": 3, + "Comment": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]},{"posts":[{"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]},{"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, + // Estimated : 10 * (4 + 5 * (3 + 2 * (2 + 1))) = 490 + expectedEstimatedCost: 490, + // Actual cost: 2 * (4 + 1.5 * (3 + 3 * (2 + 1))) = 44 + expectedActualCost: 44, + }, + computeCosts(), + )) + + t.Run("actual cost for root-level list - no parent", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ users(first: 10) { id } }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + // Response has 3 users at the root level + sendResponseBody: `{"data":{"users":[ + {"id":"1"}, + {"id":"2"}, + {"id":"3"}]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "User", FieldName: "id"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"id":"1"},{"id":"2"},{"id":"3"}]}}`, + // Estimated: 10 * (4 + 1) = 50 + expectedEstimatedCost: 50, + // Actual cost: 3 users at root + // 3 * (4 + 1) = 15 + expectedActualCost: 15, + }, + computeCosts(), + )) + + t.Run("mixed empty and non-empty lists - averaging behavior", runWithoutError( + ExecutionEngineTestCase{ + schema: schemaNested, + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + users(first: 10) { + posts(first: 5) { + comments(first: 3) { text } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"users":[ + {"posts":[ + {"comments":[{"text":"a"},{"text":"b"}]}, + {"comments":[{"text":"c"},{"text":"d"}]} + ]}, + {"posts":[]}, + {"posts":[ + {"comments":[]} + ]} + ]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: rootNodes, + ChildNodes: childNodes, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "users"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "User", FieldName: "posts"}: { + AssumedSize: 50, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Post", FieldName: "comments"}: { + AssumedSize: 20, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "User": 4, + "Post": 3, + "Comment": 2, + }, + }, + }, + customConfig, + ), + }, + fields: fieldConfig, + expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"a"},{"text":"b"}]},{"comments":[{"text":"c"},{"text":"d"}]}]},{"posts":[]},{"posts":[{"comments":[]}]}]}}`, + expectedEstimatedCost: 640, // 10 * (4 + 5 * (3 + 3 * (2 + 1))) + // Actual cost with mixed empty/non-empty lists: + // Users: 3 items, multiplier 3.0 + // Posts: 3 items, 3 parents => multiplier 1.0 (avg) + // Comments: 4 items, 3 parents => multiplier 1.33 (avg) + // + // Calculation: + // Comments: RoundToEven((2 + 1) * 1.33) ~= 4 + // Posts: RoundToEven((3 + 4) * 1.00) = 7 + // Users: RoundToEven((4 + 7) * 3.00) = 33 + // + // Empty lists are included in the averaging: + expectedActualCost: 33, + }, + computeCosts(), + )) + + t.Run("deeply nested lists with fractional multipliers - compounding rounding", runWithoutError( + ExecutionEngineTestCase{ + schema: func() *graphql.Schema { + deepSchema := ` + type Query { + level1(first: Int): [Level1!] + } + type Level1 @key(fields: "id") { + id: ID! + level2(first: Int): [Level2!] + } + type Level2 @key(fields: "id") { + id: ID! + level3(first: Int): [Level3!] + } + type Level3 @key(fields: "id") { + id: ID! + level4(first: Int): [Level4!] + } + type Level4 @key(fields: "id") { + id: ID! + level5(first: Int): [Level5!] + } + type Level5 @key(fields: "id") { + id: ID! + value: String! + } + ` + s, err := graphql.NewSchemaFromString(deepSchema) + require.NoError(t, err) + return s + }(), + operation: func(t *testing.T) graphql.Request { + return graphql.Request{ + Query: `{ + level1(first: 10) { + level2(first: 10) { + level3(first: 10) { + level4(first: 10) { + level5(first: 10) { + value + } + } + } + } + } + }`, + } + }, + dataSources: []plan.DataSource{ + mustGraphqlDataSourceConfiguration(t, "id", + mustFactory(t, + testNetHttpClient(t, roundTripperTestCase{ + expectedHost: "example.com", + expectedPath: "/", + expectedBody: "", + sendResponseBody: `{"data":{"level1":[ + {"level2":[ + {"level3":[ + {"level4":[ + {"level5":[{"value":"a"}]}, + {"level5":[{"value":"b"},{"value":"c"}]} + ]}, + {"level4":[ + {"level5":[{"value":"d"}]} + ]} + ]}, + {"level3":[ + {"level4":[ + {"level5":[{"value":"e"}]} + ]} + ]} + ]}, + {"level2":[ + {"level3":[ + {"level4":[ + {"level5":[{"value":"f"},{"value":"g"}]}, + {"level5":[{"value":"h"}]} + ]}, + {"level4":[ + {"level5":[{"value":"i"}]} + ]} + ]} + ]}, + {"level2":[ + {"level3":[ + {"level4":[ + {"level5":[{"value":"j"}]}, + {"level5":[{"value":"k"}]} + ]}, + {"level4":[ + {"level5":[{"value":"l"}]}, + {"level5":[{"value":"m"}]} + ]} + ]} + ]} + ]}}`, + sendStatusCode: 200, + }), + ), + &plan.DataSourceMetadata{ + RootNodes: []plan.TypeField{ + {TypeName: "Query", FieldNames: []string{"level1"}}, + {TypeName: "Level1", FieldNames: []string{"id", "level2"}}, + {TypeName: "Level2", FieldNames: []string{"id", "level3"}}, + {TypeName: "Level3", FieldNames: []string{"id", "level4"}}, + {TypeName: "Level4", FieldNames: []string{"id", "level5"}}, + {TypeName: "Level5", FieldNames: []string{"id", "value"}}, + }, + ChildNodes: []plan.TypeField{}, + CostConfig: &plan.DataSourceCostConfig{ + Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ + {TypeName: "Level5", FieldName: "value"}: {HasWeight: true, Weight: 1}, + }, + ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ + {TypeName: "Query", FieldName: "level1"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Level1", FieldName: "level2"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Level2", FieldName: "level3"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Level3", FieldName: "level4"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + {TypeName: "Level4", FieldName: "level5"}: { + AssumedSize: 100, + SlicingArguments: []string{"first"}, + }, + }, + Types: map[string]int{ + "Level1": 1, + "Level2": 1, + "Level3": 1, + "Level4": 1, + "Level5": 1, + }, + }, + }, + mustConfiguration(t, graphql_datasource.ConfigurationInput{ + Fetch: &graphql_datasource.FetchConfiguration{ + URL: "https://example.com/", + Method: "GET", + }, + SchemaConfiguration: mustSchemaConfig(t, nil, ` + type Query { + level1(first: Int): [Level1!] + } + type Level1 @key(fields: "id") { + id: ID! + level2(first: Int): [Level2!] + } + type Level2 @key(fields: "id") { + id: ID! + level3(first: Int): [Level3!] + } + type Level3 @key(fields: "id") { + id: ID! + level4(first: Int): [Level4!] + } + type Level4 @key(fields: "id") { + id: ID! + level5(first: Int): [Level5!] + } + type Level5 @key(fields: "id") { + id: ID! + value: String! + } + `), + }), + ), + }, + fields: []plan.FieldConfiguration{ + { + TypeName: "Query", FieldName: "level1", Path: []string{"level1"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + { + TypeName: "Level1", FieldName: "level2", Path: []string{"level2"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + { + TypeName: "Level2", FieldName: "level3", Path: []string{"level3"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + { + TypeName: "Level3", FieldName: "level4", Path: []string{"level4"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + { + TypeName: "Level4", FieldName: "level5", Path: []string{"level5"}, + Arguments: []plan.ArgumentConfiguration{ + {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, + }, + }, + }, + expectedResponse: `{"data":{"level1":[{"level2":[{"level3":[{"level4":[{"level5":[{"value":"a"}]},{"level5":[{"value":"b"},{"value":"c"}]}]},{"level4":[{"level5":[{"value":"d"}]}]}]},{"level3":[{"level4":[{"level5":[{"value":"e"}]}]}]}]},{"level2":[{"level3":[{"level4":[{"level5":[{"value":"f"},{"value":"g"}]},{"level5":[{"value":"h"}]}]},{"level4":[{"level5":[{"value":"i"}]}]}]}]},{"level2":[{"level3":[{"level4":[{"level5":[{"value":"j"}]},{"level5":[{"value":"k"}]}]},{"level4":[{"level5":[{"value":"l"}]},{"level5":[{"value":"m"}]}]}]}]}]}}`, + expectedEstimatedCost: 211110, + // Actual cost with fractional multipliers: + // Level5: 13 items, 11 parents => multiplier 1.18 (13/11 = 1.181818...) + // Level4: 11 items, 7 parents => multiplier 1.57 (11/7 = 1.571428...) + // Level3: 7 items, 4 parents => multiplier 1.75 (7/4 = 1.75) + // Level2: 4 items, 3 parents => multiplier 1.33 (4/3 = 1.333...) + // Level1: 3 items, 1 parent => multiplier 3.0 + // + // Ideal calculation without rounding: + // cost = 3 * (1 + 1.33 * (1 + 1.75 * (1 + 1.57 * (1 + 1.18 * (1 + 1))))) + // = 50.806584 ~= 51 + // + // Current implementation: + // Level5: RoundToEven((1 + 1) * 1.18) = 2 + // Level4: RoundToEven((1 + 2) * 1.57) = 5 + // Level3: RoundToEven((1 + 5) * 1.75) = 10 (rounds to even) + // Level2: RoundToEven((1 + 10) * 1.33) = 15 + // Level1: RoundToEven((1 + 15) * 3.00) = 48 + // + // The compounding rounding error: 48 vs 51 (6% underestimate) + expectedActualCost: 48, + }, + computeCosts(), + )) + }) +} diff --git a/execution/engine/execution_engine_test.go b/execution/engine/execution_engine_test.go index 9c3370efe0..0f7c48ac00 100644 --- a/execution/engine/execution_engine_test.go +++ b/execution/engine/execution_engine_test.go @@ -17,7 +17,6 @@ import ( "github.com/sebdah/goldie/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "google.golang.org/grpc" "github.com/wundergraph/graphql-go-tools/execution/federationtesting" "github.com/wundergraph/graphql-go-tools/execution/graphql" @@ -61,13 +60,104 @@ func mustFactory(t testing.TB, httpClient *http.Client) plan.PlannerFactory[grap return factory } -func mustFactoryGRPC(t testing.TB, grpcClient grpc.ClientConnInterface) plan.PlannerFactory[graphql_datasource.Configuration] { - t.Helper() +func runExecutionTest(testCase ExecutionEngineTestCase, withError bool, expectedErrorMessage string, options ...executionTestOptions) func(t *testing.T) { + return func(t *testing.T) { + t.Helper() - factory, err := graphql_datasource.NewFactoryGRPC(context.Background(), grpcClient) - require.NoError(t, err) + if testCase.skipReason != "" { + t.Skip(testCase.skipReason) + } - return factory + engineConf := NewConfiguration(testCase.schema) + engineConf.SetDataSources(testCase.dataSources) + engineConf.SetFieldConfigurations(testCase.fields) + engineConf.SetCustomResolveMap(testCase.customResolveMap) + + engineConf.plannerConfig.Debug = plan.DebugConfiguration{ + // PrintOperationTransformations: true, + // PrintPlanningPaths: true, + // PrintNodeSuggestions: true, + // PrintQueryPlans: true, + // ConfigurationVisitor: true, + // PlanningVisitor: true, + // DatasourceVisitor: true, + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var opts _executionTestOptions + for _, option := range options { + option(&opts) + } + engineConf.plannerConfig.BuildFetchReasons = opts.propagateFetchReasons + engineConf.plannerConfig.ValidateRequiredExternalFields = opts.validateRequiredExternalFields + engineConf.plannerConfig.ComputeCosts = opts.computeCosts + engineConf.plannerConfig.StaticCostDefaultListSize = 10 + engineConf.plannerConfig.RelaxSubgraphOperationFieldSelectionMergingNullability = opts.relaxFieldSelectionMergingNullability + resolveOpts := resolve.ResolverOptions{ + MaxConcurrency: 1024, + ResolvableOptions: opts.resolvableOptions, + ApolloRouterCompatibilitySubrequestHTTPError: opts.apolloRouterCompatibilitySubrequestHTTPError, + PropagateFetchReasons: opts.propagateFetchReasons, + ValidateRequiredExternalFields: opts.validateRequiredExternalFields, + } + engine, err := NewExecutionEngine(ctx, abstractlogger.Noop{}, engineConf, resolveOpts) + require.NoError(t, err) + + operation := testCase.operation(t) + resultWriter := graphql.NewEngineResultWriter() + execCtx, execCtxCancel := context.WithCancel(context.Background()) + defer execCtxCancel() + err = engine.Execute(execCtx, &operation, &resultWriter, testCase.engineOptions...) + actualResponse := resultWriter.String() + + if testCase.indentJSON { + dst := new(bytes.Buffer) + require.NoError(t, json.Indent(dst, []byte(actualResponse), "", " ")) + actualResponse = dst.String() + } + + if testCase.expectedFixture != "" { + g := goldie.New(t, goldie.WithFixtureDir("testdata"), goldie.WithNameSuffix(".json")) + g.Assert(t, testCase.expectedFixture, []byte(actualResponse)) + return + } + + if withError { + require.Error(t, err) + if expectedErrorMessage != "" { + assert.Equal(t, expectedErrorMessage, err.Error()) + } + } else { + require.NoError(t, err) + } + + if testCase.expectedJSONResponse != "" { + assert.JSONEq(t, testCase.expectedJSONResponse, actualResponse) + } + + if testCase.expectedResponse != "" { + assert.Equal(t, testCase.expectedResponse, actualResponse) + } + + if testCase.expectedEstimatedCost != 0 { + gotCost := operation.EstimatedCost() + require.Equal(t, testCase.expectedEstimatedCost, gotCost) + } + + if testCase.expectedActualCost != 0 { + gotActualCost := operation.ActualCost() + require.Equal(t, testCase.expectedActualCost, gotActualCost) + } + } +} + +func runWithAndCompareError(testCase ExecutionEngineTestCase, expectedErrorMessage string, options ...executionTestOptions) func(t *testing.T) { + return runExecutionTest(testCase, true, expectedErrorMessage, options...) +} + +func runWithoutError(testCase ExecutionEngineTestCase, options ...executionTestOptions) func(t *testing.T) { + return runExecutionTest(testCase, false, "", options...) } func mustGraphqlDataSourceConfiguration(t *testing.T, id string, factory plan.PlannerFactory[graphql_datasource.Configuration], metadata *plan.DataSourceMetadata, customConfig graphql_datasource.Configuration) plan.DataSourceConfiguration[graphql_datasource.Configuration] { @@ -262,113 +352,6 @@ func relaxFieldSelectionMergingNullability() executionTestOptions { } func TestExecutionEngine_Execute(t *testing.T) { - run := func(testCase ExecutionEngineTestCase, withError bool, expectedErrorMessage string, options ...executionTestOptions) func(t *testing.T) { - t.Helper() - - return func(t *testing.T) { - t.Helper() - - if testCase.skipReason != "" { - t.Skip(testCase.skipReason) - } - - engineConf := NewConfiguration(testCase.schema) - engineConf.SetDataSources(testCase.dataSources) - engineConf.SetFieldConfigurations(testCase.fields) - engineConf.SetCustomResolveMap(testCase.customResolveMap) - - engineConf.plannerConfig.Debug = plan.DebugConfiguration{ - // PrintOperationTransformations: true, - // PrintPlanningPaths: true, - // PrintNodeSuggestions: true, - // PrintQueryPlans: true, - // ConfigurationVisitor: true, - // PlanningVisitor: true, - // DatasourceVisitor: true, - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var opts _executionTestOptions - for _, option := range options { - option(&opts) - } - engineConf.plannerConfig.BuildFetchReasons = opts.propagateFetchReasons - engineConf.plannerConfig.ValidateRequiredExternalFields = opts.validateRequiredExternalFields - engineConf.plannerConfig.ComputeCosts = opts.computeCosts - engineConf.plannerConfig.StaticCostDefaultListSize = 10 - engineConf.plannerConfig.RelaxSubgraphOperationFieldSelectionMergingNullability = opts.relaxFieldSelectionMergingNullability - resolveOpts := resolve.ResolverOptions{ - MaxConcurrency: 1024, - ResolvableOptions: opts.resolvableOptions, - ApolloRouterCompatibilitySubrequestHTTPError: opts.apolloRouterCompatibilitySubrequestHTTPError, - PropagateFetchReasons: opts.propagateFetchReasons, - ValidateRequiredExternalFields: opts.validateRequiredExternalFields, - } - engine, err := NewExecutionEngine(ctx, abstractlogger.Noop{}, engineConf, resolveOpts) - require.NoError(t, err) - - operation := testCase.operation(t) - resultWriter := graphql.NewEngineResultWriter() - execCtx, execCtxCancel := context.WithCancel(context.Background()) - defer execCtxCancel() - err = engine.Execute(execCtx, &operation, &resultWriter, testCase.engineOptions...) - actualResponse := resultWriter.String() - - if testCase.indentJSON { - dst := new(bytes.Buffer) - require.NoError(t, json.Indent(dst, []byte(actualResponse), "", " ")) - actualResponse = dst.String() - } - - if testCase.expectedFixture != "" { - g := goldie.New(t, goldie.WithFixtureDir("testdata"), goldie.WithNameSuffix(".json")) - g.Assert(t, testCase.expectedFixture, []byte(actualResponse)) - return - } - - if withError { - require.Error(t, err) - if expectedErrorMessage != "" { - assert.Equal(t, expectedErrorMessage, err.Error()) - } - } else { - require.NoError(t, err) - } - - if testCase.expectedJSONResponse != "" { - assert.JSONEq(t, testCase.expectedJSONResponse, actualResponse) - } - - if testCase.expectedResponse != "" { - assert.Equal(t, testCase.expectedResponse, actualResponse) - } - - if testCase.expectedEstimatedCost != 0 { - gotCost := operation.EstimatedCost() - require.Equal(t, testCase.expectedEstimatedCost, gotCost) - } - - if testCase.expectedActualCost != 0 { - gotActualCost := operation.ActualCost() - require.Equal(t, testCase.expectedActualCost, gotActualCost) - } - - } - } - - runWithAndCompareError := func(testCase ExecutionEngineTestCase, expectedErrorMessage string, options ...executionTestOptions) func(t *testing.T) { - t.Helper() - - return run(testCase, true, expectedErrorMessage, options...) - } - - runWithoutError := func(testCase ExecutionEngineTestCase, options ...executionTestOptions) func(t *testing.T) { - t.Helper() - - return run(testCase, false, "", options...) - } - t.Run("apollo router compatibility subrequest HTTP error enabled", runWithoutError( ExecutionEngineTestCase{ schema: graphql.StarwarsSchema(t), @@ -2346,7 +2329,7 @@ func TestExecutionEngine_Execute(t *testing.T) { schema, err := graphql.NewSchemaFromString(enumSDL) require.NoError(t, err) - t.Run("invalid non-nullable enum input", run( + t.Run("invalid non-nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -2409,7 +2392,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, true, `Variable "$enum" got invalid value "INVALID"; Value "INVALID" does not exist in "Enum" enum.`, )) - t.Run("nested invalid non-nullable enum input", run( + t.Run("nested invalid non-nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -2480,7 +2463,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, true, `Variable "$enum" got invalid value "INVALID"; Value "INVALID" does not exist in "Enum" enum.`, )) - t.Run("invalid nullable enum input", run( + t.Run("invalid nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -2543,7 +2526,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, true, `Variable "$enum" got invalid value "INVALID"; Value "INVALID" does not exist in "Enum" enum.`, )) - t.Run("nested invalid nullable enum input", run( + t.Run("nested invalid nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -3214,7 +3197,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, )) - t.Run("inaccessible non-nullable enum input", run( + t.Run("inaccessible non-nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -3277,7 +3260,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, true, `Variable "$enum" got invalid value "INACCESSIBLE"; Value "INACCESSIBLE" does not exist in "Enum" enum.`, )) - t.Run("nested inaccessible non-nullable enum input", run( + t.Run("nested inaccessible non-nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -3348,7 +3331,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, true, `Variable "$enum" got invalid value "INACCESSIBLE"; Value "INACCESSIBLE" does not exist in "Enum" enum.`, )) - t.Run("inaccessible nullable enum input", run( + t.Run("inaccessible nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -3411,7 +3394,7 @@ func TestExecutionEngine_Execute(t *testing.T) { }, true, `Variable "$enum" got invalid value "INACCESSIBLE"; Value "INACCESSIBLE" does not exist in "Enum" enum.`, )) - t.Run("nested inaccessible nullable enum input", run( + t.Run("nested inaccessible nullable enum input", runExecutionTest( ExecutionEngineTestCase{ schema: schema, operation: func(t *testing.T) graphql.Request { @@ -5646,1948 +5629,6 @@ func TestExecutionEngine_Execute(t *testing.T) { }) }) - t.Run("costs computation", func(t *testing.T) { - t.Run("common on star wars scheme", func(t *testing.T) { - rootNodes := []plan.TypeField{ - {TypeName: "Query", FieldNames: []string{"hero", "droid"}}, - {TypeName: "Human", FieldNames: []string{"name", "height", "friends"}}, - {TypeName: "Droid", FieldNames: []string{"name", "primaryFunction", "friends"}}, - } - childNodes := []plan.TypeField{ - {TypeName: "Character", FieldNames: []string{"name", "friends"}}, - } - customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ - Fetch: &graphql_datasource.FetchConfiguration{ - URL: "https://example.com/", - Method: "GET", - }, - SchemaConfiguration: mustSchemaConfig( - t, - nil, - string(graphql.StarwarsSchema(t).RawSchema()), - ), - }) - - t.Run("droid with weighted plain fields", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - droid(id: "R2D2") { - name - primaryFunction - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, - }, - }}, - customConfig, - ), - }, - fields: []plan.FieldConfiguration{ - { - TypeName: "Query", FieldName: "droid", - Arguments: []plan.ArgumentConfiguration{ - { - Name: "id", - SourceType: plan.FieldArgumentSource, - RenderConfig: plan.RenderArgumentAsGraphQLValue, - }, - }, - }, - }, - expectedResponse: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, - expectedEstimatedCost: 18, // Query.droid (1) + droid.name (17) - }, - computeCosts(), - )) - - t.Run("droid with weighted plain fields and an argument", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - droid(id: "R2D2") { - name - primaryFunction - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Query", FieldName: "droid"}: { - ArgumentWeights: map[string]int{"id": 3}, - HasWeight: false, - }, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, - }, - }}, - customConfig, - ), - }, - fields: []plan.FieldConfiguration{ - { - TypeName: "Query", FieldName: "droid", - Arguments: []plan.ArgumentConfiguration{ - { - Name: "id", - SourceType: plan.FieldArgumentSource, - RenderConfig: plan.RenderArgumentAsGraphQLValue, - }, - }, - }, - }, - expectedResponse: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, - expectedEstimatedCost: 21, // Query.droid (1) + Query.droid.id (3) + droid.name (17) - }, - computeCosts(), - )) - - t.Run("negative weights - cost is never negative", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - droid(id: "R2D2") { - name - primaryFunction - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Query", FieldName: "droid"}: { - HasWeight: true, - Weight: -10, // Negative field weight - ArgumentWeights: map[string]int{"id": -5}, // Negative argument weight - }, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: -3}, - {TypeName: "Droid", FieldName: "primaryFunction"}: {HasWeight: true, Weight: -2}, - }, - Types: map[string]int{ - "Droid": -1, // Negative type weight - }, - }}, - customConfig, - ), - }, - fields: []plan.FieldConfiguration{ - { - TypeName: "Query", FieldName: "droid", - Arguments: []plan.ArgumentConfiguration{ - { - Name: "id", - SourceType: plan.FieldArgumentSource, - RenderConfig: plan.RenderArgumentAsGraphQLValue, - }, - }, - }, - }, - expectedResponse: `{"data":{"droid":{"name":"R2D2","primaryFunction":"no"}}}`, - // All weights are negative. - // But cost should be floored to 0 (never negative) - expectedEstimatedCost: 0, - }, - computeCosts(), - )) - - t.Run("hero field has weight (returns interface) and with concrete fragment", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - name - ... on Human { height } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke Skywalker","height":"12"}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{RootNodes: rootNodes, ChildNodes: childNodes, CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Query", FieldName: "hero"}: {HasWeight: true, Weight: 2}, - {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 3}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 7}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, - }, - Types: map[string]int{ - "Human": 13, - }, - }}, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"name":"Luke Skywalker","height":"12"}}}`, - expectedEstimatedCost: 22, // Query.hero (2) + Human.height (3) + Droid.name (17=max(7, 17)) - }, - computeCosts(), - )) - - t.Run("hero field has no weight (returns interface) and with concrete fragment", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { name } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke Skywalker"}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{RootNodes: rootNodes, ChildNodes: childNodes, CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 7}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 17}, - }, - Types: map[string]int{ - "Human": 13, - "Droid": 11, - }, - }}, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"name":"Luke Skywalker"}}}`, - expectedEstimatedCost: 30, // Query.Human (13) + Droid.name (17=max(7, 17)) - }, - computeCosts(), - )) - - t.Run("query hero without assumedSize on friends", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - friends { - ...on Droid { name primaryFunction } - ...on Human { name height } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ - {"__typename":"Human","name":"Luke Skywalker","height":"12"}, - {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} - ]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, - }, - Types: map[string]int{ - "Human": 7, - "Droid": 5, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, - expectedEstimatedCost: 127, // Query.hero(max(7,5))+10*(Human(max(7,5))+Human.name(2)+Human.height(1)+Droid.name(2)) - }, - computeCosts(), - )) - - t.Run("query hero with assumedSize on friends", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - friends { - ...on Droid { name primaryFunction } - ...on Human { name height } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ - {"__typename":"Human","name":"Luke Skywalker","height":"12"}, - {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} - ]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Human", FieldName: "friends"}: {AssumedSize: 5}, - {TypeName: "Droid", FieldName: "friends"}: {AssumedSize: 20}, - }, - Types: map[string]int{ - "Human": 7, - "Droid": 5, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, - expectedEstimatedCost: 247, // Query.hero(max(7,5))+ 20 * (7+2+2+1) - // We pick maximum on every path independently. This is to reveal the upper boundary. - // Query.hero: picked maximum weight (Human=7) out of two types (Human, Droid) - // Query.hero.friends: the max possible weight (7) is for implementing class Human - // of the returned type of Character; the multiplier picked for the Droid since - // it is the maximum possible value - we considered the enclosing type that contains it. - }, - computeCosts(), - )) - - t.Run("query hero with assumedSize on friends and weight defined", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - friends { - ...on Droid { name primaryFunction } - ...on Human { name height } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ - {"__typename":"Human","name":"Luke Skywalker","height":"12"}, - {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} - ]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Human", FieldName: "friends"}: {HasWeight: true, Weight: 3}, - {TypeName: "Droid", FieldName: "friends"}: {HasWeight: true, Weight: 4}, - {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Human", FieldName: "friends"}: {AssumedSize: 5}, - {TypeName: "Droid", FieldName: "friends"}: {AssumedSize: 20}, - }, - Types: map[string]int{ - "Human": 7, - "Droid": 5, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, - expectedEstimatedCost: 187, // Query.hero(max(7,5))+ 20 * (4+2+2+1) - }, - computeCosts(), - )) - - t.Run("query hero with empty cost structures", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - friends { - ...on Droid { name primaryFunction } - ...on Human { name height } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ - {"__typename":"Human","name":"Luke Skywalker","height":"12"}, - {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} - ]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{}, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, - expectedEstimatedCost: 11, // Query.hero(max(1,1))+ 10 * 1 - }, - computeCosts(), - )) - - // Actual cost tests - verifies that actual cost uses real list sizes from response - // rather than estimated/assumed sizes - - t.Run("actual cost with list field - 2 items instead of default 10", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - friends { - ...on Droid { name primaryFunction } - ...on Human { name height } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - // Response has 2 friends (not 10 as estimated) - sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[ - {"__typename":"Human","name":"Luke Skywalker","height":"12"}, - {"__typename":"Droid","name":"R2DO","primaryFunction":"joke"} - ]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 1}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, - }, - Types: map[string]int{ - "Human": 7, - "Droid": 5, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"friends":[{"name":"Luke Skywalker","height":"12"},{"name":"R2DO","primaryFunction":"joke"}]}}}`, - // Estimated with default list size 10: hero(7) + 10 * (7 + 2 + 2 + 1) = 127 - expectedEstimatedCost: 127, - // Actual uses real list size 2: hero(7) + 2 * (7 + 2 + 2 + 1) = 31 - expectedActualCost: 31, - }, - computeCosts(), - )) - - t.Run("actual cost with empty list", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - hero { - friends { - ...on Droid { name } - ...on Human { name } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - // Response has empty friends array - sendResponseBody: `{"data":{"hero":{"__typename":"Human","friends":[]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 2}, - }, - Types: map[string]int{ - "Human": 7, - "Droid": 5, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"friends":[]}}}`, - // Estimated with default list size 10: hero(7) + 10 * (7 + 2 + 2) = 117 - expectedEstimatedCost: 117, - // Actual with empty list: hero(7) + 1 * (7 + 2 + 2) = 18 - // We consider empty lists as lists containing one item to account for the - // resolver work. - expectedActualCost: 18, - }, - computeCosts(), - )) - - t.Run("named fragment on interface", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: ` - fragment CharacterFields on Character { - name - friends { name } - } - { hero { ...CharacterFields } } - `, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke","friends":[{"name":"Leia"}]}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Query", FieldName: "hero"}: {HasWeight: true, Weight: 2}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 3}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 5}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Human", FieldName: "friends"}: {AssumedSize: 4}, - {TypeName: "Droid", FieldName: "friends"}: {AssumedSize: 6}, - }, - Types: map[string]int{ - "Human": 2, - "Droid": 3, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"name":"Luke","friends":[{"name":"Leia"}]}}}`, - // Cost calculation: - // Query.hero: 2 - // Character.name: max(Human.name=3, Droid.name=5) = 5 - // friends listSize: max(4, 6) = 6 - // Character type: max(Human=2, Droid=3) = 3 - // name: max(Human.name=3, Droid.name=5) = 5 - // Total: 2 + 5 + 6 * (3 + 5) - expectedEstimatedCost: 55, - }, - computeCosts(), - )) - - t.Run("named fragment with concrete type", runWithoutError( - ExecutionEngineTestCase{ - schema: graphql.StarwarsSchema(t), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: ` - fragment HumanFields on Human { - name - height - } - { hero { ...HumanFields } } - `, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"hero":{"__typename":"Human","name":"Luke","height":"1.72"}}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Query", FieldName: "hero"}: {HasWeight: true, Weight: 2}, - {TypeName: "Human", FieldName: "name"}: {HasWeight: true, Weight: 3}, - {TypeName: "Human", FieldName: "height"}: {HasWeight: true, Weight: 7}, - {TypeName: "Droid", FieldName: "name"}: {HasWeight: true, Weight: 5}, - }, - Types: map[string]int{ - "Human": 1, - "Droid": 1, - }, - }, - }, - customConfig, - ), - }, - expectedResponse: `{"data":{"hero":{"name":"Luke","height":"1.72"}}}`, - // Total: 2 + 3 + 7 - expectedEstimatedCost: 12, - }, - computeCosts(), - )) - - }) - - t.Run("union types", func(t *testing.T) { - unionSchema := ` - type Query { - search(term: String!): [SearchResult!] - } - union SearchResult = User | Post | Comment - type User @key(fields: "id") { - id: ID! - name: String! - email: String! - } - type Post @key(fields: "id") { - id: ID! - title: String! - body: String! - } - type Comment @key(fields: "id") { - id: ID! - text: String! - } - ` - schema, err := graphql.NewSchemaFromString(unionSchema) - require.NoError(t, err) - - rootNodes := []plan.TypeField{ - {TypeName: "Query", FieldNames: []string{"search"}}, - {TypeName: "User", FieldNames: []string{"id", "name", "email"}}, - {TypeName: "Post", FieldNames: []string{"id", "title", "body"}}, - {TypeName: "Comment", FieldNames: []string{"id", "text"}}, - } - childNodes := []plan.TypeField{} - customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ - Fetch: &graphql_datasource.FetchConfiguration{ - URL: "https://example.com/", - Method: "GET", - }, - SchemaConfiguration: mustSchemaConfig(t, nil, unionSchema), - }) - fieldConfig := []plan.FieldConfiguration{ - { - TypeName: "Query", - FieldName: "search", - Path: []string{"search"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "term", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - } - - t.Run("union with all member types", runWithoutError( - ExecutionEngineTestCase{ - schema: schema, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - search(term: "test") { - ... on User { name email } - ... on Post { title body } - ... on Comment { text } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"search":[{"__typename":"User","name":"John","email":"john@test.com"}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "User", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "User", FieldName: "email"}: {HasWeight: true, Weight: 3}, - {TypeName: "Post", FieldName: "title"}: {HasWeight: true, Weight: 4}, - {TypeName: "Post", FieldName: "body"}: {HasWeight: true, Weight: 5}, - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "search"}: {AssumedSize: 5}, - }, - Types: map[string]int{ - "User": 2, - "Post": 3, - "Comment": 1, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"search":[{"name":"John","email":"john@test.com"}]}}`, - // search listSize: 10 - // For each SearchResult, use max across all union members: - // Type weight: max(User=2, Post=3, Comment=1) = 3 - // Fields: all fields from all fragments are counted - // (2 + 3) + (4 + 5) + (1) = 15 - // TODO: this is not correct, we should pick a maximum sum among types implementing union. - // 9 should be used instead of 15 - // Total: 5 * (3 + 15) - expectedEstimatedCost: 90, - }, - computeCosts(), - )) - - t.Run("union with weighted search field", runWithoutError( - ExecutionEngineTestCase{ - schema: schema, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - search(term: "test") { - ... on User { name } - ... on Post { title } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"search":[{"__typename":"User","name":"John"}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "User", FieldName: "name"}: {HasWeight: true, Weight: 2}, - {TypeName: "Post", FieldName: "title"}: {HasWeight: true, Weight: 5}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "search"}: {AssumedSize: 3}, - }, - Types: map[string]int{ - "User": 6, - "Post": 10, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"search":[{"name":"John"}]}}`, - // Query.search: max(User=10, Post=6) - // search listSize: 3 - // Union members: - // All fields from all fragments: User.name(2) + Post.title(5) - // Total: 3 * (10+2+5) - // TODO: we might correct this by counting only members of one implementing types - // of a union when fragments are used. - expectedEstimatedCost: 51, - }, - computeCosts(), - )) - }) - - t.Run("listSize", func(t *testing.T) { - listSchema := ` - type Query { - items(first: Int, last: Int): [Item!] - } - type Item @key(fields: "id") { - id: ID - } - ` - schemaSlicing, err := graphql.NewSchemaFromString(listSchema) - require.NoError(t, err) - rootNodes := []plan.TypeField{ - {TypeName: "Query", FieldNames: []string{"items"}}, - {TypeName: "Item", FieldNames: []string{"id"}}, - } - childNodes := []plan.TypeField{} - customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ - Fetch: &graphql_datasource.FetchConfiguration{ - URL: "https://example.com/", - Method: "GET", - }, - SchemaConfiguration: mustSchemaConfig(t, nil, listSchema), - }) - fieldConfig := []plan.FieldConfiguration{ - { - TypeName: "Query", - FieldName: "items", - Path: []string{"items"}, - Arguments: []plan.ArgumentConfiguration{ - { - Name: "first", - SourceType: plan.FieldArgumentSource, - RenderConfig: plan.RenderArgumentAsGraphQLValue, - }, - { - Name: "last", - SourceType: plan.FieldArgumentSource, - RenderConfig: plan.RenderArgumentAsGraphQLValue, - }, - }, - }, - } - t.Run("multiple slicing arguments as literals", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaSlicing, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `query MultipleSlicingArguments { - items(first: 5, last: 12) { id } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"items":[ {"id":"2"}, {"id":"3"} ]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "items"}: { - AssumedSize: 8, - SlicingArguments: []string{"first", "last"}, - }, - }, - Types: map[string]int{ - "Item": 3, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"items":[{"id":"2"},{"id":"3"}]}}`, - expectedEstimatedCost: 48, // slicingArgument(12) * (Item(3)+Item.id(1)) - }, - computeCosts(), - )) - t.Run("slicing argument as a variable", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaSlicing, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `query SlicingWithVariable($limit: Int!) { - items(first: $limit) { id } - }`, - Variables: []byte(`{"limit": 25}`), - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"items":[ {"id":"2"}, {"id":"3"} ]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "items"}: { - AssumedSize: 8, - SlicingArguments: []string{"first", "last"}, - }, - }, - Types: map[string]int{ - "Item": 3, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"items":[{"id":"2"},{"id":"3"}]}}`, - expectedEstimatedCost: 100, // slicingArgument($limit=25) * (Item(3)+Item.id(1)) - }, - computeCosts(), - )) - t.Run("slicing argument not provided falls back to assumedSize", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaSlicing, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `query NoSlicingArg { - items { id } - }`, - // No slicing arguments provided - should fall back to assumedSize - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"items":[{"id":"1"},{"id":"2"}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "items"}: { - AssumedSize: 15, - SlicingArguments: []string{"first", "last"}, - }, - }, - Types: map[string]int{ - "Item": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"items":[{"id":"1"},{"id":"2"}]}}`, - expectedEstimatedCost: 45, // Total: 15 * (2 + 1) - }, - computeCosts(), - )) - t.Run("zero slicing argument falls back to assumedSize", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaSlicing, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `query ZeroSlicing { - items(first: 0) { id } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"items":[]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "items"}: { - AssumedSize: 20, - SlicingArguments: []string{"first", "last"}, - }, - }, - Types: map[string]int{ - "Item": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"items":[]}}`, - expectedEstimatedCost: 60, // 20 * (2 + 1) - }, - computeCosts(), - )) - t.Run("negative slicing argument falls back to assumedSize", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaSlicing, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `query NegativeSlicing { - items(first: -5) { id } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", expectedPath: "/", expectedBody: "", - sendResponseBody: `{"data":{"items":[]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Item", FieldName: "id"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "items"}: { - AssumedSize: 25, - SlicingArguments: []string{"first", "last"}, - }, - }, - Types: map[string]int{ - "Item": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"items":[]}}`, - expectedEstimatedCost: 75, // 25 * (2 + 1) - }, - computeCosts(), - )) - - }) - - t.Run("nested lists with compounding multipliers", func(t *testing.T) { - nestedSchema := ` - type Query { - users(first: Int): [User!] - } - type User @key(fields: "id") { - id: ID! - posts(first: Int): [Post!] - } - type Post @key(fields: "id") { - id: ID! - comments(first: Int): [Comment!] - } - type Comment @key(fields: "id") { - id: ID! - text: String! - } - ` - schemaNested, err := graphql.NewSchemaFromString(nestedSchema) - require.NoError(t, err) - - rootNodes := []plan.TypeField{ - {TypeName: "Query", FieldNames: []string{"users"}}, - {TypeName: "User", FieldNames: []string{"id", "posts"}}, - {TypeName: "Post", FieldNames: []string{"id", "comments"}}, - {TypeName: "Comment", FieldNames: []string{"id", "text"}}, - } - childNodes := []plan.TypeField{} - customConfig := mustConfiguration(t, graphql_datasource.ConfigurationInput{ - Fetch: &graphql_datasource.FetchConfiguration{ - URL: "https://example.com/", - Method: "GET", - }, - SchemaConfiguration: mustSchemaConfig(t, nil, nestedSchema), - }) - fieldConfig := []plan.FieldConfiguration{ - { - TypeName: "Query", FieldName: "users", Path: []string{"users"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - { - TypeName: "User", FieldName: "posts", Path: []string{"posts"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - { - TypeName: "Post", FieldName: "comments", Path: []string{"comments"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - } - - t.Run("nested lists with slicing arguments", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - users(first: 10) { - posts(first: 5) { - comments(first: 3) { text } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "User", FieldName: "posts"}: { - AssumedSize: 50, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Post", FieldName: "comments"}: { - AssumedSize: 20, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - "Post": 3, - "Comment": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, - // Cost calculation: - // users(first:10): multiplier 10 - // User type weight: 4 - // posts(first:5): multiplier 5 - // Post type weight: 3 - // comments(first:3): multiplier 3 - // Comment type weight: 2 - // text weight: 1 - // Total: 10 * (4 + 5 * (3 + 3 * (2 + 1))) - expectedEstimatedCost: 640, - }, - computeCosts(), - )) - - t.Run("nested lists fallback to assumedSize when slicing arg not provided", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - users(first: 2) { - posts { - comments(first: 4) { text } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"users":[{"posts":[{"comments":[{"text":"hi"}]}]}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "User", FieldName: "posts"}: { - AssumedSize: 50, // no slicing arg, should use this - }, - {TypeName: "Post", FieldName: "comments"}: { - AssumedSize: 20, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - "Post": 3, - "Comment": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"hi"}]}]}]}}`, - // Cost calculation: - // users(first:2): multiplier 2 - // User type weight: 4 - // posts (no arg): assumedSize 50 - // Post type weight: 3 - // comments(first:4): multiplier 4 - // Comment type weight: 2 - // text weight: 1 - // Total: 2 * (4 + 50 * (3 + 4 * (2 + 1))) - expectedEstimatedCost: 1508, - }, - computeCosts(), - )) - - t.Run("actual cost for nested lists - 1 item at each level", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - users(first: 10) { - posts(first: 5) { - comments(first: 3) { text } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - // Response has 1 user with 1 post with 1 comment - sendResponseBody: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "User", FieldName: "posts"}: { - AssumedSize: 50, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Post", FieldName: "comments"}: { - AssumedSize: 20, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - "Post": 3, - "Comment": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"hello"}]}]}]}}`, - // Estimated cost with slicing arguments (10, 5, 3): - // Total: 10 * (4 + 5 * (3 + 3 * (2 + 1))) = 640 - expectedEstimatedCost: 640, - // Actual cost with 1 item at each level: - // Total: 1 * (4 + 1 * (3 + 1 * (2 + 1))) = 10 - expectedActualCost: 10, - }, - computeCosts(), - )) - - t.Run("actual cost for nested lists - varying sizes", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - users(first: 10) { - posts(first: 5) { - comments(first: 3) { text } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - // Response has 2 users, each with 2 posts, each with 3 comments - sendResponseBody: `{"data":{"users":[ - {"posts":[ - {"comments":[{"text":"a"},{"text":"b"},{"text":"c"}]}, - {"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]}, - {"posts":[ - {"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]}, - {"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "User", FieldName: "posts"}: { - AssumedSize: 50, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Post", FieldName: "comments"}: { - AssumedSize: 20, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - "Post": 3, - "Comment": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"a"},{"text":"b"},{"text":"c"}]},{"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]},{"posts":[{"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]},{"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, - expectedEstimatedCost: 640, - // Actual cost: 2 * (4 + 2 * (3 + 3 * (2 + 1))) = 56 - expectedActualCost: 56, - }, - computeCosts(), - )) - - t.Run("actual cost for nested lists - uneven sizes", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - users(first: 10) { - posts(first: 5) { - comments(first: 2) { text } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - // Response has 2 users, with 1.5 posts each, each with 3 comments - sendResponseBody: `{"data":{"users":[ - {"posts":[ - {"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]}, - {"posts":[ - {"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]}, - {"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "User", FieldName: "posts"}: { - AssumedSize: 50, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Post", FieldName: "comments"}: { - AssumedSize: 20, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - "Post": 3, - "Comment": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"d"},{"text":"e"},{"text":"f"}]}]},{"posts":[{"comments":[{"text":"g"},{"text":"h"},{"text":"i"}]},{"comments":[{"text":"j"},{"text":"k"},{"text":"l"}]}]}]}}`, - // Estimated : 10 * (4 + 5 * (3 + 2 * (2 + 1))) = 490 - expectedEstimatedCost: 490, - // Actual cost: 2 * (4 + 1.5 * (3 + 3 * (2 + 1))) = 44 - expectedActualCost: 44, - }, - computeCosts(), - )) - - t.Run("actual cost for root-level list - no parent", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ users(first: 10) { id } }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - // Response has 3 users at the root level - sendResponseBody: `{"data":{"users":[ - {"id":"1"}, - {"id":"2"}, - {"id":"3"}]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "User", FieldName: "id"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"id":"1"},{"id":"2"},{"id":"3"}]}}`, - // Estimated: 10 * (4 + 1) = 50 - expectedEstimatedCost: 50, - // Actual cost: 3 users at root - // 3 * (4 + 1) = 15 - expectedActualCost: 15, - }, - computeCosts(), - )) - - t.Run("mixed empty and non-empty lists - averaging behavior", runWithoutError( - ExecutionEngineTestCase{ - schema: schemaNested, - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - users(first: 10) { - posts(first: 5) { - comments(first: 3) { text } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"users":[ - {"posts":[ - {"comments":[{"text":"a"},{"text":"b"}]}, - {"comments":[{"text":"c"},{"text":"d"}]} - ]}, - {"posts":[]}, - {"posts":[ - {"comments":[]} - ]} - ]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: rootNodes, - ChildNodes: childNodes, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Comment", FieldName: "text"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "users"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "User", FieldName: "posts"}: { - AssumedSize: 50, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Post", FieldName: "comments"}: { - AssumedSize: 20, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "User": 4, - "Post": 3, - "Comment": 2, - }, - }, - }, - customConfig, - ), - }, - fields: fieldConfig, - expectedResponse: `{"data":{"users":[{"posts":[{"comments":[{"text":"a"},{"text":"b"}]},{"comments":[{"text":"c"},{"text":"d"}]}]},{"posts":[]},{"posts":[{"comments":[]}]}]}}`, - expectedEstimatedCost: 640, // 10 * (4 + 5 * (3 + 3 * (2 + 1))) - // Actual cost with mixed empty/non-empty lists: - // Users: 3 items, multiplier 3.0 - // Posts: 3 items, 3 parents => multiplier 1.0 (avg) - // Comments: 4 items, 3 parents => multiplier 1.33 (avg) - // - // Calculation: - // Comments: RoundToEven((2 + 1) * 1.33) ~= 4 - // Posts: RoundToEven((3 + 4) * 1.00) = 7 - // Users: RoundToEven((4 + 7) * 3.00) = 33 - // - // Empty lists are included in the averaging: - expectedActualCost: 33, - }, - computeCosts(), - )) - - t.Run("deeply nested lists with fractional multipliers - compounding rounding", runWithoutError( - ExecutionEngineTestCase{ - schema: func() *graphql.Schema { - deepSchema := ` - type Query { - level1(first: Int): [Level1!] - } - type Level1 @key(fields: "id") { - id: ID! - level2(first: Int): [Level2!] - } - type Level2 @key(fields: "id") { - id: ID! - level3(first: Int): [Level3!] - } - type Level3 @key(fields: "id") { - id: ID! - level4(first: Int): [Level4!] - } - type Level4 @key(fields: "id") { - id: ID! - level5(first: Int): [Level5!] - } - type Level5 @key(fields: "id") { - id: ID! - value: String! - } - ` - s, err := graphql.NewSchemaFromString(deepSchema) - require.NoError(t, err) - return s - }(), - operation: func(t *testing.T) graphql.Request { - return graphql.Request{ - Query: `{ - level1(first: 10) { - level2(first: 10) { - level3(first: 10) { - level4(first: 10) { - level5(first: 10) { - value - } - } - } - } - } - }`, - } - }, - dataSources: []plan.DataSource{ - mustGraphqlDataSourceConfiguration(t, "id", - mustFactory(t, - testNetHttpClient(t, roundTripperTestCase{ - expectedHost: "example.com", - expectedPath: "/", - expectedBody: "", - sendResponseBody: `{"data":{"level1":[ - {"level2":[ - {"level3":[ - {"level4":[ - {"level5":[{"value":"a"}]}, - {"level5":[{"value":"b"},{"value":"c"}]} - ]}, - {"level4":[ - {"level5":[{"value":"d"}]} - ]} - ]}, - {"level3":[ - {"level4":[ - {"level5":[{"value":"e"}]} - ]} - ]} - ]}, - {"level2":[ - {"level3":[ - {"level4":[ - {"level5":[{"value":"f"},{"value":"g"}]}, - {"level5":[{"value":"h"}]} - ]}, - {"level4":[ - {"level5":[{"value":"i"}]} - ]} - ]} - ]}, - {"level2":[ - {"level3":[ - {"level4":[ - {"level5":[{"value":"j"}]}, - {"level5":[{"value":"k"}]} - ]}, - {"level4":[ - {"level5":[{"value":"l"}]}, - {"level5":[{"value":"m"}]} - ]} - ]} - ]} - ]}}`, - sendStatusCode: 200, - }), - ), - &plan.DataSourceMetadata{ - RootNodes: []plan.TypeField{ - {TypeName: "Query", FieldNames: []string{"level1"}}, - {TypeName: "Level1", FieldNames: []string{"id", "level2"}}, - {TypeName: "Level2", FieldNames: []string{"id", "level3"}}, - {TypeName: "Level3", FieldNames: []string{"id", "level4"}}, - {TypeName: "Level4", FieldNames: []string{"id", "level5"}}, - {TypeName: "Level5", FieldNames: []string{"id", "value"}}, - }, - ChildNodes: []plan.TypeField{}, - CostConfig: &plan.DataSourceCostConfig{ - Weights: map[plan.FieldCoordinate]*plan.FieldWeight{ - {TypeName: "Level5", FieldName: "value"}: {HasWeight: true, Weight: 1}, - }, - ListSizes: map[plan.FieldCoordinate]*plan.FieldListSize{ - {TypeName: "Query", FieldName: "level1"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Level1", FieldName: "level2"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Level2", FieldName: "level3"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Level3", FieldName: "level4"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - {TypeName: "Level4", FieldName: "level5"}: { - AssumedSize: 100, - SlicingArguments: []string{"first"}, - }, - }, - Types: map[string]int{ - "Level1": 1, - "Level2": 1, - "Level3": 1, - "Level4": 1, - "Level5": 1, - }, - }, - }, - mustConfiguration(t, graphql_datasource.ConfigurationInput{ - Fetch: &graphql_datasource.FetchConfiguration{ - URL: "https://example.com/", - Method: "GET", - }, - SchemaConfiguration: mustSchemaConfig(t, nil, ` - type Query { - level1(first: Int): [Level1!] - } - type Level1 @key(fields: "id") { - id: ID! - level2(first: Int): [Level2!] - } - type Level2 @key(fields: "id") { - id: ID! - level3(first: Int): [Level3!] - } - type Level3 @key(fields: "id") { - id: ID! - level4(first: Int): [Level4!] - } - type Level4 @key(fields: "id") { - id: ID! - level5(first: Int): [Level5!] - } - type Level5 @key(fields: "id") { - id: ID! - value: String! - } - `), - }), - ), - }, - fields: []plan.FieldConfiguration{ - { - TypeName: "Query", FieldName: "level1", Path: []string{"level1"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - { - TypeName: "Level1", FieldName: "level2", Path: []string{"level2"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - { - TypeName: "Level2", FieldName: "level3", Path: []string{"level3"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - { - TypeName: "Level3", FieldName: "level4", Path: []string{"level4"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - { - TypeName: "Level4", FieldName: "level5", Path: []string{"level5"}, - Arguments: []plan.ArgumentConfiguration{ - {Name: "first", SourceType: plan.FieldArgumentSource, RenderConfig: plan.RenderArgumentAsGraphQLValue}, - }, - }, - }, - expectedResponse: `{"data":{"level1":[{"level2":[{"level3":[{"level4":[{"level5":[{"value":"a"}]},{"level5":[{"value":"b"},{"value":"c"}]}]},{"level4":[{"level5":[{"value":"d"}]}]}]},{"level3":[{"level4":[{"level5":[{"value":"e"}]}]}]}]},{"level2":[{"level3":[{"level4":[{"level5":[{"value":"f"},{"value":"g"}]},{"level5":[{"value":"h"}]}]},{"level4":[{"level5":[{"value":"i"}]}]}]}]},{"level2":[{"level3":[{"level4":[{"level5":[{"value":"j"}]},{"level5":[{"value":"k"}]}]},{"level4":[{"level5":[{"value":"l"}]},{"level5":[{"value":"m"}]}]}]}]}]}}`, - expectedEstimatedCost: 211110, - // Actual cost with fractional multipliers: - // Level5: 13 items, 11 parents => multiplier 1.18 (13/11 = 1.181818...) - // Level4: 11 items, 7 parents => multiplier 1.57 (11/7 = 1.571428...) - // Level3: 7 items, 4 parents => multiplier 1.75 (7/4 = 1.75) - // Level2: 4 items, 3 parents => multiplier 1.33 (4/3 = 1.333...) - // Level1: 3 items, 1 parent => multiplier 3.0 - // - // Ideal calculation without rounding: - // cost = 3 * (1 + 1.33 * (1 + 1.75 * (1 + 1.57 * (1 + 1.18 * (1 + 1))))) - // = 50.806584 ~= 51 - // - // Current implementation: - // Level5: RoundToEven((1 + 1) * 1.18) = 2 - // Level4: RoundToEven((1 + 2) * 1.57) = 5 - // Level3: RoundToEven((1 + 5) * 1.75) = 10 (rounds to even) - // Level2: RoundToEven((1 + 10) * 1.33) = 15 - // Level1: RoundToEven((1 + 15) * 3.00) = 48 - // - // The compounding rounding error: 48 vs 51 (6% underestimate) - expectedActualCost: 48, - }, - computeCosts(), - )) - }) - - }) - t.Run("field merging with different nullability on non-overlapping union types", func(t *testing.T) { unionSchema := ` union Entity = User | Organization diff --git a/release-please-manifest.json b/release-please-manifest.json index f2a9fd6fb2..1400038e61 100644 --- a/release-please-manifest.json +++ b/release-please-manifest.json @@ -1,4 +1,4 @@ { - "v2": "2.0.0-rc.256", + "v2": "2.0.0-rc.261", "execution": "1.9.0" } diff --git a/v2/CHANGELOG.md b/v2/CHANGELOG.md index 63c46618e0..0341f2d9ad 100644 --- a/v2/CHANGELOG.md +++ b/v2/CHANGELOG.md @@ -1,5 +1,40 @@ # Changelog +## [2.0.0-rc.261](https://github.com/wundergraph/graphql-go-tools/compare/v2.0.0-rc.260...v2.0.0-rc.261) (2026-03-06) + + +### Bug Fixes + +* fix selecting parent of unique nodes ([#1430](https://github.com/wundergraph/graphql-go-tools/issues/1430)) ([fd0e06a](https://github.com/wundergraph/graphql-go-tools/commit/fd0e06afa472a4c069f429c3c73e442831ed4b19)) + +## [2.0.0-rc.260](https://github.com/wundergraph/graphql-go-tools/compare/v2.0.0-rc.259...v2.0.0-rc.260) (2026-03-05) + + +### Bug Fixes + +* invalid data resolution for null parent types ([#1428](https://github.com/wundergraph/graphql-go-tools/issues/1428)) ([b7863be](https://github.com/wundergraph/graphql-go-tools/commit/b7863bed652a9324c0b1d02b3b11ce548c1b8fcc)) + +## [2.0.0-rc.259](https://github.com/wundergraph/graphql-go-tools/compare/v2.0.0-rc.258...v2.0.0-rc.259) (2026-03-05) + + +### Bug Fixes + +* skip invocation for empty context in field resolvers ([#1413](https://github.com/wundergraph/graphql-go-tools/issues/1413)) ([5885c48](https://github.com/wundergraph/graphql-go-tools/commit/5885c48066c696e60a70bf3ab4b10a824eca780a)) + +## [2.0.0-rc.258](https://github.com/wundergraph/graphql-go-tools/compare/v2.0.0-rc.257...v2.0.0-rc.258) (2026-03-05) + + +### Bug Fixes + +* handle complex types inside inline fragments in gRPC execution plan ([#1411](https://github.com/wundergraph/graphql-go-tools/issues/1411)) ([3b4dbcb](https://github.com/wundergraph/graphql-go-tools/commit/3b4dbcb2df54dd6fd2bc51094e0fee12cf7fd9a0)) + +## [2.0.0-rc.257](https://github.com/wundergraph/graphql-go-tools/compare/v2.0.0-rc.256...v2.0.0-rc.257) (2026-02-25) + + +### Bug Fixes + +* keep order of error extension fields after sanitization ([#1407](https://github.com/wundergraph/graphql-go-tools/issues/1407)) ([e974cd3](https://github.com/wundergraph/graphql-go-tools/commit/e974cd34d03fdcb10f36d2b636981700a2c20450)) + ## [2.0.0-rc.256](https://github.com/wundergraph/graphql-go-tools/compare/v2.0.0-rc.255...v2.0.0-rc.256) (2026-02-23) diff --git a/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go b/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go index 7b90e6c778..7f115f1e83 100644 --- a/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go +++ b/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go @@ -20218,4 +20218,388 @@ func TestGraphQLDataSourceFederation(t *testing.T) { }) }) }) + + t.Run("unique nodes parent root nodes selection", func(t *testing.T) { + // Tests a scenario where the planner must navigate through multiple layers of + // abstract types with @external fields to reach an entity whose fields are + // split across subgraphs. Mirrors a real-world pattern where: + // + // - Node (interface) is implemented by NodeA and NodeB + // - NodeA/NodeB declare pool: Pool! as @external in the first subgraph + // (to satisfy the Node interface), but Pool is truly owned by the second subgraph + // - Pool (interface) is implemented by Pool1 + // - Pool1.detail: Detail! is @external in the first subgraph, owned by the second + // - Detail is an entity with fields split across subgraphs: + // uniqueField → second subgraph only + // sharedField → first subgraph only + // + // Expected execution (zigzag: first → second → first): + // Fetch 0: first subgraph — root nodes query, returns NodeA keys + // Fetch 1: second subgraph — entity-resolve NodeA, traverse pool → Pool1 → detail, + // inline Detail.uniqueField (owned by second subgraph) + // Fetch 2: first subgraph — entity-resolve Detail to get sharedField + // + // Planner confusion: Pool1 appears as an entity in the first subgraph with + // detail @external. The planner may incorrectly try to resolve detail through + // the first subgraph's Pool1 entity, not realising it must go via the second + // subgraph's NodeA entity resolution first. + t.Run("external pool interface field on node implementation with split detail entity", func(t *testing.T) { + definition := ` + type Query { + nodes: [Node!]! + } + + interface Node { + id: ID! + detail: Detailer! + } + + type NodeA implements Node { + id: ID! + detail: Detailer! + } + + interface Detailer { + id: ID! + uniqueField: String! + } + + type Detail implements Detailer { + id: ID! + uniqueField: String! + } + ` + + // First subgraph: query root + NodeA/NodeB as entities (pool is @external). + // Owns Detail.sharedField. Pool1.detail is @external (owned by second subgraph). + firstSubgraphSDL := ` + type Query { + nodes: [Node!]! + } + + interface Node { + id: ID! + detail: Detailer + } + + type NodeA implements Node @key(fields: "id") { + id: ID! + detail: Detailer! @external + } + + interface Detailer { + id: ID! + uniqueField: String! + } + + type Detail implements Detailer @key(fields: "id") { + id: ID! + uniqueField: String! + } + ` + + firstDatasourceConfiguration := mustDataSourceConfiguration( + t, + "first-service", + &plan.DataSourceMetadata{ + RootNodes: []plan.TypeField{ + { + TypeName: "Query", + FieldNames: []string{"nodes"}, + }, + { + TypeName: "NodeA", + FieldNames: []string{"id"}, + ExternalFieldNames: []string{"detail"}, + }, + { + TypeName: "Detail", + FieldNames: []string{"id", "uniqueField"}, + }, + }, + ChildNodes: []plan.TypeField{ + { + TypeName: "Node", + FieldNames: []string{"id", "detail"}, + }, + { + TypeName: "Detailer", + FieldNames: []string{"id", "uniqueField"}, + }, + }, + FederationMetaData: plan.FederationMetaData{ + Keys: plan.FederationFieldConfigurations{ + { + TypeName: "NodeA", + SelectionSet: "id", + }, + { + TypeName: "Detail", + SelectionSet: "id", + }, + }, + }, + }, + mustCustomConfiguration(t, + ConfigurationInput{ + Fetch: &FetchConfiguration{ + URL: "http://first.service", + }, + SchemaConfiguration: mustSchema(t, + &FederationConfiguration{ + Enabled: true, + ServiceSDL: firstSubgraphSDL, + }, + firstSubgraphSDL, + ), + }, + ), + ) + + // Second subgraph: owns pool on NodeA/NodeB, owns detail on Pool1, + // owns Detail.uniqueField. Detail.sharedField lives only in first subgraph. + secondSubgraphSDL := ` + type Query { + nodes: [Node!]! + } + + interface Node { + id: ID! + detail: Detailer + } + + type NodeA implements Node @key(fields: "id") { + id: ID! + detail: Detailer! + } + + interface Detailer { + id: ID! + } + + type Detail implements Detailer @key(fields: "id") { + id: ID! + } + ` + + secondDatasourceConfiguration := mustDataSourceConfiguration( + t, + "second-service", + &plan.DataSourceMetadata{ + RootNodes: []plan.TypeField{ + { + TypeName: "Query", + FieldNames: []string{"nodes"}, + }, + { + TypeName: "NodeA", + FieldNames: []string{"id", "detail"}, + }, + { + TypeName: "Detail", + FieldNames: []string{"id"}, + }, + }, + ChildNodes: []plan.TypeField{ + { + TypeName: "Node", + FieldNames: []string{"id", "detail"}, + }, + { + TypeName: "Detailer", + FieldNames: []string{"id"}, + }, + }, + FederationMetaData: plan.FederationMetaData{ + Keys: plan.FederationFieldConfigurations{ + { + TypeName: "NodeA", + SelectionSet: "id", + }, + { + TypeName: "Detail", + SelectionSet: "id", + }, + }, + }, + }, + mustCustomConfiguration(t, + ConfigurationInput{ + Fetch: &FetchConfiguration{ + URL: "http://second.service", + }, + SchemaConfiguration: mustSchema(t, + &FederationConfiguration{ + Enabled: true, + ServiceSDL: secondSubgraphSDL, + }, + secondSubgraphSDL, + ), + }, + ), + ) + + planConfiguration := plan.Configuration{ + DataSources: []plan.DataSource{ + firstDatasourceConfiguration, + secondDatasourceConfiguration, + }, + DisableResolveFieldPositions: true, + } + + t.Run("run", func(t *testing.T) { + RunWithPermutations( + t, + definition, + ` + query TestQuery { + nodes { + detail { + uniqueField + } + } + }`, + "TestQuery", + &plan.SynchronousResponsePlan{ + Response: &resolve.GraphQLResponse{ + Fetches: resolve.Sequence( + // Fetch 0: root query — first subgraph returns NodeA keys only (pool is @external) + resolve.Single(&resolve.SingleFetch{ + FetchConfiguration: resolve.FetchConfiguration{ + Input: `{"method":"POST","url":"http://first.service","body":{"query":"{nodes {__typename ... on NodeA {__typename id}}}"}}`, + PostProcessing: DefaultPostProcessingConfiguration, + DataSource: &Source{}, + }, + DataSourceIdentifier: []byte("graphql_datasource.Source"), + }), + // Fetch 1: entity-resolve NodeA from second subgraph. + // Second subgraph owns pool (non-external on NodeA), Pool1.detail, and Detail.uniqueField, + // so all three can be resolved inline without additional entity fetches. + resolve.SingleWithPath(&resolve.SingleFetch{ + FetchDependencies: resolve.FetchDependencies{ + FetchID: 1, + DependsOnFetchIDs: []int{0}, + }, + FetchConfiguration: resolve.FetchConfiguration{ + RequiresEntityBatchFetch: true, + RequiresEntityFetch: false, + Input: `{"method":"POST","url":"http://second.service","body":{"query":"query($representations: [_Any!]!){_entities(representations: $representations){... on NodeA {__typename detail {__typename ... on Detail {__typename id}}}}}","variables":{"representations":[$$0$$]}}}`, + DataSource: &Source{}, + SetTemplateOutputToNullOnVariableNull: true, + Variables: []resolve.Variable{ + &resolve.ResolvableObjectVariable{ + Renderer: resolve.NewGraphQLVariableResolveRenderer(&resolve.Object{ + Nullable: true, + Fields: []*resolve.Field{ + { + Name: []byte("__typename"), + Value: &resolve.String{ + Path: []string{"__typename"}, + }, + OnTypeNames: [][]byte{[]byte("NodeA")}, + }, + { + Name: []byte("id"), + Value: &resolve.Scalar{ + Path: []string{"id"}, + }, + OnTypeNames: [][]byte{[]byte("NodeA")}, + }, + }, + }), + }, + }, + PostProcessing: EntitiesPostProcessingConfiguration, + }, + DataSourceIdentifier: []byte("graphql_datasource.Source"), + }, "nodes", resolve.ArrayPath("nodes")), + // Fetch 2: entity-resolve Detail from first subgraph to get sharedField. + // This is the jump back — first subgraph is the only owner of Detail.sharedField. + resolve.SingleWithPath(&resolve.SingleFetch{ + FetchDependencies: resolve.FetchDependencies{ + FetchID: 2, + DependsOnFetchIDs: []int{1}, + }, + FetchConfiguration: resolve.FetchConfiguration{ + RequiresEntityBatchFetch: true, + RequiresEntityFetch: false, + Input: `{"method":"POST","url":"http://first.service","body":{"query":"query($representations: [_Any!]!){_entities(representations: $representations){... on Detail {__typename uniqueField}}}","variables":{"representations":[$$0$$]}}}`, + DataSource: &Source{}, + SetTemplateOutputToNullOnVariableNull: true, + Variables: []resolve.Variable{ + &resolve.ResolvableObjectVariable{ + Renderer: resolve.NewGraphQLVariableResolveRenderer(&resolve.Object{ + Nullable: true, + Fields: []*resolve.Field{ + { + Name: []byte("__typename"), + Value: &resolve.String{ + Path: []string{"__typename"}, + }, + OnTypeNames: [][]byte{[]byte("Detail")}, + }, + { + Name: []byte("id"), + Value: &resolve.Scalar{ + Path: []string{"id"}, + }, + OnTypeNames: [][]byte{[]byte("Detail")}, + }, + }, + }), + }, + }, + PostProcessing: EntitiesPostProcessingConfiguration, + }, + DataSourceIdentifier: []byte("graphql_datasource.Source"), + }, "nodes.@.detail", resolve.ArrayPath("nodes"), resolve.PathElementWithTypeNames(resolve.ObjectPath("detail"), []string{"NodeA"})), + ), + Data: &resolve.Object{ + Fields: []*resolve.Field{ + { + Name: []byte("nodes"), + Value: &resolve.Array{ + Path: []string{"nodes"}, + Nullable: false, + Item: &resolve.Object{ + Nullable: false, + PossibleTypes: map[string]struct{}{ + "NodeA": {}, + }, + TypeName: "Node", + Fields: []*resolve.Field{ + { + Name: []byte("detail"), + OnTypeNames: [][]byte{[]byte("NodeA")}, + Value: &resolve.Object{ + Path: []string{"detail"}, + Nullable: false, + PossibleTypes: map[string]struct{}{ + "Detail": {}, + }, + TypeName: "Detailer", + Fields: []*resolve.Field{ + { + Name: []byte("uniqueField"), + Value: &resolve.String{ + Path: []string{"uniqueField"}, + }, + OnTypeNames: [][]byte{[]byte("Detail")}}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + planConfiguration, + WithDefaultPostProcessor(), + ) + }) + }) + }) } diff --git a/v2/pkg/engine/datasource/grpc_datasource/compiler.go b/v2/pkg/engine/datasource/grpc_datasource/compiler.go index d7926853a6..5a17a43a17 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/compiler.go +++ b/v2/pkg/engine/datasource/grpc_datasource/compiler.go @@ -399,6 +399,8 @@ type ServiceCall struct { Output protoref.Message // RPC is the call that was made to the gRPC service RPC *RPCCall + // Skip is true if the service call should not be invoked + Skip bool } func (s *ServiceCall) MethodFullName() string { @@ -464,6 +466,10 @@ func (p *RPCCompiler) CompileFetches(graph *DependencyGraph, fetches []FetchItem return nil, err } + if serviceCall.Skip { + continue + } + graph.SetFetchData(node.ID, &serviceCall) serviceCalls = append(serviceCalls, serviceCall) } @@ -508,8 +514,10 @@ func (p *RPCCompiler) CompileNode(graph *DependencyGraph, fetch FetchItem, input } request, err = p.buildProtoMessageWithContext(inputMessage, &call.Request, inputData, context) - if err != nil { - return ServiceCall{}, err + if err != nil || request == nil { + return ServiceCall{ + Skip: true, + }, err } } @@ -572,6 +580,12 @@ func (p *RPCCompiler) buildProtoMessageWithContext(inputMessage Message, rpcMess return nil, fmt.Errorf("context is required for resolve calls") } + // If the context is empty, we can skip the invocation + // Currently only one context is supported for resolve calls. This might be extended in the future. + if context[0].ServiceCall == nil || context[0].ServiceCall.Output == nil { + return nil, nil + } + if p.doc.MessageRefByName(rpcMessage.Name) == InvalidRef { return nil, fmt.Errorf("message %s not found in document", rpcMessage.Name) } @@ -597,9 +611,13 @@ func (p *RPCCompiler) buildProtoMessageWithContext(inputMessage Message, rpcMess return nil, fmt.Errorf("context field not found in message %s", inputMessage.Name) } - contextList := p.newEmptyListMessageByName(rootMessage, contextSchemaField.Name) - contextData := p.resolveContextData(context[0], contextRPCField) // TODO handle multiple contexts (resolver requires another resolver) + // TODO handle multiple contexts (resolver requires another resolver) + contextData := p.resolveContextData(context[0], contextRPCField) + if len(contextData) == 0 { + return nil, nil + } + contextList := p.newEmptyListMessageByName(rootMessage, contextSchemaField.Name) for _, contextElement := range contextData { val := contextList.NewElement() valMsg := val.Message() @@ -680,6 +698,10 @@ func (p *RPCCompiler) resolveContextDataForPath(message protoref.Message, path a // resolveListDataForPath resolves the data for a given path in a list message. func (p *RPCCompiler) resolveListDataForPath(message protoref.List, fd protoref.FieldDescriptor, path ast.Path) []protoref.Value { + if !message.IsValid() { + return nil + } + if path.Len() == 0 { return nil } @@ -713,6 +735,10 @@ func (p *RPCCompiler) resolveListDataForPath(message protoref.List, fd protoref. // resolveDataForPath resolves the data for a given path in a message. func (p *RPCCompiler) resolveDataForPath(messsage protoref.Message, path ast.Path) []protoref.Value { + if !messsage.IsValid() { + return nil + } + if path.Len() == 0 { return nil } @@ -738,9 +764,17 @@ func (p *RPCCompiler) resolveDataForPath(messsage protoref.Message, path ast.Pat switch fd.Kind() { case protoref.MessageKind: if fd.IsList() { + if !field.List().IsValid() { + return nil + } + return []protoref.Value{protoref.ValueOfList(field.List())} } + if !field.Message().IsValid() { + return nil + } + return p.resolveDataForPath(field.Message(), path[1:]) default: return []protoref.Value{field} diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go index eef14671ce..5d523446d7 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go @@ -102,8 +102,8 @@ type RPCMessage struct { Name string // Fields is a list of fields in the message Fields RPCFields - // FieldSelectionSet are field selections based on inline fragments - FieldSelectionSet RPCFieldSelectionSet + // FragmentFields are field selections based on inline fragments + FragmentFields RPCFieldSelectionSet // OneOfType indicates the type of the oneof field OneOfType OneOfType // MemberTypes provides the names of the types that are implemented by the Interface or Union @@ -275,6 +275,15 @@ func (r RPCFields) Exists(name, alias string) bool { return false } +// Last returns the last element of r or nil if r has no elements. +func (r RPCFields) Last() *RPCField { + if len(r) == 0 { + return nil + } + + return &r[len(r)-1] +} + func (r *RPCExecutionPlan) String() string { var result strings.Builder @@ -453,6 +462,45 @@ func (r *rpcPlanningContext) resolveRPCMethodMapping(operationType ast.Operation return rpcConfig, nil } +// enterNestedField handles descending into a nested response message +// when entering a selection set. inlineFragmentRef identifies the inline fragment +// that directly contains the field being descended into (ast.InvalidRef if none). +// Returns true if it descended into a nested message, false if there was nothing +// to descend into. +func (r *rpcPlanningContext) enterNestedField(info *planningInfo, enclosingTypeNode ast.Node, selectionSetRef, inlineFragmentRef int) bool { + lastField := r.lastResponseField(info.currentResponseMessage, inlineFragmentRef) + if lastField == nil { + return false + } + + if lastField.Message == nil { + lastField.Message = r.newMessageFromSelectionSet(enclosingTypeNode, selectionSetRef) + } + + info.responseMessageAncestors = append(info.responseMessageAncestors, info.currentResponseMessage) + info.currentResponseMessage = lastField.Message + return true +} + +// lastResponseField returns a pointer to the last field (or fragment field) of the message, +// or nil if there are no fields. +func (r *rpcPlanningContext) lastResponseField(msg *RPCMessage, inlineFragmentRef int) *RPCField { + if inlineFragmentRef == ast.InvalidRef { + return msg.Fields.Last() + } + + inlineFragmentName := r.operation.InlineFragmentTypeConditionNameString(inlineFragmentRef) + return msg.FragmentFields[inlineFragmentName].Last() +} + +// leaveNestedField pops the response message ancestors when leaving a selection set. +func (r *rpcPlanningContext) leaveNestedField(info *planningInfo) { + if len(info.responseMessageAncestors) > 0 { + info.currentResponseMessage = info.responseMessageAncestors[len(info.responseMessageAncestors)-1] + info.responseMessageAncestors = info.responseMessageAncestors[:len(info.responseMessageAncestors)-1] + } +} + // newMessageFromSelectionSet creates a new message from the enclosing type node and the selection set reference. func (r *rpcPlanningContext) newMessageFromSelectionSet(enclosingTypeNode ast.Node, selectSetRef int) *RPCMessage { message := &RPCMessage{ @@ -769,11 +817,11 @@ func (r *rpcPlanningContext) buildFieldMessage(fieldTypeNode ast.Node, fieldRef return nil, err } - if message.FieldSelectionSet == nil { - message.FieldSelectionSet = make(RPCFieldSelectionSet) + if message.FragmentFields == nil { + message.FragmentFields = make(RPCFieldSelectionSet) } - message.FieldSelectionSet.Add(typeName, fields...) + message.FragmentFields.Add(typeName, fields...) } for _, fieldRef := range fieldRefs { @@ -1081,7 +1129,7 @@ func (r *rpcPlanningContext) buildFieldResolverTypeMessage(typeName string, reso // If the resolved field returns a composite type we need to handle the selection set for the inline fragment. if len(resolverField.fragmentSelections) > 0 { - message.FieldSelectionSet = make(RPCFieldSelectionSet, len(resolverField.fragmentSelections)) + message.FragmentFields = make(RPCFieldSelectionSet, len(resolverField.fragmentSelections)) for _, fragmentSelection := range resolverField.fragmentSelections { inlineFragmentTypeNode, found := r.definition.NodeByNameStr(fragmentSelection.typeName) @@ -1094,7 +1142,7 @@ func (r *rpcPlanningContext) buildFieldResolverTypeMessage(typeName string, reso return nil, err } - message.FieldSelectionSet[fragmentSelection.typeName] = fields + message.FragmentFields[fragmentSelection.typeName] = fields } } diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_composite_test.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_composite_test.go index 1066d47000..761b735e4c 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_composite_test.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_composite_test.go @@ -43,7 +43,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Cat", "Dog", }, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "meow_volume", @@ -102,7 +102,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Cat", "Dog", }, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "meow_volume", @@ -169,7 +169,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Cat", "Dog", }, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "meow_volume", @@ -237,7 +237,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Dog", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Animal": { { Name: "id", @@ -365,7 +365,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Category", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Product": { { Name: "id", @@ -449,7 +449,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Category", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Product": { { Name: "id", @@ -557,7 +557,7 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { "Category", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Product": { { Name: "id", @@ -591,6 +591,373 @@ func TestCompositeTypeExecutionPlan(t *testing.T) { }, }, }, + { + name: "Should create an execution plan for a nested message inside an interface fragment with common fields", + query: "query CatOwnerQuery { randomPet { name kind ... on Cat { meowVolume owner { id name } } } }", + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "QueryRandomPet", + Request: RPCMessage{ + Name: "QueryRandomPetRequest", + }, + Response: RPCMessage{ + Name: "QueryRandomPetResponse", + Fields: []RPCField{ + { + Name: "random_pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "randomPet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "kind", + ProtoTypeName: DataTypeString, + JSONPath: "kind", + }, + }, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "meow_volume", + ProtoTypeName: DataTypeInt32, + JSONPath: "meowVolume", + }, + { + Name: "owner", + ProtoTypeName: DataTypeMessage, + JSONPath: "owner", + Message: &RPCMessage{ + Name: "Owner", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for a nested message inside an interface fragment with common fields on both sides", + query: "query CatOwnerQuery { randomPet { name ... on Cat { meowVolume owner { id name } } kind } }", + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "QueryRandomPet", + Request: RPCMessage{ + Name: "QueryRandomPetRequest", + }, + Response: RPCMessage{ + Name: "QueryRandomPetResponse", + Fields: []RPCField{ + { + Name: "random_pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "randomPet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "kind", + ProtoTypeName: DataTypeString, + JSONPath: "kind", + }, + }, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "meow_volume", + ProtoTypeName: DataTypeInt32, + JSONPath: "meowVolume", + }, + { + Name: "owner", + ProtoTypeName: DataTypeMessage, + JSONPath: "owner", + Message: &RPCMessage{ + Name: "Owner", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for a nested message inside an interface fragment without common fields", + query: "query CatBreedQuery { randomPet { ... on Cat { breed { name origin } } } }", + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "QueryRandomPet", + Request: RPCMessage{ + Name: "QueryRandomPetRequest", + }, + Response: RPCMessage{ + Name: "QueryRandomPetResponse", + Fields: []RPCField{ + { + Name: "random_pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "randomPet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "breed", + ProtoTypeName: DataTypeMessage, + JSONPath: "breed", + Message: &RPCMessage{ + Name: "CatBreed", + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "origin", + ProtoTypeName: DataTypeString, + JSONPath: "origin", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for a deeply nested message inside an inline fragment", + query: "query CatBreedCharacteristicsQuery { randomPet { ... on Cat { breed { characteristics { temperament } } } } }", + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "QueryRandomPet", + Request: RPCMessage{ + Name: "QueryRandomPetRequest", + }, + Response: RPCMessage{ + Name: "QueryRandomPetResponse", + Fields: []RPCField{ + { + Name: "random_pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "randomPet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "breed", + ProtoTypeName: DataTypeMessage, + JSONPath: "breed", + Message: &RPCMessage{ + Name: "CatBreed", + Fields: []RPCField{ + { + Name: "characteristics", + ProtoTypeName: DataTypeMessage, + JSONPath: "characteristics", + Message: &RPCMessage{ + Name: "BreedCharacteristics", + Fields: []RPCField{ + { + Name: "temperament", + ProtoTypeName: DataTypeString, + JSONPath: "temperament", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for nested inline fragments through an intermediate regular message", + query: "query OwnerPetQuery { randomPet { ... on Cat { owner { name pet { ... on Cat { breed { name origin } } ... on Dog { barkVolume } } } } } }", + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "QueryRandomPet", + Request: RPCMessage{ + Name: "QueryRandomPetRequest", + }, + Response: RPCMessage{ + Name: "QueryRandomPetResponse", + Fields: []RPCField{ + { + Name: "random_pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "randomPet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "owner", + ProtoTypeName: DataTypeMessage, + JSONPath: "owner", + Message: &RPCMessage{ + Name: "Owner", + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "pet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "breed", + ProtoTypeName: DataTypeMessage, + JSONPath: "breed", + Message: &RPCMessage{ + Name: "CatBreed", + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "origin", + ProtoTypeName: DataTypeString, + JSONPath: "origin", + }, + }, + }, + }, + }, + "Dog": { + { + Name: "bark_volume", + ProtoTypeName: DataTypeInt32, + JSONPath: "barkVolume", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, } for _, tt := range tests { @@ -683,7 +1050,7 @@ func TestMutationUnionExecutionPlan(t *testing.T) { "ActionError", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -765,7 +1132,7 @@ func TestMutationUnionExecutionPlan(t *testing.T) { "ActionError", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -835,7 +1202,7 @@ func TestMutationUnionExecutionPlan(t *testing.T) { "ActionError", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionError": { { Name: "message", diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_federation_test.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_federation_test.go index d858b173fb..e2cde3c829 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_federation_test.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_federation_test.go @@ -1598,7 +1598,7 @@ func TestEntityLookupWithFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "Animal", OneOfType: OneOfTypeInterface, MemberTypes: []string{"Cat", "Dog"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "name", @@ -1781,7 +1781,7 @@ func TestEntityLookupWithFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "ActionResult", OneOfType: OneOfTypeUnion, MemberTypes: []string{"ActionSuccess", "ActionError"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -1987,7 +1987,7 @@ func TestEntityLookupWithFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "Animal", OneOfType: OneOfTypeInterface, MemberTypes: []string{"Cat", "Dog"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "name", @@ -2023,7 +2023,7 @@ func TestEntityLookupWithFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "ActionResult", OneOfType: OneOfTypeUnion, MemberTypes: []string{"ActionSuccess", "ActionError"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -2094,6 +2094,894 @@ func TestEntityLookupWithFieldResolvers_WithCompositeTypes(t *testing.T) { } } +var nestedInlineFragmentFederationSchema = testFederationSchemaString(` + type Query { + _entities(representations: [_Any!]!): [_Entity]! + } + type User @key(fields: "id") { + id: ID! + name: String! + pet: Animal + } + interface Animal { + id: ID! + name: String! + kind: String! + } + type Cat implements Animal { + id: ID! + name: String! + kind: String! + meowVolume: Int! + owner: Owner! + breed: CatBreed! + } + type Dog implements Animal { + id: ID! + name: String! + kind: String! + barkVolume: Int! + } + type Owner { + id: ID! + name: String! + pet: Animal! + } + type CatBreed { + id: ID! + name: String! + origin: String! + characteristics: BreedCharacteristics! + } + type BreedCharacteristics { + temperament: String! + } + `, []string{"User"}) + +var nestedInlineFragmentFederationMapping = &GRPCMapping{ + Service: "Products", + EntityRPCs: map[string][]EntityRPCConfig{ + "User": { + { + Key: "id", + RPCConfig: RPCConfig{ + RPC: "LookupUserById", + Request: "LookupUserByIdRequest", + Response: "LookupUserByIdResponse", + }, + }, + }, + }, + Fields: map[string]FieldMap{ + "Cat": { + "meowVolume": {TargetName: "meow_volume"}, + }, + "Dog": { + "barkVolume": {TargetName: "bark_volume"}, + }, + }, +} + +var nestedInlineFragmentFederationConfigs = plan.FederationFieldConfigurations{ + { + TypeName: "User", + SelectionSet: "id", + }, +} + +func TestEntityLookupWithNestedInlineFragments(t *testing.T) { + t.Parallel() + tests := []struct { + name string + query string + schema string + expectedPlan *RPCExecutionPlan + mapping *GRPCMapping + federationConfigs plan.FederationFieldConfigurations + }{ + { + name: "Should create an execution plan for a nested message inside an entity with interface fragment and common fields", + query: `query EntityLookup($representations: [_Any!]!) { _entities(representations: $representations) { ... on User { __typename id name pet { name kind ... on Cat { meowVolume owner { id name } } } } } }`, + schema: nestedInlineFragmentFederationSchema, + mapping: nestedInlineFragmentFederationMapping, + federationConfigs: nestedInlineFragmentFederationConfigs, + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "LookupUserById", + Kind: CallKindEntity, + Request: RPCMessage{ + Name: "LookupUserByIdRequest", + Fields: []RPCField{ + { + Name: "keys", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "representations", + Message: &RPCMessage{ + Name: "LookupUserByIdKey", + MemberTypes: []string{"User"}, + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "LookupUserByIdResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "_entities", + Message: &RPCMessage{ + Name: "User", + Fields: []RPCField{ + { + Name: "__typename", + ProtoTypeName: DataTypeString, + JSONPath: "__typename", + StaticValue: "User", + }, + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "pet", + Optional: true, + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "kind", + ProtoTypeName: DataTypeString, + JSONPath: "kind", + }, + }, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "meow_volume", + ProtoTypeName: DataTypeInt32, + JSONPath: "meowVolume", + }, + { + Name: "owner", + ProtoTypeName: DataTypeMessage, + JSONPath: "owner", + Message: &RPCMessage{ + Name: "Owner", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for a nested message inside an entity with interface fragment without common fields", + query: `query EntityLookup($representations: [_Any!]!) { _entities(representations: $representations) { ... on User { __typename id pet { ... on Cat { breed { name origin } } } } } }`, + schema: nestedInlineFragmentFederationSchema, + mapping: nestedInlineFragmentFederationMapping, + federationConfigs: nestedInlineFragmentFederationConfigs, + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "LookupUserById", + Kind: CallKindEntity, + Request: RPCMessage{ + Name: "LookupUserByIdRequest", + Fields: []RPCField{ + { + Name: "keys", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "representations", + Message: &RPCMessage{ + Name: "LookupUserByIdKey", + MemberTypes: []string{"User"}, + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "LookupUserByIdResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "_entities", + Message: &RPCMessage{ + Name: "User", + Fields: []RPCField{ + { + Name: "__typename", + ProtoTypeName: DataTypeString, + JSONPath: "__typename", + StaticValue: "User", + }, + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "pet", + Optional: true, + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "breed", + ProtoTypeName: DataTypeMessage, + JSONPath: "breed", + Message: &RPCMessage{ + Name: "CatBreed", + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "origin", + ProtoTypeName: DataTypeString, + JSONPath: "origin", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for a deeply nested message inside an entity with inline fragment", + query: `query EntityLookup($representations: [_Any!]!) { _entities(representations: $representations) { ... on User { __typename id pet { ... on Cat { breed { characteristics { temperament } } } } } } }`, + schema: nestedInlineFragmentFederationSchema, + mapping: nestedInlineFragmentFederationMapping, + federationConfigs: nestedInlineFragmentFederationConfigs, + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "LookupUserById", + Kind: CallKindEntity, + Request: RPCMessage{ + Name: "LookupUserByIdRequest", + Fields: []RPCField{ + { + Name: "keys", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "representations", + Message: &RPCMessage{ + Name: "LookupUserByIdKey", + MemberTypes: []string{"User"}, + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "LookupUserByIdResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "_entities", + Message: &RPCMessage{ + Name: "User", + Fields: []RPCField{ + { + Name: "__typename", + ProtoTypeName: DataTypeString, + JSONPath: "__typename", + StaticValue: "User", + }, + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "pet", + Optional: true, + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "breed", + ProtoTypeName: DataTypeMessage, + JSONPath: "breed", + Message: &RPCMessage{ + Name: "CatBreed", + Fields: []RPCField{ + { + Name: "characteristics", + ProtoTypeName: DataTypeMessage, + JSONPath: "characteristics", + Message: &RPCMessage{ + Name: "BreedCharacteristics", + Fields: []RPCField{ + { + Name: "temperament", + ProtoTypeName: DataTypeString, + JSONPath: "temperament", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Should create an execution plan for nested inline fragments through an intermediate regular message in entity", + query: `query EntityLookup($representations: [_Any!]!) { _entities(representations: $representations) { ... on User { __typename id pet { ... on Cat { owner { name pet { ... on Cat { breed { name origin } } ... on Dog { barkVolume } } } } } } } }`, + schema: nestedInlineFragmentFederationSchema, + mapping: nestedInlineFragmentFederationMapping, + federationConfigs: nestedInlineFragmentFederationConfigs, + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "LookupUserById", + Kind: CallKindEntity, + Request: RPCMessage{ + Name: "LookupUserByIdRequest", + Fields: []RPCField{ + { + Name: "keys", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "representations", + Message: &RPCMessage{ + Name: "LookupUserByIdKey", + MemberTypes: []string{"User"}, + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "LookupUserByIdResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "_entities", + Message: &RPCMessage{ + Name: "User", + Fields: []RPCField{ + { + Name: "__typename", + ProtoTypeName: DataTypeString, + JSONPath: "__typename", + StaticValue: "User", + }, + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "pet", + Optional: true, + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "owner", + ProtoTypeName: DataTypeMessage, + JSONPath: "owner", + Message: &RPCMessage{ + Name: "Owner", + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "pet", + ProtoTypeName: DataTypeMessage, + JSONPath: "pet", + Message: &RPCMessage{ + Name: "Animal", + OneOfType: OneOfTypeInterface, + MemberTypes: []string{ + "Cat", + "Dog", + }, + Fields: RPCFields{}, + FragmentFields: RPCFieldSelectionSet{ + "Cat": { + { + Name: "breed", + ProtoTypeName: DataTypeMessage, + JSONPath: "breed", + Message: &RPCMessage{ + Name: "CatBreed", + Fields: []RPCField{ + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + { + Name: "origin", + ProtoTypeName: DataTypeString, + JSONPath: "origin", + }, + }, + }, + }, + }, + "Dog": { + { + Name: "bark_volume", + ProtoTypeName: DataTypeInt32, + JSONPath: "barkVolume", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + runFederationTest(t, tt) + } +} + +// complexResolverInNestedMessageFederationSchema defines an entity Product that has a +// regular (non-resolver) nested field "specs: ProductSpecs!". ProductSpecs contains a +// resolver field "relatedProduct" that returns another Product (complex return type), +// followed by a plain scalar field "dimensions". This combination is used to reproduce +// the bug where LeaveSelectionSet incorrectly pops the responseMessageAncestors stack +// for the resolver's selection set, causing "dimensions" to land in the wrong message. +var complexResolverInNestedMessageFederationSchema = ` +scalar connect__FieldSet +directive @connect__fieldResolver(context: connect__FieldSet!) on FIELD_DEFINITION + +schema { + query: Query +} + +type Query { + _entities(representations: [_Any!]!): [_Entity]! +} + +type Product @key(fields: "id") { + id: ID! + name: String! + specs: ProductSpecs! +} + +type ProductSpecs { + id: ID! + weight: Float! + relatedProduct(category: String!): Product @connect__fieldResolver(context: "id") + dimensions: String! +} + +union _Entity = Product +scalar _Any +` + +var complexResolverInNestedMessageFederationMapping = &GRPCMapping{ + Service: "Products", + EntityRPCs: map[string][]EntityRPCConfig{ + "Product": { + { + Key: "id", + RPCConfig: RPCConfig{ + RPC: "LookupProductById", + Request: "LookupProductByIdRequest", + Response: "LookupProductByIdResponse", + }, + }, + }, + }, + ResolveRPCs: RPCConfigMap[ResolveRPCMapping]{ + "ProductSpecs": { + "relatedProduct": ResolveRPCTypeField{ + FieldMappingData: FieldMapData{ + TargetName: "related_product", + ArgumentMappings: FieldArgumentMap{ + "category": "category", + }, + }, + RPC: "ResolveProductSpecsRelatedProduct", + Request: "ResolveProductSpecsRelatedProductRequest", + Response: "ResolveProductSpecsRelatedProductResponse", + }, + }, + }, + Fields: map[string]FieldMap{ + "Product": { + "id": {TargetName: "id"}, + "name": {TargetName: "name"}, + "specs": {TargetName: "specs"}, + }, + "ProductSpecs": { + "id": {TargetName: "id"}, + "weight": {TargetName: "weight"}, + "dimensions": {TargetName: "dimensions"}, + "relatedProduct": { + TargetName: "related_product", + ArgumentMappings: FieldArgumentMap{ + "category": "category", + }, + }, + }, + }, +} + +var complexResolverInNestedMessageFederationConfigs = plan.FederationFieldConfigurations{ + { + TypeName: "Product", + SelectionSet: "id", + }, +} + +// TestEntityLookupWithFieldResolvers_ComplexResolverInNestedMessage tests that fields +// following a complex-return-type resolver inside a nested message of an entity are placed +// into the correct parent message. This is a regression test for a bug where +// LeaveSelectionSet in the federation visitor incorrectly called leaveNestedField for +// a resolver field whose selection set never called enterNestedField. +// +// With the bug, the "dimensions" field that comes after "relatedProduct" in the +// "specs" selection set ends up in Product.Fields instead of ProductSpecs.Fields. +func TestEntityLookupWithFieldResolvers_ComplexResolverInNestedMessage(t *testing.T) { + t.Parallel() + + query := `query EntityLookup($representations: [_Any!]!, $category: String!) { + _entities(representations: $representations) { + ... on Product { + __typename + id + specs { + weight + relatedProduct(category: $category) { + id + name + } + dimensions + } + } + } + }` + + expectedPlan := &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "LookupProductById", + Kind: CallKindEntity, + Request: RPCMessage{ + Name: "LookupProductByIdRequest", + Fields: []RPCField{ + { + Name: "keys", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "representations", + Message: &RPCMessage{ + Name: "LookupProductByIdKey", + MemberTypes: []string{"Product"}, + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "LookupProductByIdResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + Repeated: true, + JSONPath: "_entities", + Message: &RPCMessage{ + Name: "Product", + Fields: []RPCField{ + { + Name: "__typename", + ProtoTypeName: DataTypeString, + JSONPath: "__typename", + StaticValue: "Product", + }, + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "specs", + ProtoTypeName: DataTypeMessage, + JSONPath: "specs", + // Both "weight" and "dimensions" must be in ProductSpecs.Fields. + // The bug causes "dimensions" to be placed in Product.Fields + // instead, because LeaveSelectionSet for the relatedProduct + // resolver selection set incorrectly pops the ProductSpecs + // message off responseMessageAncestors. + Message: &RPCMessage{ + Name: "ProductSpecs", + Fields: []RPCField{ + { + Name: "weight", + ProtoTypeName: DataTypeDouble, + JSONPath: "weight", + }, + { + Name: "dimensions", + ProtoTypeName: DataTypeString, + JSONPath: "dimensions", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + ID: 1, + DependentCalls: []int{0}, + ServiceName: "Products", + MethodName: "ResolveProductSpecsRelatedProduct", + Kind: CallKindResolve, + ResponsePath: buildPath("_entities.specs.relatedProduct"), + Request: RPCMessage{ + Name: "ResolveProductSpecsRelatedProductRequest", + Fields: []RPCField{ + { + Name: "context", + ProtoTypeName: DataTypeMessage, + Repeated: true, + Message: &RPCMessage{ + Name: "ResolveProductSpecsRelatedProductContext", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + ResolvePath: buildPath("result.specs.id"), + }, + }, + }, + }, + { + Name: "field_args", + ProtoTypeName: DataTypeMessage, + Message: &RPCMessage{ + Name: "ResolveProductSpecsRelatedProductArgs", + Fields: []RPCField{ + { + Name: "category", + ProtoTypeName: DataTypeString, + JSONPath: "category", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "ResolveProductSpecsRelatedProductResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + JSONPath: "result", + Repeated: true, + Message: &RPCMessage{ + Name: "ResolveProductSpecsRelatedProductResult", + Fields: []RPCField{ + { + Name: "related_product", + ProtoTypeName: DataTypeMessage, + JSONPath: "relatedProduct", + Optional: true, + Message: &RPCMessage{ + Name: "Product", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + t.Run("Should place fields after a complex resolver correctly in the parent message", func(t *testing.T) { + t.Parallel() + + definition := unsafeparser.ParseGraphqlDocumentStringWithBaseSchema(complexResolverInNestedMessageFederationSchema) + report := operationreport.Report{} + astvalidation.DefaultDefinitionValidator().Validate(&definition, &report) + if report.HasErrors() { + t.Fatalf("failed to validate schema: %s", report.Error()) + } + + operation, report := astparser.ParseGraphqlDocumentString(query) + if report.HasErrors() { + t.Fatalf("failed to parse query: %s", report.Error()) + } + + planner, err := NewPlanner("Products", complexResolverInNestedMessageFederationMapping, complexResolverInNestedMessageFederationConfigs) + if err != nil { + t.Fatalf("failed to create planner: %s", err) + } + plan, err := planner.PlanOperation(&operation, &definition) + if err != nil { + t.Fatalf("failed to plan operation: %s", err) + } + + diff := cmp.Diff(expectedPlan, plan) + if diff != "" { + t.Fatalf("execution plan mismatch: %s", diff) + } + }) +} + func runFederationTest(t *testing.T, tt struct { name string query string diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_field_resolvers_test.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_field_resolvers_test.go index 43ca958dc4..a2c8fc64f3 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_field_resolvers_test.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_field_resolvers_test.go @@ -2966,7 +2966,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "Animal", OneOfType: OneOfTypeInterface, MemberTypes: []string{"Cat", "Dog"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "name", @@ -3087,7 +3087,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "ActionResult", OneOfType: OneOfTypeUnion, MemberTypes: []string{"ActionSuccess", "ActionError"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -3247,7 +3247,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "Animal", OneOfType: OneOfTypeInterface, MemberTypes: []string{"Cat", "Dog"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "name", @@ -3410,7 +3410,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "ActionResult", OneOfType: OneOfTypeUnion, MemberTypes: []string{"ActionSuccess", "ActionError"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -3573,7 +3573,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "Animal", OneOfType: OneOfTypeInterface, MemberTypes: []string{"Cat", "Dog"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "name", @@ -3609,7 +3609,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "ActionResult", OneOfType: OneOfTypeUnion, MemberTypes: []string{"ActionSuccess", "ActionError"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "ActionSuccess": { { Name: "message", @@ -3772,7 +3772,7 @@ func TestExecutionPlanFieldResolvers_WithCompositeTypes(t *testing.T) { Name: "Animal", OneOfType: OneOfTypeInterface, MemberTypes: []string{"Cat", "Dog"}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "id", @@ -4053,10 +4053,10 @@ func TestExecutionPlanFieldResolvers_CustomSchemas(t *testing.T) { ProtoTypeName: DataTypeMessage, JSONPath: "fooResolver", Message: &RPCMessage{ - Name: "Bar", - FieldSelectionSet: RPCFieldSelectionSet{"Baz": {}}, - OneOfType: OneOfTypeInterface, - MemberTypes: []string{"Baz"}, + Name: "Bar", + FragmentFields: RPCFieldSelectionSet{"Baz": {}}, + OneOfType: OneOfTypeInterface, + MemberTypes: []string{"Baz"}, }, }, }, @@ -4377,6 +4377,184 @@ func TestExecutionPlanFieldResolvers_CustomSchemas(t *testing.T) { } } +// TestExecutionPlanFieldResolvers_ComplexResolverInNestedMessage tests that fields +// following a complex-return-type resolver inside a nested message are placed into +// the correct parent message. This is a regression test for a bug where +// LeaveSelectionSet incorrectly calls leaveNestedField for resolver fields whose +// selection set never called enterNestedField, corrupting the responseMessageAncestors +// stack and causing subsequent sibling fields to be added to the wrong message. +func TestExecutionPlanFieldResolvers_ComplexResolverInNestedMessage(t *testing.T) { + t.Parallel() + + // The query fetches categories -> subcategories, where inside the subcategory + // selection there is a complex-return-type field resolver (featuredCategory) + // followed by a regular scalar field (name). + // + // With the bug, LeaveSelectionSet for featuredCategory's selection set pops + // the Subcategory message off responseMessageAncestors even though + // enterNestedField was never called for it. As a result, the "name" field that + // comes after featuredCategory ends up in Category.Fields instead of + // Subcategory.Fields. + runTest(t, testCase{ + query: `query SubcategoryComplexResolverBug($includeChildren: Boolean!) { + categories { + id + subcategories { + id + featuredCategory(includeChildren: $includeChildren) { + id + name + } + name + } + } + }`, + expectedPlan: &RPCExecutionPlan{ + Calls: []RPCCall{ + { + ServiceName: "Products", + MethodName: "QueryCategories", + Request: RPCMessage{ + Name: "QueryCategoriesRequest", + }, + Response: RPCMessage{ + Name: "QueryCategoriesResponse", + Fields: []RPCField{ + { + Name: "categories", + ProtoTypeName: DataTypeMessage, + JSONPath: "categories", + Repeated: true, + Message: &RPCMessage{ + Name: "Category", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "subcategories", + ProtoTypeName: DataTypeMessage, + JSONPath: "subcategories", + IsListType: true, + Optional: true, + ListMetadata: &ListMetadata{ + NestingLevel: 1, + LevelInfo: []LevelInfo{{Optional: true}}, + }, + // Both "id" and "name" must be in Subcategory.Fields. + // The bug causes "name" to be placed in Category.Fields + // instead, because LeaveSelectionSet for the + // featuredCategory resolver selection set incorrectly + // pops the Subcategory message from the ancestor stack. + Message: &RPCMessage{ + Name: "Subcategory", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + ID: 1, + DependentCalls: []int{0}, + ServiceName: "Products", + MethodName: "ResolveSubcategoryFeaturedCategory", + Kind: CallKindResolve, + ResponsePath: buildPath("categories.subcategories.featuredCategory"), + Request: RPCMessage{ + Name: "ResolveSubcategoryFeaturedCategoryRequest", + Fields: []RPCField{ + { + Name: "context", + ProtoTypeName: DataTypeMessage, + Repeated: true, + Message: &RPCMessage{ + Name: "ResolveSubcategoryFeaturedCategoryContext", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + ResolvePath: buildPath("categories.@subcategories.id"), + }, + }, + }, + }, + { + Name: "field_args", + ProtoTypeName: DataTypeMessage, + Message: &RPCMessage{ + Name: "ResolveSubcategoryFeaturedCategoryArgs", + Fields: []RPCField{ + { + Name: "include_children", + ProtoTypeName: DataTypeBool, + JSONPath: "includeChildren", + }, + }, + }, + }, + }, + }, + Response: RPCMessage{ + Name: "ResolveSubcategoryFeaturedCategoryResponse", + Fields: []RPCField{ + { + Name: "result", + ProtoTypeName: DataTypeMessage, + JSONPath: "result", + Repeated: true, + Message: &RPCMessage{ + Name: "ResolveSubcategoryFeaturedCategoryResult", + Fields: []RPCField{ + { + Name: "featured_category", + ProtoTypeName: DataTypeMessage, + JSONPath: "featuredCategory", + Optional: true, + Message: &RPCMessage{ + Name: "Category", + Fields: []RPCField{ + { + Name: "id", + ProtoTypeName: DataTypeString, + JSONPath: "id", + }, + { + Name: "name", + ProtoTypeName: DataTypeString, + JSONPath: "name", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }) +} + func schemaWithNestedResolverAndCompositeType(t *testing.T) ast.Document { schema := ` diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go index a80896fb89..074c2967de 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go @@ -1808,7 +1808,7 @@ func TestProductExecutionPlanWithAliases(t *testing.T) { "Cat", "Dog", }, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "meow_volume", @@ -1882,7 +1882,7 @@ func TestProductExecutionPlanWithAliases(t *testing.T) { "Category", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Product": { { Name: "id", @@ -2382,7 +2382,7 @@ func TestProductExecutionPlanWithAliases(t *testing.T) { "Cat", "Dog", }, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Cat": { { Name: "meow_volume", @@ -2471,7 +2471,7 @@ func TestProductExecutionPlanWithAliases(t *testing.T) { "Category", }, Fields: RPCFields{}, - FieldSelectionSet: RPCFieldSelectionSet{ + FragmentFields: RPCFieldSelectionSet{ "Product": { { Name: "id", diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go index 85f1878dd2..f04d44f47a 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go @@ -220,22 +220,20 @@ func (r *rpcPlanVisitor) EnterSelectionSet(ref int) { return } - // If we don't have any fields or selecting on a field, we can return. - if len(r.planInfo.currentResponseMessage.Fields) == 0 || r.walker.Ancestor().Kind != ast.NodeKindField { + // If we don't select on a field, we can return. + if r.walker.Ancestor().Kind != ast.NodeKindField { return } - lastIndex := len(r.planInfo.currentResponseMessage.Fields) - 1 - - // In nested selection sets, a new message needs to be created, which will be added to the current response message. - if r.planInfo.currentResponseMessage.Fields[lastIndex].Message == nil { - r.planInfo.currentResponseMessage.Fields[lastIndex].Message = r.planCtx.newMessageFromSelectionSet(r.walker.EnclosingTypeDefinition, ref) + // Determine which inline fragment directly contains the field we are about + // to descend into. When entering a field's selection set, the walker Ancestors + // are: [..., (maybe inline fragment), parent selection set, field]. + // Ancestors[-3] is therefore the inline fragment directly wrapping the field, if any. + inlineFragmentRef := inlineFragmentRefFromAncestors(r.walker.Ancestors) + if !r.planCtx.enterNestedField(&r.planInfo, r.walker.EnclosingTypeDefinition, ref, inlineFragmentRef) { + return } - // Add the current response message to the ancestors and set the current response message to the current field message - r.planInfo.responseMessageAncestors = append(r.planInfo.responseMessageAncestors, r.planInfo.currentResponseMessage) - r.planInfo.currentResponseMessage = r.planInfo.currentResponseMessage.Fields[lastIndex].Message - // Check if the ancestor type is a composite type (interface or union) // and set the oneof type and member types. if err := r.handleCompositeType(r.walker.Ancestor()); err != nil { @@ -286,14 +284,14 @@ func (r *rpcPlanVisitor) handleCompositeType(node ast.Node) error { // It updates the current response field index and response message ancestors. // If the ancestor is an operation definition, it adds the current call to the group. func (r *rpcPlanVisitor) LeaveSelectionSet(ref int) { + if r.fieldResolverAncestors.len() > 0 && r.walker.Ancestor().Kind == ast.NodeKindField { + return + } if r.walker.Ancestor().Kind == ast.NodeKindInlineFragment { return } - if len(r.planInfo.responseMessageAncestors) > 0 { - r.planInfo.currentResponseMessage = r.planInfo.responseMessageAncestors[len(r.planInfo.responseMessageAncestors)-1] - r.planInfo.responseMessageAncestors = r.planInfo.responseMessageAncestors[:len(r.planInfo.responseMessageAncestors)-1] - } + r.planCtx.leaveNestedField(&r.planInfo) } func (r *rpcPlanVisitor) handleRootField(isRootField bool, ref int) error { @@ -385,12 +383,12 @@ func (r *rpcPlanVisitor) EnterField(ref int) { // check if we are inside of an inline fragment if ref, ok := r.walker.ResolveInlineFragment(); ok { - if r.planInfo.currentResponseMessage.FieldSelectionSet == nil { - r.planInfo.currentResponseMessage.FieldSelectionSet = make(RPCFieldSelectionSet) + if r.planInfo.currentResponseMessage.FragmentFields == nil { + r.planInfo.currentResponseMessage.FragmentFields = make(RPCFieldSelectionSet) } inlineFragmentName := r.operation.InlineFragmentTypeConditionNameString(ref) - r.planInfo.currentResponseMessage.FieldSelectionSet.Add(inlineFragmentName, field) + r.planInfo.currentResponseMessage.FragmentFields.Add(inlineFragmentName, field) return } diff --git a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor_federation.go b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor_federation.go index 2481dc224f..f7553c782c 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor_federation.go +++ b/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor_federation.go @@ -162,7 +162,6 @@ func (r *rpcPlanVisitorFederation) EnterInlineFragment(ref int) { // LeaveInlineFragment implements astvisitor.InlineFragmentVisitor. func (r *rpcPlanVisitorFederation) LeaveInlineFragment(ref int) { if r.entityInfo.entityInlineFragmentRef != ref { - // We only handle the entity inline fragment return } @@ -209,21 +208,21 @@ func (r *rpcPlanVisitorFederation) EnterSelectionSet(ref int) { return } - if r.planInfo.currentRequestMessage == nil || len(r.planInfo.currentResponseMessage.Fields) == 0 || r.walker.Ancestor().Kind != ast.NodeKindField { + if r.planInfo.currentRequestMessage == nil || r.walker.Ancestor().Kind != ast.NodeKindField { return } - // We ignore selection sets from inline fragments or fragment spreads. - lastIndex := len(r.planInfo.currentResponseMessage.Fields) - 1 - - // In nested selection sets, a new message needs to be created, which will be added to the current response message. - if r.planInfo.currentResponseMessage.Fields[lastIndex].Message == nil { - r.planInfo.currentResponseMessage.Fields[lastIndex].Message = r.planCtx.newMessageFromSelectionSet(r.walker.EnclosingTypeDefinition, ref) + // Determine which inline fragment directly contains the field we are about + // to descend into, excluding the entity inline fragment whose fields are + // treated as regular (non-fragment) fields. + inlineFragmentRef := inlineFragmentRefFromAncestors(r.walker.Ancestors) + if inlineFragmentRef == r.entityInfo.entityInlineFragmentRef { + inlineFragmentRef = ast.InvalidRef } - // Add the current response message to the ancestors and set the current response message to the current field message - r.planInfo.responseMessageAncestors = append(r.planInfo.responseMessageAncestors, r.planInfo.currentResponseMessage) - r.planInfo.currentResponseMessage = r.planInfo.currentResponseMessage.Fields[lastIndex].Message + if !r.planCtx.enterNestedField(&r.planInfo, r.walker.EnclosingTypeDefinition, ref, inlineFragmentRef) { + return + } // Check if the ancestor type is a composite type (interface or union) // and set the oneof type and member types. @@ -233,7 +232,6 @@ func (r *rpcPlanVisitorFederation) EnterSelectionSet(ref int) { r.walker.StopWithInternalErr(err) return } - } func (r *rpcPlanVisitorFederation) handleCompositeType(node ast.Node) error { @@ -274,14 +272,14 @@ func (r *rpcPlanVisitorFederation) handleCompositeType(node ast.Node) error { // LeaveSelectionSet implements astvisitor.SelectionSetVisitor. func (r *rpcPlanVisitorFederation) LeaveSelectionSet(ref int) { + if r.fieldResolverAncestors.len() > 0 && r.walker.Ancestor().Kind == ast.NodeKindField { + return + } if r.walker.Ancestor().Kind == ast.NodeKindInlineFragment { return } - if len(r.planInfo.responseMessageAncestors) > 0 { - r.planInfo.currentResponseMessage = r.planInfo.responseMessageAncestors[len(r.planInfo.responseMessageAncestors)-1] - r.planInfo.responseMessageAncestors = r.planInfo.responseMessageAncestors[:len(r.planInfo.responseMessageAncestors)-1] - } + r.planCtx.leaveNestedField(&r.planInfo) } // EnterField implements astvisitor.FieldVisitor. @@ -351,12 +349,12 @@ func (r *rpcPlanVisitorFederation) EnterField(ref int) { // check if we are inside of an inline fragment and not the entity inline fragment if ref, ok := r.walker.ResolveInlineFragment(); ok && r.entityInfo.entityInlineFragmentRef != ref { - if r.planInfo.currentResponseMessage.FieldSelectionSet == nil { - r.planInfo.currentResponseMessage.FieldSelectionSet = make(RPCFieldSelectionSet) + if r.planInfo.currentResponseMessage.FragmentFields == nil { + r.planInfo.currentResponseMessage.FragmentFields = make(RPCFieldSelectionSet) } inlineFragmentName := r.operation.InlineFragmentTypeConditionNameString(ref) - r.planInfo.currentResponseMessage.FieldSelectionSet.Add(inlineFragmentName, field) + r.planInfo.currentResponseMessage.FragmentFields.Add(inlineFragmentName, field) return } diff --git a/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_spy_test.go b/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_spy_test.go new file mode 100644 index 0000000000..f9e710d6a2 --- /dev/null +++ b/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_spy_test.go @@ -0,0 +1,180 @@ +package grpcdatasource + +import ( + "context" + "fmt" + "net" + "sync/atomic" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/test/bufconn" + + "github.com/wundergraph/graphql-go-tools/v2/pkg/astparser" + "github.com/wundergraph/graphql-go-tools/v2/pkg/grpctest" + "github.com/wundergraph/graphql-go-tools/v2/pkg/grpctest/productv1" +) + +// mockServiceSpy wraps MockService and counts calls to the methods +type mockServiceSpy struct { + grpctest.MockService + + categoriesCalls atomic.Int64 + categoryCalls atomic.Int64 + normalizedScoreCalls atomic.Int64 + relatedCategoryCalls atomic.Int64 + productCountCalls atomic.Int64 + popularityScoreCalls atomic.Int64 + categoryMetricsCalls atomic.Int64 + mascotCalls atomic.Int64 + + queryCategoryFunc func(ctx context.Context, req *productv1.QueryCategoryRequest) (*productv1.QueryCategoryResponse, error) +} + +func (s *mockServiceSpy) QueryCategories(ctx context.Context, req *productv1.QueryCategoriesRequest) (*productv1.QueryCategoriesResponse, error) { + s.categoriesCalls.Add(1) + return s.MockService.QueryCategories(ctx, req) +} + +func (s *mockServiceSpy) QueryCategory(ctx context.Context, req *productv1.QueryCategoryRequest) (*productv1.QueryCategoryResponse, error) { + s.categoryCalls.Add(1) + if s.queryCategoryFunc != nil { + return s.queryCategoryFunc(ctx, req) + } + return s.MockService.QueryCategory(ctx, req) +} + +func (s *mockServiceSpy) ResolveCategoryMetricsNormalizedScore(ctx context.Context, req *productv1.ResolveCategoryMetricsNormalizedScoreRequest) (*productv1.ResolveCategoryMetricsNormalizedScoreResponse, error) { + s.normalizedScoreCalls.Add(1) + return s.MockService.ResolveCategoryMetricsNormalizedScore(ctx, req) +} + +func (s *mockServiceSpy) ResolveCategoryMetricsRelatedCategory(ctx context.Context, req *productv1.ResolveCategoryMetricsRelatedCategoryRequest) (*productv1.ResolveCategoryMetricsRelatedCategoryResponse, error) { + s.relatedCategoryCalls.Add(1) + return s.MockService.ResolveCategoryMetricsRelatedCategory(ctx, req) +} + +func (s *mockServiceSpy) ResolveCategoryProductCount(ctx context.Context, req *productv1.ResolveCategoryProductCountRequest) (*productv1.ResolveCategoryProductCountResponse, error) { + s.productCountCalls.Add(1) + return s.MockService.ResolveCategoryProductCount(ctx, req) +} + +func (s *mockServiceSpy) ResolveCategoryPopularityScore(ctx context.Context, req *productv1.ResolveCategoryPopularityScoreRequest) (*productv1.ResolveCategoryPopularityScoreResponse, error) { + s.popularityScoreCalls.Add(1) + return s.MockService.ResolveCategoryPopularityScore(ctx, req) +} + +func (s *mockServiceSpy) ResolveCategoryCategoryMetrics(ctx context.Context, req *productv1.ResolveCategoryCategoryMetricsRequest) (*productv1.ResolveCategoryCategoryMetricsResponse, error) { + s.categoryMetricsCalls.Add(1) + return s.MockService.ResolveCategoryCategoryMetrics(ctx, req) +} + +func (s *mockServiceSpy) ResolveCategoryMascot(ctx context.Context, req *productv1.ResolveCategoryMascotRequest) (*productv1.ResolveCategoryMascotResponse, error) { + s.mascotCalls.Add(1) + return s.MockService.ResolveCategoryMascot(ctx, req) +} + +func setupSpyServer(t *testing.T) (*mockServiceSpy, *grpc.ClientConn, func()) { + spy := &mockServiceSpy{} + lis := bufconn.Listen(1024 * 1024) + server := grpc.NewServer() + productv1.RegisterProductServiceServer(server, spy) + go func() { + if err := server.Serve(lis); err != nil { + t.Errorf("failed to serve: %v", err) + } + }() + + conn, err := grpc.NewClient( + "passthrough:///bufnet", + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return lis.Dial() }), + grpc.WithLocalDNSResolution(), + ) + require.NoError(t, err) + + return spy, conn, func() { + conn.Close() + server.Stop() + lis.Close() + } +} + +// Test_DataSource_Load_NullMetrics_NestedResolversNotInvoked verifies that when nullMetrics +// is always null, the nested field resolver RPCs (normalizedScore, relatedCategory, productCount) +// are never invoked by the engine. +func Test_DataSource_Load_NullMetrics_NestedResolversNotInvoked(t *testing.T) { + spy, conn, cleanup := setupSpyServer(t) + t.Cleanup(cleanup) + + query := "query CategoriesWithNullMetrics($baseline: Float!, $include: Boolean) { categories { id name nullMetrics { id normalizedScore(baseline: $baseline) relatedCategory(include: $include) { id name productCount } } } }" + vars := `{"variables":{"baseline":100,"include":true}}` + + schemaDoc := grpctest.MustGraphQLSchema(t) + queryDoc, report := astparser.ParseGraphqlDocumentString(query) + require.False(t, report.HasErrors(), "failed to parse query: %s", report.Error()) + + compiler, err := NewProtoCompiler(grpctest.MustProtoSchema(t), testMapping()) + require.NoError(t, err) + + ds, err := NewDataSource(conn, DataSourceConfig{ + Operation: &queryDoc, + Definition: &schemaDoc, + SubgraphName: "Products", + Mapping: testMapping(), + Compiler: compiler, + }) + require.NoError(t, err) + + input := fmt.Sprintf(`{"query":%q,"body":%s}`, query, vars) + _, err = ds.Load(context.Background(), nil, []byte(input)) + require.NoError(t, err) + + require.Equal(t, int64(1), spy.categoriesCalls.Load(), "QueryCategories must be called") + require.Zero(t, spy.normalizedScoreCalls.Load(), "ResolveCategoryMetricsNormalizedScore must not be called when parent nullMetrics is null") + require.Zero(t, spy.relatedCategoryCalls.Load(), "ResolveCategoryMetricsRelatedCategory must not be called when parent nullMetrics is null") + require.Zero(t, spy.productCountCalls.Load(), "ResolveCategoryProductCount must not be called when parent nullMetrics is null") +} + +// Test_DataSource_Load_NullCategory_FieldResolversNotInvoked verifies that when the top-level +// category query returns null, no nested field resolver RPCs are invoked by the engine. +func Test_DataSource_Load_NullCategory_FieldResolversNotInvoked(t *testing.T) { + spy, conn, cleanup := setupSpyServer(t) + t.Cleanup(cleanup) + + spy.queryCategoryFunc = func(_ context.Context, _ *productv1.QueryCategoryRequest) (*productv1.QueryCategoryResponse, error) { + return &productv1.QueryCategoryResponse{ + Category: nil, + }, nil + } + + query := `query CategoryQuery($id: ID!, $threshold: Int, $metricType: String!, $includeVolume: Boolean!) { category(id: $id) { id name popularityScore(threshold: $threshold) categoryMetrics(metricType: $metricType) { id } mascot(includeVolume: $includeVolume) { ... on Cat { id } } } }` + vars := `{"variables":{"id":"cat-1","threshold":10,"metricType":"views","includeVolume":true}}` + + schemaDoc := grpctest.MustGraphQLSchema(t) + queryDoc, report := astparser.ParseGraphqlDocumentString(query) + require.False(t, report.HasErrors(), "failed to parse query: %s", report.Error()) + + compiler, err := NewProtoCompiler(grpctest.MustProtoSchema(t), testMapping()) + require.NoError(t, err) + + ds, err := NewDataSource(conn, DataSourceConfig{ + Operation: &queryDoc, + Definition: &schemaDoc, + SubgraphName: "Products", + Mapping: testMapping(), + Compiler: compiler, + }) + require.NoError(t, err) + + input := fmt.Sprintf(`{"query":%q,"body":%s}`, query, vars) + _, err = ds.Load(context.Background(), nil, []byte(input)) + require.NoError(t, err) + + require.Equal(t, int64(1), spy.categoryCalls.Load(), "QueryCategory must be called once") + require.Zero(t, spy.popularityScoreCalls.Load(), "ResolveCategoryPopularityScore must not be called when category is null") + require.Zero(t, spy.categoryMetricsCalls.Load(), "ResolveCategoryCategoryMetrics must not be called when category is null") + require.Zero(t, spy.mascotCalls.Load(), "ResolveCategoryMascot must not be called when category is null") +} diff --git a/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go b/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go index 5846a2ab64..d9a3e0bce3 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go +++ b/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go @@ -156,10 +156,8 @@ func setupTestGRPCServer(t testing.TB) (conn *grpc.ClientConn, cleanup func()) { } // Connect using bufconn dialer - // see https://github.com/grpc/grpc-go/issues/7091 - // nolint: staticcheck - conn, err := grpc.Dial( - "bufnet", + conn, err := grpc.NewClient( + "passthrough:///bufnet", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(bufDialer), grpc.WithLocalDNSResolution(), @@ -5194,6 +5192,32 @@ func Test_Datasource_Load_WithFieldResolvers(t *testing.T) { require.Empty(t, errData) }, }, + { + // nullMetrics is always null. The field resolvers at two levels of nesting (normalizedScore on CategoryMetrics, + // and relatedCategory on CategoryMetrics which itself carries the productCount field resolver on Category) + // should not be invoked. + name: "Query with nullMetrics and two levels of nested field resolvers", + query: "query CategoriesWithNullMetrics($baseline: Float!, $include: Boolean) { categories { id name nullMetrics { id normalizedScore(baseline: $baseline) relatedCategory(include: $include) { id name productCount } } } }", + vars: `{"variables":{"baseline":100,"include":true}}`, + validate: func(t *testing.T, data map[string]interface{}) { + require.NotEmpty(t, data) + categories, ok := data["categories"].([]interface{}) + require.True(t, ok, "categories should be an array") + require.NotEmpty(t, categories, "categories should not be empty") + require.Len(t, categories, 4, "Should return 4 categories") + + for _, cat := range categories { + category, ok := cat.(map[string]interface{}) + require.True(t, ok, "category should be an object") + require.NotEmpty(t, category["id"], "category id should not be empty") + require.NotEmpty(t, category["name"], "category name should not be empty") + require.Nil(t, category["nullMetrics"], "nullMetrics should be null since it is never populated") + } + }, + validateError: func(t *testing.T, errData []graphqlError) { + require.Empty(t, errData) + }, + }, } for _, tc := range testCases { diff --git a/v2/pkg/engine/datasource/grpc_datasource/json_builder.go b/v2/pkg/engine/datasource/grpc_datasource/json_builder.go index 95475720c2..3eeff2a047 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/json_builder.go +++ b/v2/pkg/engine/datasource/grpc_datasource/json_builder.go @@ -277,6 +277,10 @@ func (j *jsonBuilder) flattenObject(value *astjson.Value, path ast.Path) ([]*ast segment := path[0] current := value.Get(segment.FieldName.String()) + if current == nil { + return nil, fmt.Errorf("field %s not found in object", segment.FieldName.String()) + } + result := make([]*astjson.Value, 0) switch current.Type() { case astjson.TypeObject: @@ -350,7 +354,7 @@ func (j *jsonBuilder) marshalResponseJSON(message *RPCMessage, data protoref.Mes validFields := message.Fields if message.IsOneOf() { // For oneOf types, add type-specific fields based on the actual concrete type - validFields = append(validFields, message.FieldSelectionSet.SelectFieldsForTypes(message.SelectValidTypes(string(data.Type().Descriptor().Name())))...) + validFields = append(validFields, message.FragmentFields.SelectFieldsForTypes(message.SelectValidTypes(string(data.Type().Descriptor().Name())))...) } // Process each field in the message diff --git a/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go b/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go index 8b36b7b98f..0ff2e69a41 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go +++ b/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go @@ -49,6 +49,11 @@ func testMapping() *GRPCMapping { Request: "QueryCategoriesRequest", Response: "QueryCategoriesResponse", }, + "category": { + RPC: "QueryCategory", + Request: "QueryCategoryRequest", + Response: "QueryCategoryResponse", + }, "categoriesByKind": { RPC: "QueryCategoriesByKind", Request: "QueryCategoriesByKindRequest", @@ -320,6 +325,17 @@ func testMapping() *GRPCMapping { Request: "ResolveCategoryMetricsNormalizedScoreRequest", Response: "ResolveCategoryMetricsNormalizedScoreResponse", }, + "relatedCategory": { + FieldMappingData: FieldMapData{ + TargetName: "related_category", + ArgumentMappings: FieldArgumentMap{ + "include": "include", + }, + }, + RPC: "ResolveCategoryMetricsRelatedCategory", + Request: "ResolveCategoryMetricsRelatedCategoryRequest", + Response: "ResolveCategoryMetricsRelatedCategoryResponse", + }, }, "Product": { "shippingEstimate": { @@ -390,6 +406,17 @@ func testMapping() *GRPCMapping { Request: "ResolveSubcategoryItemCountRequest", Response: "ResolveSubcategoryItemCountResponse", }, + "featuredCategory": { + FieldMappingData: FieldMapData{ + TargetName: "featured_category", + ArgumentMappings: FieldArgumentMap{ + "includeChildren": "include_children", + }, + }, + RPC: "ResolveSubcategoryFeaturedCategory", + Request: "ResolveSubcategoryFeaturedCategoryRequest", + Response: "ResolveSubcategoryFeaturedCategoryResponse", + }, }, "TestContainer": { "details": { @@ -495,6 +522,12 @@ func testMapping() *GRPCMapping { "categories": { TargetName: "categories", }, + "category": { + TargetName: "category", + ArgumentMappings: FieldArgumentMap{ + "id": "id", + }, + }, "categoriesByKind": { TargetName: "categories_by_kind", ArgumentMappings: FieldArgumentMap{ @@ -974,6 +1007,9 @@ func testMapping() *GRPCMapping { "include": "include", }, }, + "nullMetrics": { + TargetName: "null_metrics", + }, }, "Subcategory": { "id": { @@ -994,6 +1030,12 @@ func testMapping() *GRPCMapping { "filters": "filters", }, }, + "featuredCategory": { + TargetName: "featured_category", + ArgumentMappings: FieldArgumentMap{ + "includeChildren": "include_children", + }, + }, }, "CategoryMetrics": { "id": { @@ -1019,6 +1061,9 @@ func testMapping() *GRPCMapping { }, "relatedCategory": { TargetName: "related_category", + ArgumentMappings: FieldArgumentMap{ + "include": "include", + }, }, }, "Cat": { @@ -1071,6 +1116,9 @@ func testMapping() *GRPCMapping { "contact": { TargetName: "contact", }, + "pet": { + TargetName: "pet", + }, }, "ContactInfo": { "email": { diff --git a/v2/pkg/engine/datasource/grpc_datasource/util.go b/v2/pkg/engine/datasource/grpc_datasource/util.go index 48dc37d44b..3d98da493b 100644 --- a/v2/pkg/engine/datasource/grpc_datasource/util.go +++ b/v2/pkg/engine/datasource/grpc_datasource/util.go @@ -1,5 +1,7 @@ package grpcdatasource +import "github.com/wundergraph/graphql-go-tools/v2/pkg/ast" + // initializeSlice initializes a slice with a given length and a given value. func initializeSlice[T any](len int, zero T) []T { s := make([]T, len) @@ -47,3 +49,24 @@ func (a *stack[T]) len() int { func (a *stack[T]) capacity() int { return cap(*a) } + +// inlineFragmentRefFromAncestors returns the inline fragment ref for the field +// at the top of the walker's ancestor stack, or ast.InvalidRef if the field is +// not a direct child of an inline fragment. +// +// When entering a field's selection set, the walker Ancestors slice has the shape: +// +// [..., (maybe inline fragment), parent selection set, field] +// +// Ancestors[-3] is therefore the node that directly contains the parent selection +// set — an inline fragment if and only if the field is a direct child of one. +func inlineFragmentRefFromAncestors(ancestors []ast.Node) int { + if len(ancestors) < 3 { + return ast.InvalidRef + } + ancestor := ancestors[len(ancestors)-3] + if ancestor.Kind != ast.NodeKindInlineFragment { + return ast.InvalidRef + } + return ancestor.Ref +} diff --git a/v2/pkg/engine/plan/datasource_filter_visitor.go b/v2/pkg/engine/plan/datasource_filter_visitor.go index 1e5d03cd13..6dc9c59139 100644 --- a/v2/pkg/engine/plan/datasource_filter_visitor.go +++ b/v2/pkg/engine/plan/datasource_filter_visitor.go @@ -262,10 +262,9 @@ func (f *DataSourceFilter) selectUniqNodeParentsUpToRootNode(i int) { nodesIdsToSelect = append(nodesIdsToSelect, parentIdx) if f.nodes.items[parentIdx].IsExternal && !f.nodes.items[i].IsProvided { - // such a parent can't be selected, - // so we skip this parent but continue looking for a potential root node higher - current = parentIdx - continue + // parent can't be selected because it is fully external + // we will have to find another way to get to this node + break } // TODO: there could be a potential situation when we have selected root node with enabled entity resolver, diff --git a/v2/pkg/engine/resolve/errors.go b/v2/pkg/engine/resolve/errors.go index 93b43f8c01..81b9d748da 100644 --- a/v2/pkg/engine/resolve/errors.go +++ b/v2/pkg/engine/resolve/errors.go @@ -2,8 +2,11 @@ package resolve import ( "bytes" + "encoding/json" "fmt" "slices" + + "github.com/wundergraph/astjson" ) type GraphQLError struct { @@ -11,7 +14,7 @@ type GraphQLError struct { Locations []Location `json:"locations,omitempty"` // Path is a list of path segments that lead to the error, can be number or string Path []any `json:"path"` - Extensions map[string]any `json:"extensions,omitempty"` + Extensions *astjson.Value `json:"extensions,omitempty"` } type Location struct { @@ -19,6 +22,57 @@ type Location struct { Column uint32 `json:"column"` } +// UnmarshalJSON unmarshals the GraphQLError from JSON. +// It unmarshals the Extensions field as a json.RawMessage and then parses it into an astjson.Value. +// This is necessary because we want to be able to keep the orginal order of the extensions fields. +func (e *GraphQLError) UnmarshalJSON(data []byte) error { + type Alias GraphQLError + + aux := &struct { + *Alias + + Extensions json.RawMessage `json:"extensions,omitempty"` + }{ + Alias: (*Alias)(e), + } + + if err := json.Unmarshal(data, aux); err != nil { + return err + } + + if len(aux.Extensions) > 0 { + extensions, err := astjson.ParseBytes(aux.Extensions) + if err != nil { + return err + } + + if extensions.Type() != astjson.TypeNull { + e.Extensions = extensions + } + } + + return nil +} + +// MarshalJSON marshals the GraphQLError to JSON. +// This is necessary because we need to marshal the Extensions field from an astjson.Value to a json.RawMessage. +func (e GraphQLError) MarshalJSON() ([]byte, error) { + type Alias GraphQLError + aux := &struct { + *Alias + + Extensions json.RawMessage `json:"extensions,omitempty"` + }{ + Alias: (*Alias)(&e), + } + + if e.Extensions != nil { + aux.Extensions = e.Extensions.MarshalTo(nil) + } + + return json.Marshal(aux) +} + type SubgraphError struct { DataSourceInfo DataSourceInfo Path string @@ -45,11 +99,10 @@ func (e *SubgraphError) Codes() []string { codes := make([]string, 0, len(e.DownstreamErrors)) for _, downstreamError := range e.DownstreamErrors { - if downstreamError.Extensions != nil { - if ok := downstreamError.Extensions["code"]; ok != nil { - if code, ok := downstreamError.Extensions["code"].(string); ok && !slices.Contains(codes, code) { - codes = append(codes, code) - } + if code := downstreamError.Extensions.Get("code"); code != nil { + codeStr := string(code.GetStringBytes()) + if !slices.Contains(codes, codeStr) { + codes = append(codes, codeStr) } } } diff --git a/v2/pkg/engine/resolve/loader.go b/v2/pkg/engine/resolve/loader.go index e01f0ca32a..8c6fbed84f 100644 --- a/v2/pkg/engine/resolve/loader.go +++ b/v2/pkg/engine/resolve/loader.go @@ -777,12 +777,14 @@ func (l *Loader) optionallyAllowCustomExtensionProperties(values []*astjson.Valu value.Del("extensions") continue } + newExt := astjson.ObjectValue(l.jsonArena) - for key := range l.allowedErrorExtensionFields { - if v := extensions.Get(key); v != nil { - newExt.Set(l.jsonArena, key, v) + extensions.GetObject().Visit(func(key []byte, v *astjson.Value) { + if _, ok := l.allowedErrorExtensionFields[unsafebytes.BytesToString(key)]; ok { + newExt.Set(l.jsonArena, string(key), v) } - } + }) + if newExt.GetObject().Len() == 0 { value.Del("extensions") continue diff --git a/v2/pkg/engine/resolve/loader_hooks_test.go b/v2/pkg/engine/resolve/loader_hooks_test.go index 36cc19449b..11462d8c3b 100644 --- a/v2/pkg/engine/resolve/loader_hooks_test.go +++ b/v2/pkg/engine/resolve/loader_hooks_test.go @@ -290,9 +290,9 @@ func TestLoaderHooks_FetchPipeline(t *testing.T) { assert.Equal(t, 0, subgraphError.ResponseCode) assert.Len(t, subgraphError.DownstreamErrors, 2) assert.Equal(t, "errorMessage", subgraphError.DownstreamErrors[0].Message) - assert.Empty(t, subgraphError.DownstreamErrors[0].Extensions["code"]) + assert.Nil(t, subgraphError.DownstreamErrors[0].Extensions.Get("code")) assert.Equal(t, "errorMessage2", subgraphError.DownstreamErrors[1].Message) - assert.Empty(t, subgraphError.DownstreamErrors[1].Extensions["code"]) + assert.Nil(t, subgraphError.DownstreamErrors[1].Extensions.Get("code")) assert.NotNil(t, resolveCtx.SubgraphErrors()) } @@ -1058,4 +1058,83 @@ func TestLoaderHooks_FetchPipeline(t *testing.T) { } })) + t.Run("fetch with subgraph error propagates only allowed extension fields to downstream errors in hooks", + testFnWithPostEvaluationAndOptions(ResolverOptions{ + MaxConcurrency: 1024, + PropagateSubgraphErrors: true, + PropagateSubgraphStatusCodes: true, + AllowedErrorExtensionFields: []string{"code", "serviceName"}, + SubgraphErrorPropagationMode: SubgraphErrorPropagationModePassThrough, + }, func(t *testing.T, ctrl *gomock.Controller) (node *GraphQLResponse, ctx *Context, expectedOutput string, postEvaluation func(t *testing.T)) { + mockDataSource := NewMockDataSource(ctrl) + mockDataSource.EXPECT(). + Load(gomock.Any(), gomock.Any(), gomock.Any()). + DoAndReturn(func(ctx context.Context, headers http.Header, input []byte) ([]byte, error) { + return []byte(`{"errors":[{"message":"errorMessage","extensions":{"code":"GRAPHQL_VALIDATION_FAILED","serviceName":"products","internalTrace":"abc123","sensitiveField":"secret"}},{"message":"errorMessage2","extensions":{"code":"BAD_USER_INPUT","serviceName":"users","internalTrace":"def456"}}]}`), nil + }) + resolveCtx := NewContext(context.Background()) + resolveCtx.LoaderHooks = NewTestLoaderHooks() + return &GraphQLResponse{ + Info: &GraphQLResponseInfo{ + OperationType: ast.OperationTypeQuery, + }, + Fetches: SingleWithPath(&SingleFetch{ + FetchConfiguration: FetchConfiguration{ + DataSource: mockDataSource, + PostProcessing: PostProcessingConfiguration{ + SelectResponseErrorsPath: []string{"errors"}, + }, + }, + Info: &FetchInfo{ + DataSourceID: "Products", + DataSourceName: "Products", + }, + }, "query"), + Data: &Object{ + Nullable: false, + Fields: []*Field{ + { + Name: []byte("name"), + Value: &String{ + Path: []string{"name"}, + Nullable: true, + }, + }, + }, + }, + }, resolveCtx, `{"errors":[{"message":"errorMessage","extensions":{"code":"GRAPHQL_VALIDATION_FAILED","serviceName":"products"}},{"message":"errorMessage2","extensions":{"code":"BAD_USER_INPUT","serviceName":"users"}}],"data":{"name":null}}`, + func(t *testing.T) { + loaderHooks := resolveCtx.LoaderHooks.(*TestLoaderHooks) + + assert.Equal(t, int64(1), loaderHooks.preFetchCalls.Load()) + assert.Equal(t, int64(1), loaderHooks.postFetchCalls.Load()) + + var subgraphError *SubgraphError + assert.Len(t, loaderHooks.errors, 1) + assert.ErrorAs(t, loaderHooks.errors[0], &subgraphError) + assert.Equal(t, "Products", subgraphError.DataSourceInfo.Name) + assert.Equal(t, "query", subgraphError.Path) + assert.Len(t, subgraphError.DownstreamErrors, 2) + + // First error: allowed fields "code" and "serviceName" are present, + // non-allowed fields "internalTrace" and "sensitiveField" are absent. + assert.Equal(t, "errorMessage", subgraphError.DownstreamErrors[0].Message) + assert.NotNil(t, subgraphError.DownstreamErrors[0].Extensions) + assert.Equal(t, `"GRAPHQL_VALIDATION_FAILED"`, subgraphError.DownstreamErrors[0].Extensions.Get("code").String()) + assert.Equal(t, `"products"`, subgraphError.DownstreamErrors[0].Extensions.Get("serviceName").String()) + assert.Nil(t, subgraphError.DownstreamErrors[0].Extensions.Get("internalTrace")) + assert.Nil(t, subgraphError.DownstreamErrors[0].Extensions.Get("sensitiveField")) + + // Second error: allowed fields "code" and "serviceName" are present, + // non-allowed field "internalTrace" is absent. + assert.Equal(t, "errorMessage2", subgraphError.DownstreamErrors[1].Message) + assert.NotNil(t, subgraphError.DownstreamErrors[1].Extensions) + assert.Equal(t, `"BAD_USER_INPUT"`, subgraphError.DownstreamErrors[1].Extensions.Get("code").String()) + assert.Equal(t, `"users"`, subgraphError.DownstreamErrors[1].Extensions.Get("serviceName").String()) + assert.Nil(t, subgraphError.DownstreamErrors[1].Extensions.Get("internalTrace")) + + assert.NotNil(t, resolveCtx.SubgraphErrors()) + } + })) + } diff --git a/v2/pkg/engine/resolve/resolve_test.go b/v2/pkg/engine/resolve/resolve_test.go index 56619c9035..82a8e1e635 100644 --- a/v2/pkg/engine/resolve/resolve_test.go +++ b/v2/pkg/engine/resolve/resolve_test.go @@ -1624,6 +1624,32 @@ func testFnSubgraphErrorsPassthroughAndOmitCustomFields(fn func(t *testing.T, ct } } +// testFnWithPostEvaluationAndOptions is like testFnWithPostEvaluation but allows +// configuring arbitrary ResolverOptions, enabling tests that need specific settings +// such as AllowedErrorExtensionFields. +func testFnWithPostEvaluationAndOptions(opts ResolverOptions, fn func(t *testing.T, ctrl *gomock.Controller) (node *GraphQLResponse, ctx *Context, expectedOutput string, postEvaluation func(t *testing.T))) func(t *testing.T) { + return func(t *testing.T) { + t.Helper() + + ctrl := gomock.NewController(t) + rCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + r := New(rCtx, opts) + node, ctx, expectedOutput, postEvaluation := fn(t, ctrl) + + if t.Skipped() { + return + } + + buf := &bytes.Buffer{} + _, err := r.ResolveGraphQLResponse(ctx, node, nil, buf) + assert.NoError(t, err) + assert.Equal(t, expectedOutput, buf.String()) + ctrl.Finish() + postEvaluation(t) + } +} + func TestResolver_ResolveGraphQLResponse(t *testing.T) { t.Run("empty graphql response", testFn(func(t *testing.T, ctrl *gomock.Controller) (node *GraphQLResponse, ctx Context, expectedOutput string) { diff --git a/v2/pkg/grpctest/mapping/mapping.go b/v2/pkg/grpctest/mapping/mapping.go index c3ff0f8425..c636ed69d8 100644 --- a/v2/pkg/grpctest/mapping/mapping.go +++ b/v2/pkg/grpctest/mapping/mapping.go @@ -56,6 +56,11 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { Request: "QueryCategoriesRequest", Response: "QueryCategoriesResponse", }, + "category": { + RPC: "QueryCategory", + Request: "QueryCategoryRequest", + Response: "QueryCategoryResponse", + }, "categoriesByKind": { RPC: "QueryCategoriesByKind", Request: "QueryCategoriesByKindRequest", @@ -327,6 +332,17 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { Request: "ResolveCategoryMetricsNormalizedScoreRequest", Response: "ResolveCategoryMetricsNormalizedScoreResponse", }, + "relatedCategory": { + FieldMappingData: grpcdatasource.FieldMapData{ + TargetName: "related_category", + ArgumentMappings: grpcdatasource.FieldArgumentMap{ + "include": "include", + }, + }, + RPC: "ResolveCategoryMetricsRelatedCategory", + Request: "ResolveCategoryMetricsRelatedCategoryRequest", + Response: "ResolveCategoryMetricsRelatedCategoryResponse", + }, }, "Product": { "shippingEstimate": { @@ -397,6 +413,17 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { Request: "ResolveSubcategoryItemCountRequest", Response: "ResolveSubcategoryItemCountResponse", }, + "featuredCategory": { + FieldMappingData: grpcdatasource.FieldMapData{ + TargetName: "featured_category", + ArgumentMappings: grpcdatasource.FieldArgumentMap{ + "includeChildren": "include_children", + }, + }, + RPC: "ResolveSubcategoryFeaturedCategory", + Request: "ResolveSubcategoryFeaturedCategoryRequest", + Response: "ResolveSubcategoryFeaturedCategoryResponse", + }, }, "TestContainer": { "details": { @@ -502,6 +529,12 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { "categories": { TargetName: "categories", }, + "category": { + TargetName: "category", + ArgumentMappings: grpcdatasource.FieldArgumentMap{ + "id": "id", + }, + }, "categoriesByKind": { TargetName: "categories_by_kind", ArgumentMappings: grpcdatasource.FieldArgumentMap{ @@ -981,6 +1014,9 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { "include": "include", }, }, + "nullMetrics": { + TargetName: "null_metrics", + }, }, "Subcategory": { "id": { @@ -1001,6 +1037,12 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { "filters": "filters", }, }, + "featuredCategory": { + TargetName: "featured_category", + ArgumentMappings: grpcdatasource.FieldArgumentMap{ + "includeChildren": "include_children", + }, + }, }, "CategoryMetrics": { "id": { @@ -1026,6 +1068,9 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { }, "relatedCategory": { TargetName: "related_category", + ArgumentMappings: grpcdatasource.FieldArgumentMap{ + "include": "include", + }, }, }, "Cat": { @@ -1078,6 +1123,9 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping { "contact": { TargetName: "contact", }, + "pet": { + TargetName: "pet", + }, }, "ContactInfo": { "email": { diff --git a/v2/pkg/grpctest/mockservice_enums.go b/v2/pkg/grpctest/mockservice_enums.go index 15e5900253..1eb6eb4d7a 100644 --- a/v2/pkg/grpctest/mockservice_enums.go +++ b/v2/pkg/grpctest/mockservice_enums.go @@ -36,6 +36,18 @@ func (s *MockService) QueryCategories(ctx context.Context, in *productv1.QueryCa }, nil } +// Implementation for QueryCategory +func (s *MockService) QueryCategory(ctx context.Context, in *productv1.QueryCategoryRequest) (*productv1.QueryCategoryResponse, error) { + id := in.GetId() + return &productv1.QueryCategoryResponse{ + Category: &productv1.Category{ + Id: id, + Name: fmt.Sprintf("Category %s", id), + Kind: productv1.CategoryKind_CATEGORY_KIND_BOOK, + }, + }, nil +} + // Implementation for QueryCategoriesByKind func (s *MockService) QueryCategoriesByKind(ctx context.Context, in *productv1.QueryCategoriesByKindRequest) (*productv1.QueryCategoriesByKindResponse, error) { kind := in.GetKind() diff --git a/v2/pkg/grpctest/mockservice_resolve.go b/v2/pkg/grpctest/mockservice_resolve.go index fea44506af..cda977d106 100644 --- a/v2/pkg/grpctest/mockservice_resolve.go +++ b/v2/pkg/grpctest/mockservice_resolve.go @@ -410,6 +410,34 @@ func (s *MockService) ResolveTestContainerDetails(_ context.Context, req *produc }, nil } +// ResolveCategoryMetricsRelatedCategory implements productv1.ProductServiceServer. +func (s *MockService) ResolveCategoryMetricsRelatedCategory(_ context.Context, req *productv1.ResolveCategoryMetricsRelatedCategoryRequest) (*productv1.ResolveCategoryMetricsRelatedCategoryResponse, error) { + results := make([]*productv1.ResolveCategoryMetricsRelatedCategoryResult, 0, len(req.GetContext())) + + include := true + if req.GetFieldArgs() != nil && req.GetFieldArgs().GetInclude() != nil { + include = req.GetFieldArgs().GetInclude().GetValue() + } + + for i, ctx := range req.GetContext() { + var relatedCategory *productv1.Category + if include { + relatedCategory = &productv1.Category{ + Id: fmt.Sprintf("related-category-%s-%d", ctx.GetCategoryId(), i), + Name: fmt.Sprintf("Related Category for %s", ctx.GetCategoryId()), + Kind: productv1.CategoryKind_CATEGORY_KIND_BOOK, + } + } + results = append(results, &productv1.ResolveCategoryMetricsRelatedCategoryResult{ + RelatedCategory: relatedCategory, + }) + } + + return &productv1.ResolveCategoryMetricsRelatedCategoryResponse{ + Result: results, + }, nil +} + // ResolveCategoryMetricsNormalizedScore implements productv1.ProductServiceServer. func (s *MockService) ResolveCategoryMetricsNormalizedScore(_ context.Context, req *productv1.ResolveCategoryMetricsNormalizedScoreRequest) (*productv1.ResolveCategoryMetricsNormalizedScoreResponse, error) { results := make([]*productv1.ResolveCategoryMetricsNormalizedScoreResult, 0, len(req.GetContext())) diff --git a/v2/pkg/grpctest/product.proto b/v2/pkg/grpctest/product.proto index f58706ffbe..70dca6f25e 100644 --- a/v2/pkg/grpctest/product.proto +++ b/v2/pkg/grpctest/product.proto @@ -41,6 +41,7 @@ service ProductService { rpc QueryCategories(QueryCategoriesRequest) returns (QueryCategoriesResponse) {} rpc QueryCategoriesByKind(QueryCategoriesByKindRequest) returns (QueryCategoriesByKindResponse) {} rpc QueryCategoriesByKinds(QueryCategoriesByKindsRequest) returns (QueryCategoriesByKindsResponse) {} + rpc QueryCategory(QueryCategoryRequest) returns (QueryCategoryResponse) {} rpc QueryComplexFilterType(QueryComplexFilterTypeRequest) returns (QueryComplexFilterTypeResponse) {} rpc QueryFilterCategories(QueryFilterCategoriesRequest) returns (QueryFilterCategoriesResponse) {} rpc QueryNestedType(QueryNestedTypeRequest) returns (QueryNestedTypeResponse) {} @@ -62,6 +63,7 @@ service ProductService { rpc ResolveCategoryChildCategories(ResolveCategoryChildCategoriesRequest) returns (ResolveCategoryChildCategoriesResponse) {} rpc ResolveCategoryMascot(ResolveCategoryMascotRequest) returns (ResolveCategoryMascotResponse) {} rpc ResolveCategoryMetricsNormalizedScore(ResolveCategoryMetricsNormalizedScoreRequest) returns (ResolveCategoryMetricsNormalizedScoreResponse) {} + rpc ResolveCategoryMetricsRelatedCategory(ResolveCategoryMetricsRelatedCategoryRequest) returns (ResolveCategoryMetricsRelatedCategoryResponse) {} rpc ResolveCategoryOptionalCategories(ResolveCategoryOptionalCategoriesRequest) returns (ResolveCategoryOptionalCategoriesResponse) {} rpc ResolveCategoryPopularityScore(ResolveCategoryPopularityScoreRequest) returns (ResolveCategoryPopularityScoreResponse) {} rpc ResolveCategoryProductCount(ResolveCategoryProductCountRequest) returns (ResolveCategoryProductCountResponse) {} @@ -70,6 +72,7 @@ service ProductService { rpc ResolveProductRecommendedCategory(ResolveProductRecommendedCategoryRequest) returns (ResolveProductRecommendedCategoryResponse) {} rpc ResolveProductShippingEstimate(ResolveProductShippingEstimateRequest) returns (ResolveProductShippingEstimateResponse) {} rpc ResolveProductStockStatus(ResolveProductStockStatusRequest) returns (ResolveProductStockStatusResponse) {} + rpc ResolveSubcategoryFeaturedCategory(ResolveSubcategoryFeaturedCategoryRequest) returns (ResolveSubcategoryFeaturedCategoryResponse) {} rpc ResolveSubcategoryItemCount(ResolveSubcategoryItemCountRequest) returns (ResolveSubcategoryItemCountResponse) {} rpc ResolveTestContainerDetails(ResolveTestContainerDetailsRequest) returns (ResolveTestContainerDetailsResponse) {} } @@ -385,6 +388,14 @@ message QueryCategoriesRequest { message QueryCategoriesResponse { repeated Category categories = 1; } +// Request message for category operation. +message QueryCategoryRequest { + string id = 1; +} +// Response message for category operation. +message QueryCategoryResponse { + Category category = 1; +} // Request message for categoriesByKind operation. message QueryCategoriesByKindRequest { CategoryKind kind = 1; @@ -971,6 +982,29 @@ message ResolveSubcategoryItemCountResponse { repeated ResolveSubcategoryItemCountResult result = 1; } +message ResolveSubcategoryFeaturedCategoryArgs { + bool include_children = 1; +} + +message ResolveSubcategoryFeaturedCategoryContext { + string id = 1; +} + +message ResolveSubcategoryFeaturedCategoryRequest { + // context provides the resolver context for the field featuredCategory of type Subcategory. + repeated ResolveSubcategoryFeaturedCategoryContext context = 1; + // field_args provides the arguments for the resolver field featuredCategory of type Subcategory. + ResolveSubcategoryFeaturedCategoryArgs field_args = 2; +} + +message ResolveSubcategoryFeaturedCategoryResult { + Category featured_category = 1; +} + +message ResolveSubcategoryFeaturedCategoryResponse { + repeated ResolveSubcategoryFeaturedCategoryResult result = 1; +} + message ResolveCategoryMetricsNormalizedScoreArgs { double baseline = 1; } @@ -996,6 +1030,29 @@ message ResolveCategoryMetricsNormalizedScoreResponse { repeated ResolveCategoryMetricsNormalizedScoreResult result = 1; } +message ResolveCategoryMetricsRelatedCategoryArgs { + google.protobuf.BoolValue include = 1; +} + +message ResolveCategoryMetricsRelatedCategoryContext { + string category_id = 1; +} + +message ResolveCategoryMetricsRelatedCategoryRequest { + // context provides the resolver context for the field relatedCategory of type CategoryMetrics. + repeated ResolveCategoryMetricsRelatedCategoryContext context = 1; + // field_args provides the arguments for the resolver field relatedCategory of type CategoryMetrics. + ResolveCategoryMetricsRelatedCategoryArgs field_args = 2; +} + +message ResolveCategoryMetricsRelatedCategoryResult { + Category related_category = 1; +} + +message ResolveCategoryMetricsRelatedCategoryResponse { + repeated ResolveCategoryMetricsRelatedCategoryResult result = 1; +} + message ResolveTestContainerDetailsArgs { bool include_extended = 1; } @@ -1093,7 +1150,8 @@ message Category { string id = 1; string name = 2; CategoryKind kind = 3; - ListOfSubcategory subcategories = 5; + ListOfSubcategory subcategories = 4; + CategoryMetrics null_metrics = 5; } message CategoryFilter { @@ -1310,7 +1368,6 @@ message CategoryMetrics { double value = 3; string timestamp = 4; string category_id = 5; - Category related_category = 6; } enum CategoryKind { @@ -1343,6 +1400,7 @@ message Owner { string id = 1; string name = 2; ContactInfo contact = 3; + Animal pet = 4; } message ContactInfo { diff --git a/v2/pkg/grpctest/productv1/product.pb.go b/v2/pkg/grpctest/productv1/product.pb.go index e0fe992662..928ff3aa88 100644 --- a/v2/pkg/grpctest/productv1/product.pb.go +++ b/v2/pkg/grpctest/productv1/product.pb.go @@ -2268,6 +2268,96 @@ func (x *QueryCategoriesResponse) GetCategories() []*Category { return nil } +// Request message for category operation. +type QueryCategoryRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryCategoryRequest) Reset() { + *x = QueryCategoryRequest{} + mi := &file_product_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryCategoryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryCategoryRequest) ProtoMessage() {} + +func (x *QueryCategoryRequest) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[47] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryCategoryRequest.ProtoReflect.Descriptor instead. +func (*QueryCategoryRequest) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{47} +} + +func (x *QueryCategoryRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +// Response message for category operation. +type QueryCategoryResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Category *Category `protobuf:"bytes,1,opt,name=category,proto3" json:"category,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryCategoryResponse) Reset() { + *x = QueryCategoryResponse{} + mi := &file_product_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryCategoryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryCategoryResponse) ProtoMessage() {} + +func (x *QueryCategoryResponse) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[48] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryCategoryResponse.ProtoReflect.Descriptor instead. +func (*QueryCategoryResponse) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{48} +} + +func (x *QueryCategoryResponse) GetCategory() *Category { + if x != nil { + return x.Category + } + return nil +} + // Request message for categoriesByKind operation. type QueryCategoriesByKindRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2278,7 +2368,7 @@ type QueryCategoriesByKindRequest struct { func (x *QueryCategoriesByKindRequest) Reset() { *x = QueryCategoriesByKindRequest{} - mi := &file_product_proto_msgTypes[47] + mi := &file_product_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2290,7 +2380,7 @@ func (x *QueryCategoriesByKindRequest) String() string { func (*QueryCategoriesByKindRequest) ProtoMessage() {} func (x *QueryCategoriesByKindRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[47] + mi := &file_product_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2303,7 +2393,7 @@ func (x *QueryCategoriesByKindRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryCategoriesByKindRequest.ProtoReflect.Descriptor instead. func (*QueryCategoriesByKindRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{47} + return file_product_proto_rawDescGZIP(), []int{49} } func (x *QueryCategoriesByKindRequest) GetKind() CategoryKind { @@ -2323,7 +2413,7 @@ type QueryCategoriesByKindResponse struct { func (x *QueryCategoriesByKindResponse) Reset() { *x = QueryCategoriesByKindResponse{} - mi := &file_product_proto_msgTypes[48] + mi := &file_product_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2335,7 +2425,7 @@ func (x *QueryCategoriesByKindResponse) String() string { func (*QueryCategoriesByKindResponse) ProtoMessage() {} func (x *QueryCategoriesByKindResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[48] + mi := &file_product_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2348,7 +2438,7 @@ func (x *QueryCategoriesByKindResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryCategoriesByKindResponse.ProtoReflect.Descriptor instead. func (*QueryCategoriesByKindResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{48} + return file_product_proto_rawDescGZIP(), []int{50} } func (x *QueryCategoriesByKindResponse) GetCategoriesByKind() []*Category { @@ -2368,7 +2458,7 @@ type QueryCategoriesByKindsRequest struct { func (x *QueryCategoriesByKindsRequest) Reset() { *x = QueryCategoriesByKindsRequest{} - mi := &file_product_proto_msgTypes[49] + mi := &file_product_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2380,7 +2470,7 @@ func (x *QueryCategoriesByKindsRequest) String() string { func (*QueryCategoriesByKindsRequest) ProtoMessage() {} func (x *QueryCategoriesByKindsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[49] + mi := &file_product_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2393,7 +2483,7 @@ func (x *QueryCategoriesByKindsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryCategoriesByKindsRequest.ProtoReflect.Descriptor instead. func (*QueryCategoriesByKindsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{49} + return file_product_proto_rawDescGZIP(), []int{51} } func (x *QueryCategoriesByKindsRequest) GetKinds() []CategoryKind { @@ -2413,7 +2503,7 @@ type QueryCategoriesByKindsResponse struct { func (x *QueryCategoriesByKindsResponse) Reset() { *x = QueryCategoriesByKindsResponse{} - mi := &file_product_proto_msgTypes[50] + mi := &file_product_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2425,7 +2515,7 @@ func (x *QueryCategoriesByKindsResponse) String() string { func (*QueryCategoriesByKindsResponse) ProtoMessage() {} func (x *QueryCategoriesByKindsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[50] + mi := &file_product_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2438,7 +2528,7 @@ func (x *QueryCategoriesByKindsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryCategoriesByKindsResponse.ProtoReflect.Descriptor instead. func (*QueryCategoriesByKindsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{50} + return file_product_proto_rawDescGZIP(), []int{52} } func (x *QueryCategoriesByKindsResponse) GetCategoriesByKinds() []*Category { @@ -2458,7 +2548,7 @@ type QueryFilterCategoriesRequest struct { func (x *QueryFilterCategoriesRequest) Reset() { *x = QueryFilterCategoriesRequest{} - mi := &file_product_proto_msgTypes[51] + mi := &file_product_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2470,7 +2560,7 @@ func (x *QueryFilterCategoriesRequest) String() string { func (*QueryFilterCategoriesRequest) ProtoMessage() {} func (x *QueryFilterCategoriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[51] + mi := &file_product_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2483,7 +2573,7 @@ func (x *QueryFilterCategoriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryFilterCategoriesRequest.ProtoReflect.Descriptor instead. func (*QueryFilterCategoriesRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{51} + return file_product_proto_rawDescGZIP(), []int{53} } func (x *QueryFilterCategoriesRequest) GetFilter() *CategoryFilter { @@ -2503,7 +2593,7 @@ type QueryFilterCategoriesResponse struct { func (x *QueryFilterCategoriesResponse) Reset() { *x = QueryFilterCategoriesResponse{} - mi := &file_product_proto_msgTypes[52] + mi := &file_product_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2515,7 +2605,7 @@ func (x *QueryFilterCategoriesResponse) String() string { func (*QueryFilterCategoriesResponse) ProtoMessage() {} func (x *QueryFilterCategoriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[52] + mi := &file_product_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2528,7 +2618,7 @@ func (x *QueryFilterCategoriesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryFilterCategoriesResponse.ProtoReflect.Descriptor instead. func (*QueryFilterCategoriesResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{52} + return file_product_proto_rawDescGZIP(), []int{54} } func (x *QueryFilterCategoriesResponse) GetFilterCategories() []*Category { @@ -2547,7 +2637,7 @@ type QueryRandomPetRequest struct { func (x *QueryRandomPetRequest) Reset() { *x = QueryRandomPetRequest{} - mi := &file_product_proto_msgTypes[53] + mi := &file_product_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2559,7 +2649,7 @@ func (x *QueryRandomPetRequest) String() string { func (*QueryRandomPetRequest) ProtoMessage() {} func (x *QueryRandomPetRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[53] + mi := &file_product_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2572,7 +2662,7 @@ func (x *QueryRandomPetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryRandomPetRequest.ProtoReflect.Descriptor instead. func (*QueryRandomPetRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{53} + return file_product_proto_rawDescGZIP(), []int{55} } // Response message for randomPet operation. @@ -2585,7 +2675,7 @@ type QueryRandomPetResponse struct { func (x *QueryRandomPetResponse) Reset() { *x = QueryRandomPetResponse{} - mi := &file_product_proto_msgTypes[54] + mi := &file_product_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2597,7 +2687,7 @@ func (x *QueryRandomPetResponse) String() string { func (*QueryRandomPetResponse) ProtoMessage() {} func (x *QueryRandomPetResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[54] + mi := &file_product_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2610,7 +2700,7 @@ func (x *QueryRandomPetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryRandomPetResponse.ProtoReflect.Descriptor instead. func (*QueryRandomPetResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{54} + return file_product_proto_rawDescGZIP(), []int{56} } func (x *QueryRandomPetResponse) GetRandomPet() *Animal { @@ -2629,7 +2719,7 @@ type QueryAllPetsRequest struct { func (x *QueryAllPetsRequest) Reset() { *x = QueryAllPetsRequest{} - mi := &file_product_proto_msgTypes[55] + mi := &file_product_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2641,7 +2731,7 @@ func (x *QueryAllPetsRequest) String() string { func (*QueryAllPetsRequest) ProtoMessage() {} func (x *QueryAllPetsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[55] + mi := &file_product_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2654,7 +2744,7 @@ func (x *QueryAllPetsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAllPetsRequest.ProtoReflect.Descriptor instead. func (*QueryAllPetsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{55} + return file_product_proto_rawDescGZIP(), []int{57} } // Response message for allPets operation. @@ -2667,7 +2757,7 @@ type QueryAllPetsResponse struct { func (x *QueryAllPetsResponse) Reset() { *x = QueryAllPetsResponse{} - mi := &file_product_proto_msgTypes[56] + mi := &file_product_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2679,7 +2769,7 @@ func (x *QueryAllPetsResponse) String() string { func (*QueryAllPetsResponse) ProtoMessage() {} func (x *QueryAllPetsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[56] + mi := &file_product_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2692,7 +2782,7 @@ func (x *QueryAllPetsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAllPetsResponse.ProtoReflect.Descriptor instead. func (*QueryAllPetsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{56} + return file_product_proto_rawDescGZIP(), []int{58} } func (x *QueryAllPetsResponse) GetAllPets() []*Animal { @@ -2712,7 +2802,7 @@ type QuerySearchRequest struct { func (x *QuerySearchRequest) Reset() { *x = QuerySearchRequest{} - mi := &file_product_proto_msgTypes[57] + mi := &file_product_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2724,7 +2814,7 @@ func (x *QuerySearchRequest) String() string { func (*QuerySearchRequest) ProtoMessage() {} func (x *QuerySearchRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[57] + mi := &file_product_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2737,7 +2827,7 @@ func (x *QuerySearchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QuerySearchRequest.ProtoReflect.Descriptor instead. func (*QuerySearchRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{57} + return file_product_proto_rawDescGZIP(), []int{59} } func (x *QuerySearchRequest) GetInput() *SearchInput { @@ -2757,7 +2847,7 @@ type QuerySearchResponse struct { func (x *QuerySearchResponse) Reset() { *x = QuerySearchResponse{} - mi := &file_product_proto_msgTypes[58] + mi := &file_product_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2769,7 +2859,7 @@ func (x *QuerySearchResponse) String() string { func (*QuerySearchResponse) ProtoMessage() {} func (x *QuerySearchResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[58] + mi := &file_product_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2782,7 +2872,7 @@ func (x *QuerySearchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QuerySearchResponse.ProtoReflect.Descriptor instead. func (*QuerySearchResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{58} + return file_product_proto_rawDescGZIP(), []int{60} } func (x *QuerySearchResponse) GetSearch() []*SearchResult { @@ -2801,7 +2891,7 @@ type QueryRandomSearchResultRequest struct { func (x *QueryRandomSearchResultRequest) Reset() { *x = QueryRandomSearchResultRequest{} - mi := &file_product_proto_msgTypes[59] + mi := &file_product_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2813,7 +2903,7 @@ func (x *QueryRandomSearchResultRequest) String() string { func (*QueryRandomSearchResultRequest) ProtoMessage() {} func (x *QueryRandomSearchResultRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[59] + mi := &file_product_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2826,7 +2916,7 @@ func (x *QueryRandomSearchResultRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryRandomSearchResultRequest.ProtoReflect.Descriptor instead. func (*QueryRandomSearchResultRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{59} + return file_product_proto_rawDescGZIP(), []int{61} } // Response message for randomSearchResult operation. @@ -2839,7 +2929,7 @@ type QueryRandomSearchResultResponse struct { func (x *QueryRandomSearchResultResponse) Reset() { *x = QueryRandomSearchResultResponse{} - mi := &file_product_proto_msgTypes[60] + mi := &file_product_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2851,7 +2941,7 @@ func (x *QueryRandomSearchResultResponse) String() string { func (*QueryRandomSearchResultResponse) ProtoMessage() {} func (x *QueryRandomSearchResultResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[60] + mi := &file_product_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2864,7 +2954,7 @@ func (x *QueryRandomSearchResultResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryRandomSearchResultResponse.ProtoReflect.Descriptor instead. func (*QueryRandomSearchResultResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{60} + return file_product_proto_rawDescGZIP(), []int{62} } func (x *QueryRandomSearchResultResponse) GetRandomSearchResult() *SearchResult { @@ -2883,7 +2973,7 @@ type QueryNullableFieldsTypeRequest struct { func (x *QueryNullableFieldsTypeRequest) Reset() { *x = QueryNullableFieldsTypeRequest{} - mi := &file_product_proto_msgTypes[61] + mi := &file_product_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2895,7 +2985,7 @@ func (x *QueryNullableFieldsTypeRequest) String() string { func (*QueryNullableFieldsTypeRequest) ProtoMessage() {} func (x *QueryNullableFieldsTypeRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[61] + mi := &file_product_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2908,7 +2998,7 @@ func (x *QueryNullableFieldsTypeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryNullableFieldsTypeRequest.ProtoReflect.Descriptor instead. func (*QueryNullableFieldsTypeRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{61} + return file_product_proto_rawDescGZIP(), []int{63} } // Response message for nullableFieldsType operation. @@ -2921,7 +3011,7 @@ type QueryNullableFieldsTypeResponse struct { func (x *QueryNullableFieldsTypeResponse) Reset() { *x = QueryNullableFieldsTypeResponse{} - mi := &file_product_proto_msgTypes[62] + mi := &file_product_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2933,7 +3023,7 @@ func (x *QueryNullableFieldsTypeResponse) String() string { func (*QueryNullableFieldsTypeResponse) ProtoMessage() {} func (x *QueryNullableFieldsTypeResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[62] + mi := &file_product_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2946,7 +3036,7 @@ func (x *QueryNullableFieldsTypeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryNullableFieldsTypeResponse.ProtoReflect.Descriptor instead. func (*QueryNullableFieldsTypeResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{62} + return file_product_proto_rawDescGZIP(), []int{64} } func (x *QueryNullableFieldsTypeResponse) GetNullableFieldsType() *NullableFieldsType { @@ -2966,7 +3056,7 @@ type QueryNullableFieldsTypeByIdRequest struct { func (x *QueryNullableFieldsTypeByIdRequest) Reset() { *x = QueryNullableFieldsTypeByIdRequest{} - mi := &file_product_proto_msgTypes[63] + mi := &file_product_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2978,7 +3068,7 @@ func (x *QueryNullableFieldsTypeByIdRequest) String() string { func (*QueryNullableFieldsTypeByIdRequest) ProtoMessage() {} func (x *QueryNullableFieldsTypeByIdRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[63] + mi := &file_product_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2991,7 +3081,7 @@ func (x *QueryNullableFieldsTypeByIdRequest) ProtoReflect() protoreflect.Message // Deprecated: Use QueryNullableFieldsTypeByIdRequest.ProtoReflect.Descriptor instead. func (*QueryNullableFieldsTypeByIdRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{63} + return file_product_proto_rawDescGZIP(), []int{65} } func (x *QueryNullableFieldsTypeByIdRequest) GetId() string { @@ -3011,7 +3101,7 @@ type QueryNullableFieldsTypeByIdResponse struct { func (x *QueryNullableFieldsTypeByIdResponse) Reset() { *x = QueryNullableFieldsTypeByIdResponse{} - mi := &file_product_proto_msgTypes[64] + mi := &file_product_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3023,7 +3113,7 @@ func (x *QueryNullableFieldsTypeByIdResponse) String() string { func (*QueryNullableFieldsTypeByIdResponse) ProtoMessage() {} func (x *QueryNullableFieldsTypeByIdResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[64] + mi := &file_product_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3036,7 +3126,7 @@ func (x *QueryNullableFieldsTypeByIdResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use QueryNullableFieldsTypeByIdResponse.ProtoReflect.Descriptor instead. func (*QueryNullableFieldsTypeByIdResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{64} + return file_product_proto_rawDescGZIP(), []int{66} } func (x *QueryNullableFieldsTypeByIdResponse) GetNullableFieldsTypeById() *NullableFieldsType { @@ -3056,7 +3146,7 @@ type QueryNullableFieldsTypeWithFilterRequest struct { func (x *QueryNullableFieldsTypeWithFilterRequest) Reset() { *x = QueryNullableFieldsTypeWithFilterRequest{} - mi := &file_product_proto_msgTypes[65] + mi := &file_product_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3068,7 +3158,7 @@ func (x *QueryNullableFieldsTypeWithFilterRequest) String() string { func (*QueryNullableFieldsTypeWithFilterRequest) ProtoMessage() {} func (x *QueryNullableFieldsTypeWithFilterRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[65] + mi := &file_product_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3081,7 +3171,7 @@ func (x *QueryNullableFieldsTypeWithFilterRequest) ProtoReflect() protoreflect.M // Deprecated: Use QueryNullableFieldsTypeWithFilterRequest.ProtoReflect.Descriptor instead. func (*QueryNullableFieldsTypeWithFilterRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{65} + return file_product_proto_rawDescGZIP(), []int{67} } func (x *QueryNullableFieldsTypeWithFilterRequest) GetFilter() *NullableFieldsFilter { @@ -3101,7 +3191,7 @@ type QueryNullableFieldsTypeWithFilterResponse struct { func (x *QueryNullableFieldsTypeWithFilterResponse) Reset() { *x = QueryNullableFieldsTypeWithFilterResponse{} - mi := &file_product_proto_msgTypes[66] + mi := &file_product_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3113,7 +3203,7 @@ func (x *QueryNullableFieldsTypeWithFilterResponse) String() string { func (*QueryNullableFieldsTypeWithFilterResponse) ProtoMessage() {} func (x *QueryNullableFieldsTypeWithFilterResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[66] + mi := &file_product_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3126,7 +3216,7 @@ func (x *QueryNullableFieldsTypeWithFilterResponse) ProtoReflect() protoreflect. // Deprecated: Use QueryNullableFieldsTypeWithFilterResponse.ProtoReflect.Descriptor instead. func (*QueryNullableFieldsTypeWithFilterResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{66} + return file_product_proto_rawDescGZIP(), []int{68} } func (x *QueryNullableFieldsTypeWithFilterResponse) GetNullableFieldsTypeWithFilter() []*NullableFieldsType { @@ -3145,7 +3235,7 @@ type QueryAllNullableFieldsTypesRequest struct { func (x *QueryAllNullableFieldsTypesRequest) Reset() { *x = QueryAllNullableFieldsTypesRequest{} - mi := &file_product_proto_msgTypes[67] + mi := &file_product_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3157,7 +3247,7 @@ func (x *QueryAllNullableFieldsTypesRequest) String() string { func (*QueryAllNullableFieldsTypesRequest) ProtoMessage() {} func (x *QueryAllNullableFieldsTypesRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[67] + mi := &file_product_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3170,7 +3260,7 @@ func (x *QueryAllNullableFieldsTypesRequest) ProtoReflect() protoreflect.Message // Deprecated: Use QueryAllNullableFieldsTypesRequest.ProtoReflect.Descriptor instead. func (*QueryAllNullableFieldsTypesRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{67} + return file_product_proto_rawDescGZIP(), []int{69} } // Response message for allNullableFieldsTypes operation. @@ -3183,7 +3273,7 @@ type QueryAllNullableFieldsTypesResponse struct { func (x *QueryAllNullableFieldsTypesResponse) Reset() { *x = QueryAllNullableFieldsTypesResponse{} - mi := &file_product_proto_msgTypes[68] + mi := &file_product_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3195,7 +3285,7 @@ func (x *QueryAllNullableFieldsTypesResponse) String() string { func (*QueryAllNullableFieldsTypesResponse) ProtoMessage() {} func (x *QueryAllNullableFieldsTypesResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[68] + mi := &file_product_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3208,7 +3298,7 @@ func (x *QueryAllNullableFieldsTypesResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use QueryAllNullableFieldsTypesResponse.ProtoReflect.Descriptor instead. func (*QueryAllNullableFieldsTypesResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{68} + return file_product_proto_rawDescGZIP(), []int{70} } func (x *QueryAllNullableFieldsTypesResponse) GetAllNullableFieldsTypes() []*NullableFieldsType { @@ -3227,7 +3317,7 @@ type QueryBlogPostRequest struct { func (x *QueryBlogPostRequest) Reset() { *x = QueryBlogPostRequest{} - mi := &file_product_proto_msgTypes[69] + mi := &file_product_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3239,7 +3329,7 @@ func (x *QueryBlogPostRequest) String() string { func (*QueryBlogPostRequest) ProtoMessage() {} func (x *QueryBlogPostRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[69] + mi := &file_product_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3252,7 +3342,7 @@ func (x *QueryBlogPostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBlogPostRequest.ProtoReflect.Descriptor instead. func (*QueryBlogPostRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{69} + return file_product_proto_rawDescGZIP(), []int{71} } // Response message for blogPost operation. @@ -3265,7 +3355,7 @@ type QueryBlogPostResponse struct { func (x *QueryBlogPostResponse) Reset() { *x = QueryBlogPostResponse{} - mi := &file_product_proto_msgTypes[70] + mi := &file_product_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3277,7 +3367,7 @@ func (x *QueryBlogPostResponse) String() string { func (*QueryBlogPostResponse) ProtoMessage() {} func (x *QueryBlogPostResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[70] + mi := &file_product_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3290,7 +3380,7 @@ func (x *QueryBlogPostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBlogPostResponse.ProtoReflect.Descriptor instead. func (*QueryBlogPostResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{70} + return file_product_proto_rawDescGZIP(), []int{72} } func (x *QueryBlogPostResponse) GetBlogPost() *BlogPost { @@ -3310,7 +3400,7 @@ type QueryBlogPostByIdRequest struct { func (x *QueryBlogPostByIdRequest) Reset() { *x = QueryBlogPostByIdRequest{} - mi := &file_product_proto_msgTypes[71] + mi := &file_product_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3322,7 +3412,7 @@ func (x *QueryBlogPostByIdRequest) String() string { func (*QueryBlogPostByIdRequest) ProtoMessage() {} func (x *QueryBlogPostByIdRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[71] + mi := &file_product_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3335,7 +3425,7 @@ func (x *QueryBlogPostByIdRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBlogPostByIdRequest.ProtoReflect.Descriptor instead. func (*QueryBlogPostByIdRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{71} + return file_product_proto_rawDescGZIP(), []int{73} } func (x *QueryBlogPostByIdRequest) GetId() string { @@ -3355,7 +3445,7 @@ type QueryBlogPostByIdResponse struct { func (x *QueryBlogPostByIdResponse) Reset() { *x = QueryBlogPostByIdResponse{} - mi := &file_product_proto_msgTypes[72] + mi := &file_product_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3367,7 +3457,7 @@ func (x *QueryBlogPostByIdResponse) String() string { func (*QueryBlogPostByIdResponse) ProtoMessage() {} func (x *QueryBlogPostByIdResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[72] + mi := &file_product_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3380,7 +3470,7 @@ func (x *QueryBlogPostByIdResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBlogPostByIdResponse.ProtoReflect.Descriptor instead. func (*QueryBlogPostByIdResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{72} + return file_product_proto_rawDescGZIP(), []int{74} } func (x *QueryBlogPostByIdResponse) GetBlogPostById() *BlogPost { @@ -3400,7 +3490,7 @@ type QueryBlogPostsWithFilterRequest struct { func (x *QueryBlogPostsWithFilterRequest) Reset() { *x = QueryBlogPostsWithFilterRequest{} - mi := &file_product_proto_msgTypes[73] + mi := &file_product_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3412,7 +3502,7 @@ func (x *QueryBlogPostsWithFilterRequest) String() string { func (*QueryBlogPostsWithFilterRequest) ProtoMessage() {} func (x *QueryBlogPostsWithFilterRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[73] + mi := &file_product_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3425,7 +3515,7 @@ func (x *QueryBlogPostsWithFilterRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBlogPostsWithFilterRequest.ProtoReflect.Descriptor instead. func (*QueryBlogPostsWithFilterRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{73} + return file_product_proto_rawDescGZIP(), []int{75} } func (x *QueryBlogPostsWithFilterRequest) GetFilter() *BlogPostFilter { @@ -3445,7 +3535,7 @@ type QueryBlogPostsWithFilterResponse struct { func (x *QueryBlogPostsWithFilterResponse) Reset() { *x = QueryBlogPostsWithFilterResponse{} - mi := &file_product_proto_msgTypes[74] + mi := &file_product_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3457,7 +3547,7 @@ func (x *QueryBlogPostsWithFilterResponse) String() string { func (*QueryBlogPostsWithFilterResponse) ProtoMessage() {} func (x *QueryBlogPostsWithFilterResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[74] + mi := &file_product_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3470,7 +3560,7 @@ func (x *QueryBlogPostsWithFilterResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBlogPostsWithFilterResponse.ProtoReflect.Descriptor instead. func (*QueryBlogPostsWithFilterResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{74} + return file_product_proto_rawDescGZIP(), []int{76} } func (x *QueryBlogPostsWithFilterResponse) GetBlogPostsWithFilter() []*BlogPost { @@ -3489,7 +3579,7 @@ type QueryAllBlogPostsRequest struct { func (x *QueryAllBlogPostsRequest) Reset() { *x = QueryAllBlogPostsRequest{} - mi := &file_product_proto_msgTypes[75] + mi := &file_product_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3501,7 +3591,7 @@ func (x *QueryAllBlogPostsRequest) String() string { func (*QueryAllBlogPostsRequest) ProtoMessage() {} func (x *QueryAllBlogPostsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[75] + mi := &file_product_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3514,7 +3604,7 @@ func (x *QueryAllBlogPostsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAllBlogPostsRequest.ProtoReflect.Descriptor instead. func (*QueryAllBlogPostsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{75} + return file_product_proto_rawDescGZIP(), []int{77} } // Response message for allBlogPosts operation. @@ -3527,7 +3617,7 @@ type QueryAllBlogPostsResponse struct { func (x *QueryAllBlogPostsResponse) Reset() { *x = QueryAllBlogPostsResponse{} - mi := &file_product_proto_msgTypes[76] + mi := &file_product_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3539,7 +3629,7 @@ func (x *QueryAllBlogPostsResponse) String() string { func (*QueryAllBlogPostsResponse) ProtoMessage() {} func (x *QueryAllBlogPostsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[76] + mi := &file_product_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3552,7 +3642,7 @@ func (x *QueryAllBlogPostsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAllBlogPostsResponse.ProtoReflect.Descriptor instead. func (*QueryAllBlogPostsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{76} + return file_product_proto_rawDescGZIP(), []int{78} } func (x *QueryAllBlogPostsResponse) GetAllBlogPosts() []*BlogPost { @@ -3571,7 +3661,7 @@ type QueryAuthorRequest struct { func (x *QueryAuthorRequest) Reset() { *x = QueryAuthorRequest{} - mi := &file_product_proto_msgTypes[77] + mi := &file_product_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3583,7 +3673,7 @@ func (x *QueryAuthorRequest) String() string { func (*QueryAuthorRequest) ProtoMessage() {} func (x *QueryAuthorRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[77] + mi := &file_product_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3596,7 +3686,7 @@ func (x *QueryAuthorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAuthorRequest.ProtoReflect.Descriptor instead. func (*QueryAuthorRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{77} + return file_product_proto_rawDescGZIP(), []int{79} } // Response message for author operation. @@ -3609,7 +3699,7 @@ type QueryAuthorResponse struct { func (x *QueryAuthorResponse) Reset() { *x = QueryAuthorResponse{} - mi := &file_product_proto_msgTypes[78] + mi := &file_product_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3621,7 +3711,7 @@ func (x *QueryAuthorResponse) String() string { func (*QueryAuthorResponse) ProtoMessage() {} func (x *QueryAuthorResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[78] + mi := &file_product_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3634,7 +3724,7 @@ func (x *QueryAuthorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAuthorResponse.ProtoReflect.Descriptor instead. func (*QueryAuthorResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{78} + return file_product_proto_rawDescGZIP(), []int{80} } func (x *QueryAuthorResponse) GetAuthor() *Author { @@ -3654,7 +3744,7 @@ type QueryAuthorByIdRequest struct { func (x *QueryAuthorByIdRequest) Reset() { *x = QueryAuthorByIdRequest{} - mi := &file_product_proto_msgTypes[79] + mi := &file_product_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3666,7 +3756,7 @@ func (x *QueryAuthorByIdRequest) String() string { func (*QueryAuthorByIdRequest) ProtoMessage() {} func (x *QueryAuthorByIdRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[79] + mi := &file_product_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3679,7 +3769,7 @@ func (x *QueryAuthorByIdRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAuthorByIdRequest.ProtoReflect.Descriptor instead. func (*QueryAuthorByIdRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{79} + return file_product_proto_rawDescGZIP(), []int{81} } func (x *QueryAuthorByIdRequest) GetId() string { @@ -3699,7 +3789,7 @@ type QueryAuthorByIdResponse struct { func (x *QueryAuthorByIdResponse) Reset() { *x = QueryAuthorByIdResponse{} - mi := &file_product_proto_msgTypes[80] + mi := &file_product_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3711,7 +3801,7 @@ func (x *QueryAuthorByIdResponse) String() string { func (*QueryAuthorByIdResponse) ProtoMessage() {} func (x *QueryAuthorByIdResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[80] + mi := &file_product_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3724,7 +3814,7 @@ func (x *QueryAuthorByIdResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAuthorByIdResponse.ProtoReflect.Descriptor instead. func (*QueryAuthorByIdResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{80} + return file_product_proto_rawDescGZIP(), []int{82} } func (x *QueryAuthorByIdResponse) GetAuthorById() *Author { @@ -3744,7 +3834,7 @@ type QueryAuthorsWithFilterRequest struct { func (x *QueryAuthorsWithFilterRequest) Reset() { *x = QueryAuthorsWithFilterRequest{} - mi := &file_product_proto_msgTypes[81] + mi := &file_product_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3756,7 +3846,7 @@ func (x *QueryAuthorsWithFilterRequest) String() string { func (*QueryAuthorsWithFilterRequest) ProtoMessage() {} func (x *QueryAuthorsWithFilterRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[81] + mi := &file_product_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3769,7 +3859,7 @@ func (x *QueryAuthorsWithFilterRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAuthorsWithFilterRequest.ProtoReflect.Descriptor instead. func (*QueryAuthorsWithFilterRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{81} + return file_product_proto_rawDescGZIP(), []int{83} } func (x *QueryAuthorsWithFilterRequest) GetFilter() *AuthorFilter { @@ -3789,7 +3879,7 @@ type QueryAuthorsWithFilterResponse struct { func (x *QueryAuthorsWithFilterResponse) Reset() { *x = QueryAuthorsWithFilterResponse{} - mi := &file_product_proto_msgTypes[82] + mi := &file_product_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3801,7 +3891,7 @@ func (x *QueryAuthorsWithFilterResponse) String() string { func (*QueryAuthorsWithFilterResponse) ProtoMessage() {} func (x *QueryAuthorsWithFilterResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[82] + mi := &file_product_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3814,7 +3904,7 @@ func (x *QueryAuthorsWithFilterResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAuthorsWithFilterResponse.ProtoReflect.Descriptor instead. func (*QueryAuthorsWithFilterResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{82} + return file_product_proto_rawDescGZIP(), []int{84} } func (x *QueryAuthorsWithFilterResponse) GetAuthorsWithFilter() []*Author { @@ -3833,7 +3923,7 @@ type QueryAllAuthorsRequest struct { func (x *QueryAllAuthorsRequest) Reset() { *x = QueryAllAuthorsRequest{} - mi := &file_product_proto_msgTypes[83] + mi := &file_product_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3845,7 +3935,7 @@ func (x *QueryAllAuthorsRequest) String() string { func (*QueryAllAuthorsRequest) ProtoMessage() {} func (x *QueryAllAuthorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[83] + mi := &file_product_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3858,7 +3948,7 @@ func (x *QueryAllAuthorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAllAuthorsRequest.ProtoReflect.Descriptor instead. func (*QueryAllAuthorsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{83} + return file_product_proto_rawDescGZIP(), []int{85} } // Response message for allAuthors operation. @@ -3871,7 +3961,7 @@ type QueryAllAuthorsResponse struct { func (x *QueryAllAuthorsResponse) Reset() { *x = QueryAllAuthorsResponse{} - mi := &file_product_proto_msgTypes[84] + mi := &file_product_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3883,7 +3973,7 @@ func (x *QueryAllAuthorsResponse) String() string { func (*QueryAllAuthorsResponse) ProtoMessage() {} func (x *QueryAllAuthorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[84] + mi := &file_product_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3896,7 +3986,7 @@ func (x *QueryAllAuthorsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryAllAuthorsResponse.ProtoReflect.Descriptor instead. func (*QueryAllAuthorsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{84} + return file_product_proto_rawDescGZIP(), []int{86} } func (x *QueryAllAuthorsResponse) GetAllAuthors() []*Author { @@ -3916,7 +4006,7 @@ type QueryBulkSearchAuthorsRequest struct { func (x *QueryBulkSearchAuthorsRequest) Reset() { *x = QueryBulkSearchAuthorsRequest{} - mi := &file_product_proto_msgTypes[85] + mi := &file_product_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3928,7 +4018,7 @@ func (x *QueryBulkSearchAuthorsRequest) String() string { func (*QueryBulkSearchAuthorsRequest) ProtoMessage() {} func (x *QueryBulkSearchAuthorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[85] + mi := &file_product_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3941,7 +4031,7 @@ func (x *QueryBulkSearchAuthorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBulkSearchAuthorsRequest.ProtoReflect.Descriptor instead. func (*QueryBulkSearchAuthorsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{85} + return file_product_proto_rawDescGZIP(), []int{87} } func (x *QueryBulkSearchAuthorsRequest) GetFilters() *ListOfAuthorFilter { @@ -3961,7 +4051,7 @@ type QueryBulkSearchAuthorsResponse struct { func (x *QueryBulkSearchAuthorsResponse) Reset() { *x = QueryBulkSearchAuthorsResponse{} - mi := &file_product_proto_msgTypes[86] + mi := &file_product_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3973,7 +4063,7 @@ func (x *QueryBulkSearchAuthorsResponse) String() string { func (*QueryBulkSearchAuthorsResponse) ProtoMessage() {} func (x *QueryBulkSearchAuthorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[86] + mi := &file_product_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3986,7 +4076,7 @@ func (x *QueryBulkSearchAuthorsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBulkSearchAuthorsResponse.ProtoReflect.Descriptor instead. func (*QueryBulkSearchAuthorsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{86} + return file_product_proto_rawDescGZIP(), []int{88} } func (x *QueryBulkSearchAuthorsResponse) GetBulkSearchAuthors() []*Author { @@ -4006,7 +4096,7 @@ type QueryBulkSearchBlogPostsRequest struct { func (x *QueryBulkSearchBlogPostsRequest) Reset() { *x = QueryBulkSearchBlogPostsRequest{} - mi := &file_product_proto_msgTypes[87] + mi := &file_product_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4018,7 +4108,7 @@ func (x *QueryBulkSearchBlogPostsRequest) String() string { func (*QueryBulkSearchBlogPostsRequest) ProtoMessage() {} func (x *QueryBulkSearchBlogPostsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[87] + mi := &file_product_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4031,7 +4121,7 @@ func (x *QueryBulkSearchBlogPostsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBulkSearchBlogPostsRequest.ProtoReflect.Descriptor instead. func (*QueryBulkSearchBlogPostsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{87} + return file_product_proto_rawDescGZIP(), []int{89} } func (x *QueryBulkSearchBlogPostsRequest) GetFilters() *ListOfBlogPostFilter { @@ -4051,7 +4141,7 @@ type QueryBulkSearchBlogPostsResponse struct { func (x *QueryBulkSearchBlogPostsResponse) Reset() { *x = QueryBulkSearchBlogPostsResponse{} - mi := &file_product_proto_msgTypes[88] + mi := &file_product_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4063,7 +4153,7 @@ func (x *QueryBulkSearchBlogPostsResponse) String() string { func (*QueryBulkSearchBlogPostsResponse) ProtoMessage() {} func (x *QueryBulkSearchBlogPostsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[88] + mi := &file_product_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4076,7 +4166,7 @@ func (x *QueryBulkSearchBlogPostsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryBulkSearchBlogPostsResponse.ProtoReflect.Descriptor instead. func (*QueryBulkSearchBlogPostsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{88} + return file_product_proto_rawDescGZIP(), []int{90} } func (x *QueryBulkSearchBlogPostsResponse) GetBulkSearchBlogPosts() []*BlogPost { @@ -4096,7 +4186,7 @@ type QueryTestContainerRequest struct { func (x *QueryTestContainerRequest) Reset() { *x = QueryTestContainerRequest{} - mi := &file_product_proto_msgTypes[89] + mi := &file_product_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4108,7 +4198,7 @@ func (x *QueryTestContainerRequest) String() string { func (*QueryTestContainerRequest) ProtoMessage() {} func (x *QueryTestContainerRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[89] + mi := &file_product_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4121,7 +4211,7 @@ func (x *QueryTestContainerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryTestContainerRequest.ProtoReflect.Descriptor instead. func (*QueryTestContainerRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{89} + return file_product_proto_rawDescGZIP(), []int{91} } func (x *QueryTestContainerRequest) GetId() string { @@ -4141,7 +4231,7 @@ type QueryTestContainerResponse struct { func (x *QueryTestContainerResponse) Reset() { *x = QueryTestContainerResponse{} - mi := &file_product_proto_msgTypes[90] + mi := &file_product_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4153,7 +4243,7 @@ func (x *QueryTestContainerResponse) String() string { func (*QueryTestContainerResponse) ProtoMessage() {} func (x *QueryTestContainerResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[90] + mi := &file_product_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4166,7 +4256,7 @@ func (x *QueryTestContainerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryTestContainerResponse.ProtoReflect.Descriptor instead. func (*QueryTestContainerResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{90} + return file_product_proto_rawDescGZIP(), []int{92} } func (x *QueryTestContainerResponse) GetTestContainer() *TestContainer { @@ -4185,7 +4275,7 @@ type QueryTestContainersRequest struct { func (x *QueryTestContainersRequest) Reset() { *x = QueryTestContainersRequest{} - mi := &file_product_proto_msgTypes[91] + mi := &file_product_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4197,7 +4287,7 @@ func (x *QueryTestContainersRequest) String() string { func (*QueryTestContainersRequest) ProtoMessage() {} func (x *QueryTestContainersRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[91] + mi := &file_product_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4210,7 +4300,7 @@ func (x *QueryTestContainersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryTestContainersRequest.ProtoReflect.Descriptor instead. func (*QueryTestContainersRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{91} + return file_product_proto_rawDescGZIP(), []int{93} } // Response message for testContainers operation. @@ -4223,7 +4313,7 @@ type QueryTestContainersResponse struct { func (x *QueryTestContainersResponse) Reset() { *x = QueryTestContainersResponse{} - mi := &file_product_proto_msgTypes[92] + mi := &file_product_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4235,7 +4325,7 @@ func (x *QueryTestContainersResponse) String() string { func (*QueryTestContainersResponse) ProtoMessage() {} func (x *QueryTestContainersResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[92] + mi := &file_product_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4248,7 +4338,7 @@ func (x *QueryTestContainersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryTestContainersResponse.ProtoReflect.Descriptor instead. func (*QueryTestContainersResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{92} + return file_product_proto_rawDescGZIP(), []int{94} } func (x *QueryTestContainersResponse) GetTestContainers() []*TestContainer { @@ -4268,7 +4358,7 @@ type MutationCreateUserRequest struct { func (x *MutationCreateUserRequest) Reset() { *x = MutationCreateUserRequest{} - mi := &file_product_proto_msgTypes[93] + mi := &file_product_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4280,7 +4370,7 @@ func (x *MutationCreateUserRequest) String() string { func (*MutationCreateUserRequest) ProtoMessage() {} func (x *MutationCreateUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[93] + mi := &file_product_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4293,7 +4383,7 @@ func (x *MutationCreateUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationCreateUserRequest.ProtoReflect.Descriptor instead. func (*MutationCreateUserRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{93} + return file_product_proto_rawDescGZIP(), []int{95} } func (x *MutationCreateUserRequest) GetInput() *UserInput { @@ -4313,7 +4403,7 @@ type MutationCreateUserResponse struct { func (x *MutationCreateUserResponse) Reset() { *x = MutationCreateUserResponse{} - mi := &file_product_proto_msgTypes[94] + mi := &file_product_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4325,7 +4415,7 @@ func (x *MutationCreateUserResponse) String() string { func (*MutationCreateUserResponse) ProtoMessage() {} func (x *MutationCreateUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[94] + mi := &file_product_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4338,7 +4428,7 @@ func (x *MutationCreateUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationCreateUserResponse.ProtoReflect.Descriptor instead. func (*MutationCreateUserResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{94} + return file_product_proto_rawDescGZIP(), []int{96} } func (x *MutationCreateUserResponse) GetCreateUser() *User { @@ -4358,7 +4448,7 @@ type MutationPerformActionRequest struct { func (x *MutationPerformActionRequest) Reset() { *x = MutationPerformActionRequest{} - mi := &file_product_proto_msgTypes[95] + mi := &file_product_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4370,7 +4460,7 @@ func (x *MutationPerformActionRequest) String() string { func (*MutationPerformActionRequest) ProtoMessage() {} func (x *MutationPerformActionRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[95] + mi := &file_product_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4383,7 +4473,7 @@ func (x *MutationPerformActionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationPerformActionRequest.ProtoReflect.Descriptor instead. func (*MutationPerformActionRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{95} + return file_product_proto_rawDescGZIP(), []int{97} } func (x *MutationPerformActionRequest) GetInput() *ActionInput { @@ -4403,7 +4493,7 @@ type MutationPerformActionResponse struct { func (x *MutationPerformActionResponse) Reset() { *x = MutationPerformActionResponse{} - mi := &file_product_proto_msgTypes[96] + mi := &file_product_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4415,7 +4505,7 @@ func (x *MutationPerformActionResponse) String() string { func (*MutationPerformActionResponse) ProtoMessage() {} func (x *MutationPerformActionResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[96] + mi := &file_product_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4428,7 +4518,7 @@ func (x *MutationPerformActionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationPerformActionResponse.ProtoReflect.Descriptor instead. func (*MutationPerformActionResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{96} + return file_product_proto_rawDescGZIP(), []int{98} } func (x *MutationPerformActionResponse) GetPerformAction() *ActionResult { @@ -4448,7 +4538,7 @@ type MutationCreateNullableFieldsTypeRequest struct { func (x *MutationCreateNullableFieldsTypeRequest) Reset() { *x = MutationCreateNullableFieldsTypeRequest{} - mi := &file_product_proto_msgTypes[97] + mi := &file_product_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4460,7 +4550,7 @@ func (x *MutationCreateNullableFieldsTypeRequest) String() string { func (*MutationCreateNullableFieldsTypeRequest) ProtoMessage() {} func (x *MutationCreateNullableFieldsTypeRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[97] + mi := &file_product_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4473,7 +4563,7 @@ func (x *MutationCreateNullableFieldsTypeRequest) ProtoReflect() protoreflect.Me // Deprecated: Use MutationCreateNullableFieldsTypeRequest.ProtoReflect.Descriptor instead. func (*MutationCreateNullableFieldsTypeRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{97} + return file_product_proto_rawDescGZIP(), []int{99} } func (x *MutationCreateNullableFieldsTypeRequest) GetInput() *NullableFieldsInput { @@ -4493,7 +4583,7 @@ type MutationCreateNullableFieldsTypeResponse struct { func (x *MutationCreateNullableFieldsTypeResponse) Reset() { *x = MutationCreateNullableFieldsTypeResponse{} - mi := &file_product_proto_msgTypes[98] + mi := &file_product_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4505,7 +4595,7 @@ func (x *MutationCreateNullableFieldsTypeResponse) String() string { func (*MutationCreateNullableFieldsTypeResponse) ProtoMessage() {} func (x *MutationCreateNullableFieldsTypeResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[98] + mi := &file_product_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4518,7 +4608,7 @@ func (x *MutationCreateNullableFieldsTypeResponse) ProtoReflect() protoreflect.M // Deprecated: Use MutationCreateNullableFieldsTypeResponse.ProtoReflect.Descriptor instead. func (*MutationCreateNullableFieldsTypeResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{98} + return file_product_proto_rawDescGZIP(), []int{100} } func (x *MutationCreateNullableFieldsTypeResponse) GetCreateNullableFieldsType() *NullableFieldsType { @@ -4539,7 +4629,7 @@ type MutationUpdateNullableFieldsTypeRequest struct { func (x *MutationUpdateNullableFieldsTypeRequest) Reset() { *x = MutationUpdateNullableFieldsTypeRequest{} - mi := &file_product_proto_msgTypes[99] + mi := &file_product_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4551,7 +4641,7 @@ func (x *MutationUpdateNullableFieldsTypeRequest) String() string { func (*MutationUpdateNullableFieldsTypeRequest) ProtoMessage() {} func (x *MutationUpdateNullableFieldsTypeRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[99] + mi := &file_product_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4564,7 +4654,7 @@ func (x *MutationUpdateNullableFieldsTypeRequest) ProtoReflect() protoreflect.Me // Deprecated: Use MutationUpdateNullableFieldsTypeRequest.ProtoReflect.Descriptor instead. func (*MutationUpdateNullableFieldsTypeRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{99} + return file_product_proto_rawDescGZIP(), []int{101} } func (x *MutationUpdateNullableFieldsTypeRequest) GetId() string { @@ -4591,7 +4681,7 @@ type MutationUpdateNullableFieldsTypeResponse struct { func (x *MutationUpdateNullableFieldsTypeResponse) Reset() { *x = MutationUpdateNullableFieldsTypeResponse{} - mi := &file_product_proto_msgTypes[100] + mi := &file_product_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4603,7 +4693,7 @@ func (x *MutationUpdateNullableFieldsTypeResponse) String() string { func (*MutationUpdateNullableFieldsTypeResponse) ProtoMessage() {} func (x *MutationUpdateNullableFieldsTypeResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[100] + mi := &file_product_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4616,7 +4706,7 @@ func (x *MutationUpdateNullableFieldsTypeResponse) ProtoReflect() protoreflect.M // Deprecated: Use MutationUpdateNullableFieldsTypeResponse.ProtoReflect.Descriptor instead. func (*MutationUpdateNullableFieldsTypeResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{100} + return file_product_proto_rawDescGZIP(), []int{102} } func (x *MutationUpdateNullableFieldsTypeResponse) GetUpdateNullableFieldsType() *NullableFieldsType { @@ -4636,7 +4726,7 @@ type MutationCreateBlogPostRequest struct { func (x *MutationCreateBlogPostRequest) Reset() { *x = MutationCreateBlogPostRequest{} - mi := &file_product_proto_msgTypes[101] + mi := &file_product_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4648,7 +4738,7 @@ func (x *MutationCreateBlogPostRequest) String() string { func (*MutationCreateBlogPostRequest) ProtoMessage() {} func (x *MutationCreateBlogPostRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[101] + mi := &file_product_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4661,7 +4751,7 @@ func (x *MutationCreateBlogPostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationCreateBlogPostRequest.ProtoReflect.Descriptor instead. func (*MutationCreateBlogPostRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{101} + return file_product_proto_rawDescGZIP(), []int{103} } func (x *MutationCreateBlogPostRequest) GetInput() *BlogPostInput { @@ -4681,7 +4771,7 @@ type MutationCreateBlogPostResponse struct { func (x *MutationCreateBlogPostResponse) Reset() { *x = MutationCreateBlogPostResponse{} - mi := &file_product_proto_msgTypes[102] + mi := &file_product_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4693,7 +4783,7 @@ func (x *MutationCreateBlogPostResponse) String() string { func (*MutationCreateBlogPostResponse) ProtoMessage() {} func (x *MutationCreateBlogPostResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[102] + mi := &file_product_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4706,7 +4796,7 @@ func (x *MutationCreateBlogPostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationCreateBlogPostResponse.ProtoReflect.Descriptor instead. func (*MutationCreateBlogPostResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{102} + return file_product_proto_rawDescGZIP(), []int{104} } func (x *MutationCreateBlogPostResponse) GetCreateBlogPost() *BlogPost { @@ -4727,7 +4817,7 @@ type MutationUpdateBlogPostRequest struct { func (x *MutationUpdateBlogPostRequest) Reset() { *x = MutationUpdateBlogPostRequest{} - mi := &file_product_proto_msgTypes[103] + mi := &file_product_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4739,7 +4829,7 @@ func (x *MutationUpdateBlogPostRequest) String() string { func (*MutationUpdateBlogPostRequest) ProtoMessage() {} func (x *MutationUpdateBlogPostRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[103] + mi := &file_product_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4752,7 +4842,7 @@ func (x *MutationUpdateBlogPostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationUpdateBlogPostRequest.ProtoReflect.Descriptor instead. func (*MutationUpdateBlogPostRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{103} + return file_product_proto_rawDescGZIP(), []int{105} } func (x *MutationUpdateBlogPostRequest) GetId() string { @@ -4779,7 +4869,7 @@ type MutationUpdateBlogPostResponse struct { func (x *MutationUpdateBlogPostResponse) Reset() { *x = MutationUpdateBlogPostResponse{} - mi := &file_product_proto_msgTypes[104] + mi := &file_product_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4791,7 +4881,7 @@ func (x *MutationUpdateBlogPostResponse) String() string { func (*MutationUpdateBlogPostResponse) ProtoMessage() {} func (x *MutationUpdateBlogPostResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[104] + mi := &file_product_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4804,7 +4894,7 @@ func (x *MutationUpdateBlogPostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationUpdateBlogPostResponse.ProtoReflect.Descriptor instead. func (*MutationUpdateBlogPostResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{104} + return file_product_proto_rawDescGZIP(), []int{106} } func (x *MutationUpdateBlogPostResponse) GetUpdateBlogPost() *BlogPost { @@ -4824,7 +4914,7 @@ type MutationCreateAuthorRequest struct { func (x *MutationCreateAuthorRequest) Reset() { *x = MutationCreateAuthorRequest{} - mi := &file_product_proto_msgTypes[105] + mi := &file_product_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4836,7 +4926,7 @@ func (x *MutationCreateAuthorRequest) String() string { func (*MutationCreateAuthorRequest) ProtoMessage() {} func (x *MutationCreateAuthorRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[105] + mi := &file_product_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4849,7 +4939,7 @@ func (x *MutationCreateAuthorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationCreateAuthorRequest.ProtoReflect.Descriptor instead. func (*MutationCreateAuthorRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{105} + return file_product_proto_rawDescGZIP(), []int{107} } func (x *MutationCreateAuthorRequest) GetInput() *AuthorInput { @@ -4869,7 +4959,7 @@ type MutationCreateAuthorResponse struct { func (x *MutationCreateAuthorResponse) Reset() { *x = MutationCreateAuthorResponse{} - mi := &file_product_proto_msgTypes[106] + mi := &file_product_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4881,7 +4971,7 @@ func (x *MutationCreateAuthorResponse) String() string { func (*MutationCreateAuthorResponse) ProtoMessage() {} func (x *MutationCreateAuthorResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[106] + mi := &file_product_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4894,7 +4984,7 @@ func (x *MutationCreateAuthorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationCreateAuthorResponse.ProtoReflect.Descriptor instead. func (*MutationCreateAuthorResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{106} + return file_product_proto_rawDescGZIP(), []int{108} } func (x *MutationCreateAuthorResponse) GetCreateAuthor() *Author { @@ -4915,7 +5005,7 @@ type MutationUpdateAuthorRequest struct { func (x *MutationUpdateAuthorRequest) Reset() { *x = MutationUpdateAuthorRequest{} - mi := &file_product_proto_msgTypes[107] + mi := &file_product_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4927,7 +5017,7 @@ func (x *MutationUpdateAuthorRequest) String() string { func (*MutationUpdateAuthorRequest) ProtoMessage() {} func (x *MutationUpdateAuthorRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[107] + mi := &file_product_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4940,7 +5030,7 @@ func (x *MutationUpdateAuthorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationUpdateAuthorRequest.ProtoReflect.Descriptor instead. func (*MutationUpdateAuthorRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{107} + return file_product_proto_rawDescGZIP(), []int{109} } func (x *MutationUpdateAuthorRequest) GetId() string { @@ -4967,7 +5057,7 @@ type MutationUpdateAuthorResponse struct { func (x *MutationUpdateAuthorResponse) Reset() { *x = MutationUpdateAuthorResponse{} - mi := &file_product_proto_msgTypes[108] + mi := &file_product_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4979,7 +5069,7 @@ func (x *MutationUpdateAuthorResponse) String() string { func (*MutationUpdateAuthorResponse) ProtoMessage() {} func (x *MutationUpdateAuthorResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[108] + mi := &file_product_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4992,7 +5082,7 @@ func (x *MutationUpdateAuthorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationUpdateAuthorResponse.ProtoReflect.Descriptor instead. func (*MutationUpdateAuthorResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{108} + return file_product_proto_rawDescGZIP(), []int{110} } func (x *MutationUpdateAuthorResponse) GetUpdateAuthor() *Author { @@ -5012,7 +5102,7 @@ type MutationBulkCreateAuthorsRequest struct { func (x *MutationBulkCreateAuthorsRequest) Reset() { *x = MutationBulkCreateAuthorsRequest{} - mi := &file_product_proto_msgTypes[109] + mi := &file_product_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5024,7 +5114,7 @@ func (x *MutationBulkCreateAuthorsRequest) String() string { func (*MutationBulkCreateAuthorsRequest) ProtoMessage() {} func (x *MutationBulkCreateAuthorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[109] + mi := &file_product_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5037,7 +5127,7 @@ func (x *MutationBulkCreateAuthorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationBulkCreateAuthorsRequest.ProtoReflect.Descriptor instead. func (*MutationBulkCreateAuthorsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{109} + return file_product_proto_rawDescGZIP(), []int{111} } func (x *MutationBulkCreateAuthorsRequest) GetAuthors() *ListOfAuthorInput { @@ -5057,7 +5147,7 @@ type MutationBulkCreateAuthorsResponse struct { func (x *MutationBulkCreateAuthorsResponse) Reset() { *x = MutationBulkCreateAuthorsResponse{} - mi := &file_product_proto_msgTypes[110] + mi := &file_product_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5069,7 +5159,7 @@ func (x *MutationBulkCreateAuthorsResponse) String() string { func (*MutationBulkCreateAuthorsResponse) ProtoMessage() {} func (x *MutationBulkCreateAuthorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[110] + mi := &file_product_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5082,7 +5172,7 @@ func (x *MutationBulkCreateAuthorsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use MutationBulkCreateAuthorsResponse.ProtoReflect.Descriptor instead. func (*MutationBulkCreateAuthorsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{110} + return file_product_proto_rawDescGZIP(), []int{112} } func (x *MutationBulkCreateAuthorsResponse) GetBulkCreateAuthors() []*Author { @@ -5102,7 +5192,7 @@ type MutationBulkUpdateAuthorsRequest struct { func (x *MutationBulkUpdateAuthorsRequest) Reset() { *x = MutationBulkUpdateAuthorsRequest{} - mi := &file_product_proto_msgTypes[111] + mi := &file_product_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5114,7 +5204,7 @@ func (x *MutationBulkUpdateAuthorsRequest) String() string { func (*MutationBulkUpdateAuthorsRequest) ProtoMessage() {} func (x *MutationBulkUpdateAuthorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[111] + mi := &file_product_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5127,7 +5217,7 @@ func (x *MutationBulkUpdateAuthorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationBulkUpdateAuthorsRequest.ProtoReflect.Descriptor instead. func (*MutationBulkUpdateAuthorsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{111} + return file_product_proto_rawDescGZIP(), []int{113} } func (x *MutationBulkUpdateAuthorsRequest) GetAuthors() *ListOfAuthorInput { @@ -5147,7 +5237,7 @@ type MutationBulkUpdateAuthorsResponse struct { func (x *MutationBulkUpdateAuthorsResponse) Reset() { *x = MutationBulkUpdateAuthorsResponse{} - mi := &file_product_proto_msgTypes[112] + mi := &file_product_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5159,7 +5249,7 @@ func (x *MutationBulkUpdateAuthorsResponse) String() string { func (*MutationBulkUpdateAuthorsResponse) ProtoMessage() {} func (x *MutationBulkUpdateAuthorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[112] + mi := &file_product_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5172,7 +5262,7 @@ func (x *MutationBulkUpdateAuthorsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use MutationBulkUpdateAuthorsResponse.ProtoReflect.Descriptor instead. func (*MutationBulkUpdateAuthorsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{112} + return file_product_proto_rawDescGZIP(), []int{114} } func (x *MutationBulkUpdateAuthorsResponse) GetBulkUpdateAuthors() []*Author { @@ -5192,7 +5282,7 @@ type MutationBulkCreateBlogPostsRequest struct { func (x *MutationBulkCreateBlogPostsRequest) Reset() { *x = MutationBulkCreateBlogPostsRequest{} - mi := &file_product_proto_msgTypes[113] + mi := &file_product_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5204,7 +5294,7 @@ func (x *MutationBulkCreateBlogPostsRequest) String() string { func (*MutationBulkCreateBlogPostsRequest) ProtoMessage() {} func (x *MutationBulkCreateBlogPostsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[113] + mi := &file_product_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5217,7 +5307,7 @@ func (x *MutationBulkCreateBlogPostsRequest) ProtoReflect() protoreflect.Message // Deprecated: Use MutationBulkCreateBlogPostsRequest.ProtoReflect.Descriptor instead. func (*MutationBulkCreateBlogPostsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{113} + return file_product_proto_rawDescGZIP(), []int{115} } func (x *MutationBulkCreateBlogPostsRequest) GetBlogPosts() *ListOfBlogPostInput { @@ -5237,7 +5327,7 @@ type MutationBulkCreateBlogPostsResponse struct { func (x *MutationBulkCreateBlogPostsResponse) Reset() { *x = MutationBulkCreateBlogPostsResponse{} - mi := &file_product_proto_msgTypes[114] + mi := &file_product_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5249,7 +5339,7 @@ func (x *MutationBulkCreateBlogPostsResponse) String() string { func (*MutationBulkCreateBlogPostsResponse) ProtoMessage() {} func (x *MutationBulkCreateBlogPostsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[114] + mi := &file_product_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5262,7 +5352,7 @@ func (x *MutationBulkCreateBlogPostsResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use MutationBulkCreateBlogPostsResponse.ProtoReflect.Descriptor instead. func (*MutationBulkCreateBlogPostsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{114} + return file_product_proto_rawDescGZIP(), []int{116} } func (x *MutationBulkCreateBlogPostsResponse) GetBulkCreateBlogPosts() []*BlogPost { @@ -5282,7 +5372,7 @@ type MutationBulkUpdateBlogPostsRequest struct { func (x *MutationBulkUpdateBlogPostsRequest) Reset() { *x = MutationBulkUpdateBlogPostsRequest{} - mi := &file_product_proto_msgTypes[115] + mi := &file_product_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5294,7 +5384,7 @@ func (x *MutationBulkUpdateBlogPostsRequest) String() string { func (*MutationBulkUpdateBlogPostsRequest) ProtoMessage() {} func (x *MutationBulkUpdateBlogPostsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[115] + mi := &file_product_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5307,7 +5397,7 @@ func (x *MutationBulkUpdateBlogPostsRequest) ProtoReflect() protoreflect.Message // Deprecated: Use MutationBulkUpdateBlogPostsRequest.ProtoReflect.Descriptor instead. func (*MutationBulkUpdateBlogPostsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{115} + return file_product_proto_rawDescGZIP(), []int{117} } func (x *MutationBulkUpdateBlogPostsRequest) GetBlogPosts() *ListOfBlogPostInput { @@ -5327,7 +5417,7 @@ type MutationBulkUpdateBlogPostsResponse struct { func (x *MutationBulkUpdateBlogPostsResponse) Reset() { *x = MutationBulkUpdateBlogPostsResponse{} - mi := &file_product_proto_msgTypes[116] + mi := &file_product_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5339,7 +5429,7 @@ func (x *MutationBulkUpdateBlogPostsResponse) String() string { func (*MutationBulkUpdateBlogPostsResponse) ProtoMessage() {} func (x *MutationBulkUpdateBlogPostsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[116] + mi := &file_product_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5352,7 +5442,7 @@ func (x *MutationBulkUpdateBlogPostsResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use MutationBulkUpdateBlogPostsResponse.ProtoReflect.Descriptor instead. func (*MutationBulkUpdateBlogPostsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{116} + return file_product_proto_rawDescGZIP(), []int{118} } func (x *MutationBulkUpdateBlogPostsResponse) GetBulkUpdateBlogPosts() []*BlogPost { @@ -5371,7 +5461,7 @@ type ResolveProductShippingEstimateArgs struct { func (x *ResolveProductShippingEstimateArgs) Reset() { *x = ResolveProductShippingEstimateArgs{} - mi := &file_product_proto_msgTypes[117] + mi := &file_product_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5383,7 +5473,7 @@ func (x *ResolveProductShippingEstimateArgs) String() string { func (*ResolveProductShippingEstimateArgs) ProtoMessage() {} func (x *ResolveProductShippingEstimateArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[117] + mi := &file_product_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5396,7 +5486,7 @@ func (x *ResolveProductShippingEstimateArgs) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveProductShippingEstimateArgs.ProtoReflect.Descriptor instead. func (*ResolveProductShippingEstimateArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{117} + return file_product_proto_rawDescGZIP(), []int{119} } func (x *ResolveProductShippingEstimateArgs) GetInput() *ShippingEstimateInput { @@ -5416,7 +5506,7 @@ type ResolveProductShippingEstimateContext struct { func (x *ResolveProductShippingEstimateContext) Reset() { *x = ResolveProductShippingEstimateContext{} - mi := &file_product_proto_msgTypes[118] + mi := &file_product_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5428,7 +5518,7 @@ func (x *ResolveProductShippingEstimateContext) String() string { func (*ResolveProductShippingEstimateContext) ProtoMessage() {} func (x *ResolveProductShippingEstimateContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[118] + mi := &file_product_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5441,7 +5531,7 @@ func (x *ResolveProductShippingEstimateContext) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveProductShippingEstimateContext.ProtoReflect.Descriptor instead. func (*ResolveProductShippingEstimateContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{118} + return file_product_proto_rawDescGZIP(), []int{120} } func (x *ResolveProductShippingEstimateContext) GetId() string { @@ -5470,7 +5560,7 @@ type ResolveProductShippingEstimateRequest struct { func (x *ResolveProductShippingEstimateRequest) Reset() { *x = ResolveProductShippingEstimateRequest{} - mi := &file_product_proto_msgTypes[119] + mi := &file_product_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5482,7 +5572,7 @@ func (x *ResolveProductShippingEstimateRequest) String() string { func (*ResolveProductShippingEstimateRequest) ProtoMessage() {} func (x *ResolveProductShippingEstimateRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[119] + mi := &file_product_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5495,7 +5585,7 @@ func (x *ResolveProductShippingEstimateRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveProductShippingEstimateRequest.ProtoReflect.Descriptor instead. func (*ResolveProductShippingEstimateRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{119} + return file_product_proto_rawDescGZIP(), []int{121} } func (x *ResolveProductShippingEstimateRequest) GetContext() []*ResolveProductShippingEstimateContext { @@ -5521,7 +5611,7 @@ type ResolveProductShippingEstimateResult struct { func (x *ResolveProductShippingEstimateResult) Reset() { *x = ResolveProductShippingEstimateResult{} - mi := &file_product_proto_msgTypes[120] + mi := &file_product_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5533,7 +5623,7 @@ func (x *ResolveProductShippingEstimateResult) String() string { func (*ResolveProductShippingEstimateResult) ProtoMessage() {} func (x *ResolveProductShippingEstimateResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[120] + mi := &file_product_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5546,7 +5636,7 @@ func (x *ResolveProductShippingEstimateResult) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveProductShippingEstimateResult.ProtoReflect.Descriptor instead. func (*ResolveProductShippingEstimateResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{120} + return file_product_proto_rawDescGZIP(), []int{122} } func (x *ResolveProductShippingEstimateResult) GetShippingEstimate() float64 { @@ -5565,7 +5655,7 @@ type ResolveProductShippingEstimateResponse struct { func (x *ResolveProductShippingEstimateResponse) Reset() { *x = ResolveProductShippingEstimateResponse{} - mi := &file_product_proto_msgTypes[121] + mi := &file_product_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5577,7 +5667,7 @@ func (x *ResolveProductShippingEstimateResponse) String() string { func (*ResolveProductShippingEstimateResponse) ProtoMessage() {} func (x *ResolveProductShippingEstimateResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[121] + mi := &file_product_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5590,7 +5680,7 @@ func (x *ResolveProductShippingEstimateResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ResolveProductShippingEstimateResponse.ProtoReflect.Descriptor instead. func (*ResolveProductShippingEstimateResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{121} + return file_product_proto_rawDescGZIP(), []int{123} } func (x *ResolveProductShippingEstimateResponse) GetResult() []*ResolveProductShippingEstimateResult { @@ -5609,7 +5699,7 @@ type ResolveProductRecommendedCategoryArgs struct { func (x *ResolveProductRecommendedCategoryArgs) Reset() { *x = ResolveProductRecommendedCategoryArgs{} - mi := &file_product_proto_msgTypes[122] + mi := &file_product_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5621,7 +5711,7 @@ func (x *ResolveProductRecommendedCategoryArgs) String() string { func (*ResolveProductRecommendedCategoryArgs) ProtoMessage() {} func (x *ResolveProductRecommendedCategoryArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[122] + mi := &file_product_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5634,7 +5724,7 @@ func (x *ResolveProductRecommendedCategoryArgs) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveProductRecommendedCategoryArgs.ProtoReflect.Descriptor instead. func (*ResolveProductRecommendedCategoryArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{122} + return file_product_proto_rawDescGZIP(), []int{124} } func (x *ResolveProductRecommendedCategoryArgs) GetMaxPrice() int32 { @@ -5655,7 +5745,7 @@ type ResolveProductRecommendedCategoryContext struct { func (x *ResolveProductRecommendedCategoryContext) Reset() { *x = ResolveProductRecommendedCategoryContext{} - mi := &file_product_proto_msgTypes[123] + mi := &file_product_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5667,7 +5757,7 @@ func (x *ResolveProductRecommendedCategoryContext) String() string { func (*ResolveProductRecommendedCategoryContext) ProtoMessage() {} func (x *ResolveProductRecommendedCategoryContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[123] + mi := &file_product_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5680,7 +5770,7 @@ func (x *ResolveProductRecommendedCategoryContext) ProtoReflect() protoreflect.M // Deprecated: Use ResolveProductRecommendedCategoryContext.ProtoReflect.Descriptor instead. func (*ResolveProductRecommendedCategoryContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{123} + return file_product_proto_rawDescGZIP(), []int{125} } func (x *ResolveProductRecommendedCategoryContext) GetId() string { @@ -5716,7 +5806,7 @@ type ResolveProductRecommendedCategoryRequest struct { func (x *ResolveProductRecommendedCategoryRequest) Reset() { *x = ResolveProductRecommendedCategoryRequest{} - mi := &file_product_proto_msgTypes[124] + mi := &file_product_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5728,7 +5818,7 @@ func (x *ResolveProductRecommendedCategoryRequest) String() string { func (*ResolveProductRecommendedCategoryRequest) ProtoMessage() {} func (x *ResolveProductRecommendedCategoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[124] + mi := &file_product_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5741,7 +5831,7 @@ func (x *ResolveProductRecommendedCategoryRequest) ProtoReflect() protoreflect.M // Deprecated: Use ResolveProductRecommendedCategoryRequest.ProtoReflect.Descriptor instead. func (*ResolveProductRecommendedCategoryRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{124} + return file_product_proto_rawDescGZIP(), []int{126} } func (x *ResolveProductRecommendedCategoryRequest) GetContext() []*ResolveProductRecommendedCategoryContext { @@ -5767,7 +5857,7 @@ type ResolveProductRecommendedCategoryResult struct { func (x *ResolveProductRecommendedCategoryResult) Reset() { *x = ResolveProductRecommendedCategoryResult{} - mi := &file_product_proto_msgTypes[125] + mi := &file_product_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5779,7 +5869,7 @@ func (x *ResolveProductRecommendedCategoryResult) String() string { func (*ResolveProductRecommendedCategoryResult) ProtoMessage() {} func (x *ResolveProductRecommendedCategoryResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[125] + mi := &file_product_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5792,7 +5882,7 @@ func (x *ResolveProductRecommendedCategoryResult) ProtoReflect() protoreflect.Me // Deprecated: Use ResolveProductRecommendedCategoryResult.ProtoReflect.Descriptor instead. func (*ResolveProductRecommendedCategoryResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{125} + return file_product_proto_rawDescGZIP(), []int{127} } func (x *ResolveProductRecommendedCategoryResult) GetRecommendedCategory() *Category { @@ -5811,7 +5901,7 @@ type ResolveProductRecommendedCategoryResponse struct { func (x *ResolveProductRecommendedCategoryResponse) Reset() { *x = ResolveProductRecommendedCategoryResponse{} - mi := &file_product_proto_msgTypes[126] + mi := &file_product_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5823,7 +5913,7 @@ func (x *ResolveProductRecommendedCategoryResponse) String() string { func (*ResolveProductRecommendedCategoryResponse) ProtoMessage() {} func (x *ResolveProductRecommendedCategoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[126] + mi := &file_product_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5836,7 +5926,7 @@ func (x *ResolveProductRecommendedCategoryResponse) ProtoReflect() protoreflect. // Deprecated: Use ResolveProductRecommendedCategoryResponse.ProtoReflect.Descriptor instead. func (*ResolveProductRecommendedCategoryResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{126} + return file_product_proto_rawDescGZIP(), []int{128} } func (x *ResolveProductRecommendedCategoryResponse) GetResult() []*ResolveProductRecommendedCategoryResult { @@ -5855,7 +5945,7 @@ type ResolveProductMascotRecommendationArgs struct { func (x *ResolveProductMascotRecommendationArgs) Reset() { *x = ResolveProductMascotRecommendationArgs{} - mi := &file_product_proto_msgTypes[127] + mi := &file_product_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5867,7 +5957,7 @@ func (x *ResolveProductMascotRecommendationArgs) String() string { func (*ResolveProductMascotRecommendationArgs) ProtoMessage() {} func (x *ResolveProductMascotRecommendationArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[127] + mi := &file_product_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5880,7 +5970,7 @@ func (x *ResolveProductMascotRecommendationArgs) ProtoReflect() protoreflect.Mes // Deprecated: Use ResolveProductMascotRecommendationArgs.ProtoReflect.Descriptor instead. func (*ResolveProductMascotRecommendationArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{127} + return file_product_proto_rawDescGZIP(), []int{129} } func (x *ResolveProductMascotRecommendationArgs) GetIncludeDetails() bool { @@ -5900,7 +5990,7 @@ type ResolveProductMascotRecommendationContext struct { func (x *ResolveProductMascotRecommendationContext) Reset() { *x = ResolveProductMascotRecommendationContext{} - mi := &file_product_proto_msgTypes[128] + mi := &file_product_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5912,7 +6002,7 @@ func (x *ResolveProductMascotRecommendationContext) String() string { func (*ResolveProductMascotRecommendationContext) ProtoMessage() {} func (x *ResolveProductMascotRecommendationContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[128] + mi := &file_product_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5925,7 +6015,7 @@ func (x *ResolveProductMascotRecommendationContext) ProtoReflect() protoreflect. // Deprecated: Use ResolveProductMascotRecommendationContext.ProtoReflect.Descriptor instead. func (*ResolveProductMascotRecommendationContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{128} + return file_product_proto_rawDescGZIP(), []int{130} } func (x *ResolveProductMascotRecommendationContext) GetId() string { @@ -5954,7 +6044,7 @@ type ResolveProductMascotRecommendationRequest struct { func (x *ResolveProductMascotRecommendationRequest) Reset() { *x = ResolveProductMascotRecommendationRequest{} - mi := &file_product_proto_msgTypes[129] + mi := &file_product_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5966,7 +6056,7 @@ func (x *ResolveProductMascotRecommendationRequest) String() string { func (*ResolveProductMascotRecommendationRequest) ProtoMessage() {} func (x *ResolveProductMascotRecommendationRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[129] + mi := &file_product_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5979,7 +6069,7 @@ func (x *ResolveProductMascotRecommendationRequest) ProtoReflect() protoreflect. // Deprecated: Use ResolveProductMascotRecommendationRequest.ProtoReflect.Descriptor instead. func (*ResolveProductMascotRecommendationRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{129} + return file_product_proto_rawDescGZIP(), []int{131} } func (x *ResolveProductMascotRecommendationRequest) GetContext() []*ResolveProductMascotRecommendationContext { @@ -6005,7 +6095,7 @@ type ResolveProductMascotRecommendationResult struct { func (x *ResolveProductMascotRecommendationResult) Reset() { *x = ResolveProductMascotRecommendationResult{} - mi := &file_product_proto_msgTypes[130] + mi := &file_product_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6017,7 +6107,7 @@ func (x *ResolveProductMascotRecommendationResult) String() string { func (*ResolveProductMascotRecommendationResult) ProtoMessage() {} func (x *ResolveProductMascotRecommendationResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[130] + mi := &file_product_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6030,7 +6120,7 @@ func (x *ResolveProductMascotRecommendationResult) ProtoReflect() protoreflect.M // Deprecated: Use ResolveProductMascotRecommendationResult.ProtoReflect.Descriptor instead. func (*ResolveProductMascotRecommendationResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{130} + return file_product_proto_rawDescGZIP(), []int{132} } func (x *ResolveProductMascotRecommendationResult) GetMascotRecommendation() *Animal { @@ -6049,7 +6139,7 @@ type ResolveProductMascotRecommendationResponse struct { func (x *ResolveProductMascotRecommendationResponse) Reset() { *x = ResolveProductMascotRecommendationResponse{} - mi := &file_product_proto_msgTypes[131] + mi := &file_product_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6061,7 +6151,7 @@ func (x *ResolveProductMascotRecommendationResponse) String() string { func (*ResolveProductMascotRecommendationResponse) ProtoMessage() {} func (x *ResolveProductMascotRecommendationResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[131] + mi := &file_product_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6074,7 +6164,7 @@ func (x *ResolveProductMascotRecommendationResponse) ProtoReflect() protoreflect // Deprecated: Use ResolveProductMascotRecommendationResponse.ProtoReflect.Descriptor instead. func (*ResolveProductMascotRecommendationResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{131} + return file_product_proto_rawDescGZIP(), []int{133} } func (x *ResolveProductMascotRecommendationResponse) GetResult() []*ResolveProductMascotRecommendationResult { @@ -6093,7 +6183,7 @@ type ResolveProductStockStatusArgs struct { func (x *ResolveProductStockStatusArgs) Reset() { *x = ResolveProductStockStatusArgs{} - mi := &file_product_proto_msgTypes[132] + mi := &file_product_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6105,7 +6195,7 @@ func (x *ResolveProductStockStatusArgs) String() string { func (*ResolveProductStockStatusArgs) ProtoMessage() {} func (x *ResolveProductStockStatusArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[132] + mi := &file_product_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6118,7 +6208,7 @@ func (x *ResolveProductStockStatusArgs) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveProductStockStatusArgs.ProtoReflect.Descriptor instead. func (*ResolveProductStockStatusArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{132} + return file_product_proto_rawDescGZIP(), []int{134} } func (x *ResolveProductStockStatusArgs) GetCheckAvailability() bool { @@ -6139,7 +6229,7 @@ type ResolveProductStockStatusContext struct { func (x *ResolveProductStockStatusContext) Reset() { *x = ResolveProductStockStatusContext{} - mi := &file_product_proto_msgTypes[133] + mi := &file_product_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6151,7 +6241,7 @@ func (x *ResolveProductStockStatusContext) String() string { func (*ResolveProductStockStatusContext) ProtoMessage() {} func (x *ResolveProductStockStatusContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[133] + mi := &file_product_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6164,7 +6254,7 @@ func (x *ResolveProductStockStatusContext) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveProductStockStatusContext.ProtoReflect.Descriptor instead. func (*ResolveProductStockStatusContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{133} + return file_product_proto_rawDescGZIP(), []int{135} } func (x *ResolveProductStockStatusContext) GetId() string { @@ -6200,7 +6290,7 @@ type ResolveProductStockStatusRequest struct { func (x *ResolveProductStockStatusRequest) Reset() { *x = ResolveProductStockStatusRequest{} - mi := &file_product_proto_msgTypes[134] + mi := &file_product_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6212,7 +6302,7 @@ func (x *ResolveProductStockStatusRequest) String() string { func (*ResolveProductStockStatusRequest) ProtoMessage() {} func (x *ResolveProductStockStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[134] + mi := &file_product_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6225,7 +6315,7 @@ func (x *ResolveProductStockStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveProductStockStatusRequest.ProtoReflect.Descriptor instead. func (*ResolveProductStockStatusRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{134} + return file_product_proto_rawDescGZIP(), []int{136} } func (x *ResolveProductStockStatusRequest) GetContext() []*ResolveProductStockStatusContext { @@ -6251,7 +6341,7 @@ type ResolveProductStockStatusResult struct { func (x *ResolveProductStockStatusResult) Reset() { *x = ResolveProductStockStatusResult{} - mi := &file_product_proto_msgTypes[135] + mi := &file_product_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6263,7 +6353,7 @@ func (x *ResolveProductStockStatusResult) String() string { func (*ResolveProductStockStatusResult) ProtoMessage() {} func (x *ResolveProductStockStatusResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[135] + mi := &file_product_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6276,7 +6366,7 @@ func (x *ResolveProductStockStatusResult) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveProductStockStatusResult.ProtoReflect.Descriptor instead. func (*ResolveProductStockStatusResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{135} + return file_product_proto_rawDescGZIP(), []int{137} } func (x *ResolveProductStockStatusResult) GetStockStatus() *ActionResult { @@ -6295,7 +6385,7 @@ type ResolveProductStockStatusResponse struct { func (x *ResolveProductStockStatusResponse) Reset() { *x = ResolveProductStockStatusResponse{} - mi := &file_product_proto_msgTypes[136] + mi := &file_product_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6307,7 +6397,7 @@ func (x *ResolveProductStockStatusResponse) String() string { func (*ResolveProductStockStatusResponse) ProtoMessage() {} func (x *ResolveProductStockStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[136] + mi := &file_product_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6320,7 +6410,7 @@ func (x *ResolveProductStockStatusResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveProductStockStatusResponse.ProtoReflect.Descriptor instead. func (*ResolveProductStockStatusResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{136} + return file_product_proto_rawDescGZIP(), []int{138} } func (x *ResolveProductStockStatusResponse) GetResult() []*ResolveProductStockStatusResult { @@ -6339,7 +6429,7 @@ type ResolveProductProductDetailsArgs struct { func (x *ResolveProductProductDetailsArgs) Reset() { *x = ResolveProductProductDetailsArgs{} - mi := &file_product_proto_msgTypes[137] + mi := &file_product_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6351,7 +6441,7 @@ func (x *ResolveProductProductDetailsArgs) String() string { func (*ResolveProductProductDetailsArgs) ProtoMessage() {} func (x *ResolveProductProductDetailsArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[137] + mi := &file_product_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6364,7 +6454,7 @@ func (x *ResolveProductProductDetailsArgs) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveProductProductDetailsArgs.ProtoReflect.Descriptor instead. func (*ResolveProductProductDetailsArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{137} + return file_product_proto_rawDescGZIP(), []int{139} } func (x *ResolveProductProductDetailsArgs) GetIncludeExtended() bool { @@ -6385,7 +6475,7 @@ type ResolveProductProductDetailsContext struct { func (x *ResolveProductProductDetailsContext) Reset() { *x = ResolveProductProductDetailsContext{} - mi := &file_product_proto_msgTypes[138] + mi := &file_product_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6397,7 +6487,7 @@ func (x *ResolveProductProductDetailsContext) String() string { func (*ResolveProductProductDetailsContext) ProtoMessage() {} func (x *ResolveProductProductDetailsContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[138] + mi := &file_product_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6410,7 +6500,7 @@ func (x *ResolveProductProductDetailsContext) ProtoReflect() protoreflect.Messag // Deprecated: Use ResolveProductProductDetailsContext.ProtoReflect.Descriptor instead. func (*ResolveProductProductDetailsContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{138} + return file_product_proto_rawDescGZIP(), []int{140} } func (x *ResolveProductProductDetailsContext) GetId() string { @@ -6446,7 +6536,7 @@ type ResolveProductProductDetailsRequest struct { func (x *ResolveProductProductDetailsRequest) Reset() { *x = ResolveProductProductDetailsRequest{} - mi := &file_product_proto_msgTypes[139] + mi := &file_product_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6458,7 +6548,7 @@ func (x *ResolveProductProductDetailsRequest) String() string { func (*ResolveProductProductDetailsRequest) ProtoMessage() {} func (x *ResolveProductProductDetailsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[139] + mi := &file_product_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6471,7 +6561,7 @@ func (x *ResolveProductProductDetailsRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use ResolveProductProductDetailsRequest.ProtoReflect.Descriptor instead. func (*ResolveProductProductDetailsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{139} + return file_product_proto_rawDescGZIP(), []int{141} } func (x *ResolveProductProductDetailsRequest) GetContext() []*ResolveProductProductDetailsContext { @@ -6497,7 +6587,7 @@ type ResolveProductProductDetailsResult struct { func (x *ResolveProductProductDetailsResult) Reset() { *x = ResolveProductProductDetailsResult{} - mi := &file_product_proto_msgTypes[140] + mi := &file_product_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6509,7 +6599,7 @@ func (x *ResolveProductProductDetailsResult) String() string { func (*ResolveProductProductDetailsResult) ProtoMessage() {} func (x *ResolveProductProductDetailsResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[140] + mi := &file_product_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6522,7 +6612,7 @@ func (x *ResolveProductProductDetailsResult) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveProductProductDetailsResult.ProtoReflect.Descriptor instead. func (*ResolveProductProductDetailsResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{140} + return file_product_proto_rawDescGZIP(), []int{142} } func (x *ResolveProductProductDetailsResult) GetProductDetails() *ProductDetails { @@ -6541,7 +6631,7 @@ type ResolveProductProductDetailsResponse struct { func (x *ResolveProductProductDetailsResponse) Reset() { *x = ResolveProductProductDetailsResponse{} - mi := &file_product_proto_msgTypes[141] + mi := &file_product_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6553,7 +6643,7 @@ func (x *ResolveProductProductDetailsResponse) String() string { func (*ResolveProductProductDetailsResponse) ProtoMessage() {} func (x *ResolveProductProductDetailsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[141] + mi := &file_product_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6566,7 +6656,7 @@ func (x *ResolveProductProductDetailsResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveProductProductDetailsResponse.ProtoReflect.Descriptor instead. func (*ResolveProductProductDetailsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{141} + return file_product_proto_rawDescGZIP(), []int{143} } func (x *ResolveProductProductDetailsResponse) GetResult() []*ResolveProductProductDetailsResult { @@ -6585,7 +6675,7 @@ type ResolveCategoryProductCountArgs struct { func (x *ResolveCategoryProductCountArgs) Reset() { *x = ResolveCategoryProductCountArgs{} - mi := &file_product_proto_msgTypes[142] + mi := &file_product_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6597,7 +6687,7 @@ func (x *ResolveCategoryProductCountArgs) String() string { func (*ResolveCategoryProductCountArgs) ProtoMessage() {} func (x *ResolveCategoryProductCountArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[142] + mi := &file_product_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6610,7 +6700,7 @@ func (x *ResolveCategoryProductCountArgs) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveCategoryProductCountArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryProductCountArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{142} + return file_product_proto_rawDescGZIP(), []int{144} } func (x *ResolveCategoryProductCountArgs) GetFilters() *ProductCountFilter { @@ -6630,7 +6720,7 @@ type ResolveCategoryProductCountContext struct { func (x *ResolveCategoryProductCountContext) Reset() { *x = ResolveCategoryProductCountContext{} - mi := &file_product_proto_msgTypes[143] + mi := &file_product_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6642,7 +6732,7 @@ func (x *ResolveCategoryProductCountContext) String() string { func (*ResolveCategoryProductCountContext) ProtoMessage() {} func (x *ResolveCategoryProductCountContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[143] + mi := &file_product_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6655,7 +6745,7 @@ func (x *ResolveCategoryProductCountContext) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryProductCountContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryProductCountContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{143} + return file_product_proto_rawDescGZIP(), []int{145} } func (x *ResolveCategoryProductCountContext) GetId() string { @@ -6684,7 +6774,7 @@ type ResolveCategoryProductCountRequest struct { func (x *ResolveCategoryProductCountRequest) Reset() { *x = ResolveCategoryProductCountRequest{} - mi := &file_product_proto_msgTypes[144] + mi := &file_product_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6696,7 +6786,7 @@ func (x *ResolveCategoryProductCountRequest) String() string { func (*ResolveCategoryProductCountRequest) ProtoMessage() {} func (x *ResolveCategoryProductCountRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[144] + mi := &file_product_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6709,7 +6799,7 @@ func (x *ResolveCategoryProductCountRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryProductCountRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryProductCountRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{144} + return file_product_proto_rawDescGZIP(), []int{146} } func (x *ResolveCategoryProductCountRequest) GetContext() []*ResolveCategoryProductCountContext { @@ -6735,7 +6825,7 @@ type ResolveCategoryProductCountResult struct { func (x *ResolveCategoryProductCountResult) Reset() { *x = ResolveCategoryProductCountResult{} - mi := &file_product_proto_msgTypes[145] + mi := &file_product_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6747,7 +6837,7 @@ func (x *ResolveCategoryProductCountResult) String() string { func (*ResolveCategoryProductCountResult) ProtoMessage() {} func (x *ResolveCategoryProductCountResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[145] + mi := &file_product_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6760,7 +6850,7 @@ func (x *ResolveCategoryProductCountResult) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryProductCountResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryProductCountResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{145} + return file_product_proto_rawDescGZIP(), []int{147} } func (x *ResolveCategoryProductCountResult) GetProductCount() int32 { @@ -6779,7 +6869,7 @@ type ResolveCategoryProductCountResponse struct { func (x *ResolveCategoryProductCountResponse) Reset() { *x = ResolveCategoryProductCountResponse{} - mi := &file_product_proto_msgTypes[146] + mi := &file_product_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6791,7 +6881,7 @@ func (x *ResolveCategoryProductCountResponse) String() string { func (*ResolveCategoryProductCountResponse) ProtoMessage() {} func (x *ResolveCategoryProductCountResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[146] + mi := &file_product_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6804,7 +6894,7 @@ func (x *ResolveCategoryProductCountResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use ResolveCategoryProductCountResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryProductCountResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{146} + return file_product_proto_rawDescGZIP(), []int{148} } func (x *ResolveCategoryProductCountResponse) GetResult() []*ResolveCategoryProductCountResult { @@ -6823,7 +6913,7 @@ type ResolveCategoryPopularityScoreArgs struct { func (x *ResolveCategoryPopularityScoreArgs) Reset() { *x = ResolveCategoryPopularityScoreArgs{} - mi := &file_product_proto_msgTypes[147] + mi := &file_product_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6835,7 +6925,7 @@ func (x *ResolveCategoryPopularityScoreArgs) String() string { func (*ResolveCategoryPopularityScoreArgs) ProtoMessage() {} func (x *ResolveCategoryPopularityScoreArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[147] + mi := &file_product_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6848,7 +6938,7 @@ func (x *ResolveCategoryPopularityScoreArgs) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryPopularityScoreArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryPopularityScoreArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{147} + return file_product_proto_rawDescGZIP(), []int{149} } func (x *ResolveCategoryPopularityScoreArgs) GetThreshold() *wrapperspb.Int32Value { @@ -6867,7 +6957,7 @@ type ResolveCategoryPopularityScoreContext struct { func (x *ResolveCategoryPopularityScoreContext) Reset() { *x = ResolveCategoryPopularityScoreContext{} - mi := &file_product_proto_msgTypes[148] + mi := &file_product_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6879,7 +6969,7 @@ func (x *ResolveCategoryPopularityScoreContext) String() string { func (*ResolveCategoryPopularityScoreContext) ProtoMessage() {} func (x *ResolveCategoryPopularityScoreContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[148] + mi := &file_product_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6892,7 +6982,7 @@ func (x *ResolveCategoryPopularityScoreContext) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryPopularityScoreContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryPopularityScoreContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{148} + return file_product_proto_rawDescGZIP(), []int{150} } func (x *ResolveCategoryPopularityScoreContext) GetId() string { @@ -6914,7 +7004,7 @@ type ResolveCategoryPopularityScoreRequest struct { func (x *ResolveCategoryPopularityScoreRequest) Reset() { *x = ResolveCategoryPopularityScoreRequest{} - mi := &file_product_proto_msgTypes[149] + mi := &file_product_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6926,7 +7016,7 @@ func (x *ResolveCategoryPopularityScoreRequest) String() string { func (*ResolveCategoryPopularityScoreRequest) ProtoMessage() {} func (x *ResolveCategoryPopularityScoreRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[149] + mi := &file_product_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6939,7 +7029,7 @@ func (x *ResolveCategoryPopularityScoreRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryPopularityScoreRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryPopularityScoreRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{149} + return file_product_proto_rawDescGZIP(), []int{151} } func (x *ResolveCategoryPopularityScoreRequest) GetContext() []*ResolveCategoryPopularityScoreContext { @@ -6965,7 +7055,7 @@ type ResolveCategoryPopularityScoreResult struct { func (x *ResolveCategoryPopularityScoreResult) Reset() { *x = ResolveCategoryPopularityScoreResult{} - mi := &file_product_proto_msgTypes[150] + mi := &file_product_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6977,7 +7067,7 @@ func (x *ResolveCategoryPopularityScoreResult) String() string { func (*ResolveCategoryPopularityScoreResult) ProtoMessage() {} func (x *ResolveCategoryPopularityScoreResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[150] + mi := &file_product_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6990,7 +7080,7 @@ func (x *ResolveCategoryPopularityScoreResult) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveCategoryPopularityScoreResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryPopularityScoreResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{150} + return file_product_proto_rawDescGZIP(), []int{152} } func (x *ResolveCategoryPopularityScoreResult) GetPopularityScore() *wrapperspb.Int32Value { @@ -7009,7 +7099,7 @@ type ResolveCategoryPopularityScoreResponse struct { func (x *ResolveCategoryPopularityScoreResponse) Reset() { *x = ResolveCategoryPopularityScoreResponse{} - mi := &file_product_proto_msgTypes[151] + mi := &file_product_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7021,7 +7111,7 @@ func (x *ResolveCategoryPopularityScoreResponse) String() string { func (*ResolveCategoryPopularityScoreResponse) ProtoMessage() {} func (x *ResolveCategoryPopularityScoreResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[151] + mi := &file_product_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7034,7 +7124,7 @@ func (x *ResolveCategoryPopularityScoreResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ResolveCategoryPopularityScoreResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryPopularityScoreResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{151} + return file_product_proto_rawDescGZIP(), []int{153} } func (x *ResolveCategoryPopularityScoreResponse) GetResult() []*ResolveCategoryPopularityScoreResult { @@ -7053,7 +7143,7 @@ type ResolveCategoryCategoryMetricsArgs struct { func (x *ResolveCategoryCategoryMetricsArgs) Reset() { *x = ResolveCategoryCategoryMetricsArgs{} - mi := &file_product_proto_msgTypes[152] + mi := &file_product_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7065,7 +7155,7 @@ func (x *ResolveCategoryCategoryMetricsArgs) String() string { func (*ResolveCategoryCategoryMetricsArgs) ProtoMessage() {} func (x *ResolveCategoryCategoryMetricsArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[152] + mi := &file_product_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7078,7 +7168,7 @@ func (x *ResolveCategoryCategoryMetricsArgs) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryCategoryMetricsArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryMetricsArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{152} + return file_product_proto_rawDescGZIP(), []int{154} } func (x *ResolveCategoryCategoryMetricsArgs) GetMetricType() string { @@ -7098,7 +7188,7 @@ type ResolveCategoryCategoryMetricsContext struct { func (x *ResolveCategoryCategoryMetricsContext) Reset() { *x = ResolveCategoryCategoryMetricsContext{} - mi := &file_product_proto_msgTypes[153] + mi := &file_product_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7110,7 +7200,7 @@ func (x *ResolveCategoryCategoryMetricsContext) String() string { func (*ResolveCategoryCategoryMetricsContext) ProtoMessage() {} func (x *ResolveCategoryCategoryMetricsContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[153] + mi := &file_product_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7123,7 +7213,7 @@ func (x *ResolveCategoryCategoryMetricsContext) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryCategoryMetricsContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryMetricsContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{153} + return file_product_proto_rawDescGZIP(), []int{155} } func (x *ResolveCategoryCategoryMetricsContext) GetId() string { @@ -7152,7 +7242,7 @@ type ResolveCategoryCategoryMetricsRequest struct { func (x *ResolveCategoryCategoryMetricsRequest) Reset() { *x = ResolveCategoryCategoryMetricsRequest{} - mi := &file_product_proto_msgTypes[154] + mi := &file_product_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7164,7 +7254,7 @@ func (x *ResolveCategoryCategoryMetricsRequest) String() string { func (*ResolveCategoryCategoryMetricsRequest) ProtoMessage() {} func (x *ResolveCategoryCategoryMetricsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[154] + mi := &file_product_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7177,7 +7267,7 @@ func (x *ResolveCategoryCategoryMetricsRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryCategoryMetricsRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryMetricsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{154} + return file_product_proto_rawDescGZIP(), []int{156} } func (x *ResolveCategoryCategoryMetricsRequest) GetContext() []*ResolveCategoryCategoryMetricsContext { @@ -7203,7 +7293,7 @@ type ResolveCategoryCategoryMetricsResult struct { func (x *ResolveCategoryCategoryMetricsResult) Reset() { *x = ResolveCategoryCategoryMetricsResult{} - mi := &file_product_proto_msgTypes[155] + mi := &file_product_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7215,7 +7305,7 @@ func (x *ResolveCategoryCategoryMetricsResult) String() string { func (*ResolveCategoryCategoryMetricsResult) ProtoMessage() {} func (x *ResolveCategoryCategoryMetricsResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[155] + mi := &file_product_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7228,7 +7318,7 @@ func (x *ResolveCategoryCategoryMetricsResult) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveCategoryCategoryMetricsResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryMetricsResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{155} + return file_product_proto_rawDescGZIP(), []int{157} } func (x *ResolveCategoryCategoryMetricsResult) GetCategoryMetrics() *CategoryMetrics { @@ -7247,7 +7337,7 @@ type ResolveCategoryCategoryMetricsResponse struct { func (x *ResolveCategoryCategoryMetricsResponse) Reset() { *x = ResolveCategoryCategoryMetricsResponse{} - mi := &file_product_proto_msgTypes[156] + mi := &file_product_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7259,7 +7349,7 @@ func (x *ResolveCategoryCategoryMetricsResponse) String() string { func (*ResolveCategoryCategoryMetricsResponse) ProtoMessage() {} func (x *ResolveCategoryCategoryMetricsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[156] + mi := &file_product_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7272,7 +7362,7 @@ func (x *ResolveCategoryCategoryMetricsResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ResolveCategoryCategoryMetricsResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryMetricsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{156} + return file_product_proto_rawDescGZIP(), []int{158} } func (x *ResolveCategoryCategoryMetricsResponse) GetResult() []*ResolveCategoryCategoryMetricsResult { @@ -7291,7 +7381,7 @@ type ResolveCategoryMascotArgs struct { func (x *ResolveCategoryMascotArgs) Reset() { *x = ResolveCategoryMascotArgs{} - mi := &file_product_proto_msgTypes[157] + mi := &file_product_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7303,7 +7393,7 @@ func (x *ResolveCategoryMascotArgs) String() string { func (*ResolveCategoryMascotArgs) ProtoMessage() {} func (x *ResolveCategoryMascotArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[157] + mi := &file_product_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7316,7 +7406,7 @@ func (x *ResolveCategoryMascotArgs) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveCategoryMascotArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryMascotArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{157} + return file_product_proto_rawDescGZIP(), []int{159} } func (x *ResolveCategoryMascotArgs) GetIncludeVolume() bool { @@ -7336,7 +7426,7 @@ type ResolveCategoryMascotContext struct { func (x *ResolveCategoryMascotContext) Reset() { *x = ResolveCategoryMascotContext{} - mi := &file_product_proto_msgTypes[158] + mi := &file_product_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7348,7 +7438,7 @@ func (x *ResolveCategoryMascotContext) String() string { func (*ResolveCategoryMascotContext) ProtoMessage() {} func (x *ResolveCategoryMascotContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[158] + mi := &file_product_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7361,7 +7451,7 @@ func (x *ResolveCategoryMascotContext) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveCategoryMascotContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryMascotContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{158} + return file_product_proto_rawDescGZIP(), []int{160} } func (x *ResolveCategoryMascotContext) GetId() string { @@ -7390,7 +7480,7 @@ type ResolveCategoryMascotRequest struct { func (x *ResolveCategoryMascotRequest) Reset() { *x = ResolveCategoryMascotRequest{} - mi := &file_product_proto_msgTypes[159] + mi := &file_product_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7402,7 +7492,7 @@ func (x *ResolveCategoryMascotRequest) String() string { func (*ResolveCategoryMascotRequest) ProtoMessage() {} func (x *ResolveCategoryMascotRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[159] + mi := &file_product_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7415,7 +7505,7 @@ func (x *ResolveCategoryMascotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveCategoryMascotRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryMascotRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{159} + return file_product_proto_rawDescGZIP(), []int{161} } func (x *ResolveCategoryMascotRequest) GetContext() []*ResolveCategoryMascotContext { @@ -7441,7 +7531,7 @@ type ResolveCategoryMascotResult struct { func (x *ResolveCategoryMascotResult) Reset() { *x = ResolveCategoryMascotResult{} - mi := &file_product_proto_msgTypes[160] + mi := &file_product_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7453,7 +7543,7 @@ func (x *ResolveCategoryMascotResult) String() string { func (*ResolveCategoryMascotResult) ProtoMessage() {} func (x *ResolveCategoryMascotResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[160] + mi := &file_product_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7466,7 +7556,7 @@ func (x *ResolveCategoryMascotResult) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveCategoryMascotResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryMascotResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{160} + return file_product_proto_rawDescGZIP(), []int{162} } func (x *ResolveCategoryMascotResult) GetMascot() *Animal { @@ -7485,7 +7575,7 @@ type ResolveCategoryMascotResponse struct { func (x *ResolveCategoryMascotResponse) Reset() { *x = ResolveCategoryMascotResponse{} - mi := &file_product_proto_msgTypes[161] + mi := &file_product_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7497,7 +7587,7 @@ func (x *ResolveCategoryMascotResponse) String() string { func (*ResolveCategoryMascotResponse) ProtoMessage() {} func (x *ResolveCategoryMascotResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[161] + mi := &file_product_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7510,7 +7600,7 @@ func (x *ResolveCategoryMascotResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveCategoryMascotResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryMascotResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{161} + return file_product_proto_rawDescGZIP(), []int{163} } func (x *ResolveCategoryMascotResponse) GetResult() []*ResolveCategoryMascotResult { @@ -7529,7 +7619,7 @@ type ResolveCategoryCategoryStatusArgs struct { func (x *ResolveCategoryCategoryStatusArgs) Reset() { *x = ResolveCategoryCategoryStatusArgs{} - mi := &file_product_proto_msgTypes[162] + mi := &file_product_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7541,7 +7631,7 @@ func (x *ResolveCategoryCategoryStatusArgs) String() string { func (*ResolveCategoryCategoryStatusArgs) ProtoMessage() {} func (x *ResolveCategoryCategoryStatusArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[162] + mi := &file_product_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7554,7 +7644,7 @@ func (x *ResolveCategoryCategoryStatusArgs) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryCategoryStatusArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryStatusArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{162} + return file_product_proto_rawDescGZIP(), []int{164} } func (x *ResolveCategoryCategoryStatusArgs) GetCheckHealth() bool { @@ -7574,7 +7664,7 @@ type ResolveCategoryCategoryStatusContext struct { func (x *ResolveCategoryCategoryStatusContext) Reset() { *x = ResolveCategoryCategoryStatusContext{} - mi := &file_product_proto_msgTypes[163] + mi := &file_product_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7586,7 +7676,7 @@ func (x *ResolveCategoryCategoryStatusContext) String() string { func (*ResolveCategoryCategoryStatusContext) ProtoMessage() {} func (x *ResolveCategoryCategoryStatusContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[163] + mi := &file_product_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7599,7 +7689,7 @@ func (x *ResolveCategoryCategoryStatusContext) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveCategoryCategoryStatusContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryStatusContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{163} + return file_product_proto_rawDescGZIP(), []int{165} } func (x *ResolveCategoryCategoryStatusContext) GetId() string { @@ -7628,7 +7718,7 @@ type ResolveCategoryCategoryStatusRequest struct { func (x *ResolveCategoryCategoryStatusRequest) Reset() { *x = ResolveCategoryCategoryStatusRequest{} - mi := &file_product_proto_msgTypes[164] + mi := &file_product_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7640,7 +7730,7 @@ func (x *ResolveCategoryCategoryStatusRequest) String() string { func (*ResolveCategoryCategoryStatusRequest) ProtoMessage() {} func (x *ResolveCategoryCategoryStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[164] + mi := &file_product_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7653,7 +7743,7 @@ func (x *ResolveCategoryCategoryStatusRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveCategoryCategoryStatusRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryStatusRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{164} + return file_product_proto_rawDescGZIP(), []int{166} } func (x *ResolveCategoryCategoryStatusRequest) GetContext() []*ResolveCategoryCategoryStatusContext { @@ -7679,7 +7769,7 @@ type ResolveCategoryCategoryStatusResult struct { func (x *ResolveCategoryCategoryStatusResult) Reset() { *x = ResolveCategoryCategoryStatusResult{} - mi := &file_product_proto_msgTypes[165] + mi := &file_product_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7691,7 +7781,7 @@ func (x *ResolveCategoryCategoryStatusResult) String() string { func (*ResolveCategoryCategoryStatusResult) ProtoMessage() {} func (x *ResolveCategoryCategoryStatusResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[165] + mi := &file_product_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7704,7 +7794,7 @@ func (x *ResolveCategoryCategoryStatusResult) ProtoReflect() protoreflect.Messag // Deprecated: Use ResolveCategoryCategoryStatusResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryStatusResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{165} + return file_product_proto_rawDescGZIP(), []int{167} } func (x *ResolveCategoryCategoryStatusResult) GetCategoryStatus() *ActionResult { @@ -7723,7 +7813,7 @@ type ResolveCategoryCategoryStatusResponse struct { func (x *ResolveCategoryCategoryStatusResponse) Reset() { *x = ResolveCategoryCategoryStatusResponse{} - mi := &file_product_proto_msgTypes[166] + mi := &file_product_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7735,7 +7825,7 @@ func (x *ResolveCategoryCategoryStatusResponse) String() string { func (*ResolveCategoryCategoryStatusResponse) ProtoMessage() {} func (x *ResolveCategoryCategoryStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[166] + mi := &file_product_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7748,7 +7838,7 @@ func (x *ResolveCategoryCategoryStatusResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryCategoryStatusResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryCategoryStatusResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{166} + return file_product_proto_rawDescGZIP(), []int{168} } func (x *ResolveCategoryCategoryStatusResponse) GetResult() []*ResolveCategoryCategoryStatusResult { @@ -7767,7 +7857,7 @@ type ResolveCategoryChildCategoriesArgs struct { func (x *ResolveCategoryChildCategoriesArgs) Reset() { *x = ResolveCategoryChildCategoriesArgs{} - mi := &file_product_proto_msgTypes[167] + mi := &file_product_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7779,7 +7869,7 @@ func (x *ResolveCategoryChildCategoriesArgs) String() string { func (*ResolveCategoryChildCategoriesArgs) ProtoMessage() {} func (x *ResolveCategoryChildCategoriesArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[167] + mi := &file_product_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7792,7 +7882,7 @@ func (x *ResolveCategoryChildCategoriesArgs) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveCategoryChildCategoriesArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryChildCategoriesArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{167} + return file_product_proto_rawDescGZIP(), []int{169} } func (x *ResolveCategoryChildCategoriesArgs) GetInclude() *wrapperspb.BoolValue { @@ -7812,7 +7902,7 @@ type ResolveCategoryChildCategoriesContext struct { func (x *ResolveCategoryChildCategoriesContext) Reset() { *x = ResolveCategoryChildCategoriesContext{} - mi := &file_product_proto_msgTypes[168] + mi := &file_product_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7824,7 +7914,7 @@ func (x *ResolveCategoryChildCategoriesContext) String() string { func (*ResolveCategoryChildCategoriesContext) ProtoMessage() {} func (x *ResolveCategoryChildCategoriesContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[168] + mi := &file_product_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7837,7 +7927,7 @@ func (x *ResolveCategoryChildCategoriesContext) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryChildCategoriesContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryChildCategoriesContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{168} + return file_product_proto_rawDescGZIP(), []int{170} } func (x *ResolveCategoryChildCategoriesContext) GetId() string { @@ -7866,7 +7956,7 @@ type ResolveCategoryChildCategoriesRequest struct { func (x *ResolveCategoryChildCategoriesRequest) Reset() { *x = ResolveCategoryChildCategoriesRequest{} - mi := &file_product_proto_msgTypes[169] + mi := &file_product_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7878,7 +7968,7 @@ func (x *ResolveCategoryChildCategoriesRequest) String() string { func (*ResolveCategoryChildCategoriesRequest) ProtoMessage() {} func (x *ResolveCategoryChildCategoriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[169] + mi := &file_product_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7891,7 +7981,7 @@ func (x *ResolveCategoryChildCategoriesRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryChildCategoriesRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryChildCategoriesRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{169} + return file_product_proto_rawDescGZIP(), []int{171} } func (x *ResolveCategoryChildCategoriesRequest) GetContext() []*ResolveCategoryChildCategoriesContext { @@ -7917,7 +8007,7 @@ type ResolveCategoryChildCategoriesResult struct { func (x *ResolveCategoryChildCategoriesResult) Reset() { *x = ResolveCategoryChildCategoriesResult{} - mi := &file_product_proto_msgTypes[170] + mi := &file_product_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7929,7 +8019,7 @@ func (x *ResolveCategoryChildCategoriesResult) String() string { func (*ResolveCategoryChildCategoriesResult) ProtoMessage() {} func (x *ResolveCategoryChildCategoriesResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[170] + mi := &file_product_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7942,7 +8032,7 @@ func (x *ResolveCategoryChildCategoriesResult) ProtoReflect() protoreflect.Messa // Deprecated: Use ResolveCategoryChildCategoriesResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryChildCategoriesResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{170} + return file_product_proto_rawDescGZIP(), []int{172} } func (x *ResolveCategoryChildCategoriesResult) GetChildCategories() []*Category { @@ -7961,7 +8051,7 @@ type ResolveCategoryChildCategoriesResponse struct { func (x *ResolveCategoryChildCategoriesResponse) Reset() { *x = ResolveCategoryChildCategoriesResponse{} - mi := &file_product_proto_msgTypes[171] + mi := &file_product_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7973,7 +8063,7 @@ func (x *ResolveCategoryChildCategoriesResponse) String() string { func (*ResolveCategoryChildCategoriesResponse) ProtoMessage() {} func (x *ResolveCategoryChildCategoriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[171] + mi := &file_product_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7986,7 +8076,7 @@ func (x *ResolveCategoryChildCategoriesResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ResolveCategoryChildCategoriesResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryChildCategoriesResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{171} + return file_product_proto_rawDescGZIP(), []int{173} } func (x *ResolveCategoryChildCategoriesResponse) GetResult() []*ResolveCategoryChildCategoriesResult { @@ -8005,7 +8095,7 @@ type ResolveCategoryOptionalCategoriesArgs struct { func (x *ResolveCategoryOptionalCategoriesArgs) Reset() { *x = ResolveCategoryOptionalCategoriesArgs{} - mi := &file_product_proto_msgTypes[172] + mi := &file_product_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8017,7 +8107,7 @@ func (x *ResolveCategoryOptionalCategoriesArgs) String() string { func (*ResolveCategoryOptionalCategoriesArgs) ProtoMessage() {} func (x *ResolveCategoryOptionalCategoriesArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[172] + mi := &file_product_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8030,7 +8120,7 @@ func (x *ResolveCategoryOptionalCategoriesArgs) ProtoReflect() protoreflect.Mess // Deprecated: Use ResolveCategoryOptionalCategoriesArgs.ProtoReflect.Descriptor instead. func (*ResolveCategoryOptionalCategoriesArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{172} + return file_product_proto_rawDescGZIP(), []int{174} } func (x *ResolveCategoryOptionalCategoriesArgs) GetInclude() *wrapperspb.BoolValue { @@ -8050,7 +8140,7 @@ type ResolveCategoryOptionalCategoriesContext struct { func (x *ResolveCategoryOptionalCategoriesContext) Reset() { *x = ResolveCategoryOptionalCategoriesContext{} - mi := &file_product_proto_msgTypes[173] + mi := &file_product_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8062,7 +8152,7 @@ func (x *ResolveCategoryOptionalCategoriesContext) String() string { func (*ResolveCategoryOptionalCategoriesContext) ProtoMessage() {} func (x *ResolveCategoryOptionalCategoriesContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[173] + mi := &file_product_proto_msgTypes[175] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8075,7 +8165,7 @@ func (x *ResolveCategoryOptionalCategoriesContext) ProtoReflect() protoreflect.M // Deprecated: Use ResolveCategoryOptionalCategoriesContext.ProtoReflect.Descriptor instead. func (*ResolveCategoryOptionalCategoriesContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{173} + return file_product_proto_rawDescGZIP(), []int{175} } func (x *ResolveCategoryOptionalCategoriesContext) GetId() string { @@ -8104,7 +8194,7 @@ type ResolveCategoryOptionalCategoriesRequest struct { func (x *ResolveCategoryOptionalCategoriesRequest) Reset() { *x = ResolveCategoryOptionalCategoriesRequest{} - mi := &file_product_proto_msgTypes[174] + mi := &file_product_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8116,7 +8206,7 @@ func (x *ResolveCategoryOptionalCategoriesRequest) String() string { func (*ResolveCategoryOptionalCategoriesRequest) ProtoMessage() {} func (x *ResolveCategoryOptionalCategoriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[174] + mi := &file_product_proto_msgTypes[176] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8129,7 +8219,7 @@ func (x *ResolveCategoryOptionalCategoriesRequest) ProtoReflect() protoreflect.M // Deprecated: Use ResolveCategoryOptionalCategoriesRequest.ProtoReflect.Descriptor instead. func (*ResolveCategoryOptionalCategoriesRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{174} + return file_product_proto_rawDescGZIP(), []int{176} } func (x *ResolveCategoryOptionalCategoriesRequest) GetContext() []*ResolveCategoryOptionalCategoriesContext { @@ -8155,7 +8245,7 @@ type ResolveCategoryOptionalCategoriesResult struct { func (x *ResolveCategoryOptionalCategoriesResult) Reset() { *x = ResolveCategoryOptionalCategoriesResult{} - mi := &file_product_proto_msgTypes[175] + mi := &file_product_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8167,7 +8257,7 @@ func (x *ResolveCategoryOptionalCategoriesResult) String() string { func (*ResolveCategoryOptionalCategoriesResult) ProtoMessage() {} func (x *ResolveCategoryOptionalCategoriesResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[175] + mi := &file_product_proto_msgTypes[177] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8180,7 +8270,7 @@ func (x *ResolveCategoryOptionalCategoriesResult) ProtoReflect() protoreflect.Me // Deprecated: Use ResolveCategoryOptionalCategoriesResult.ProtoReflect.Descriptor instead. func (*ResolveCategoryOptionalCategoriesResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{175} + return file_product_proto_rawDescGZIP(), []int{177} } func (x *ResolveCategoryOptionalCategoriesResult) GetOptionalCategories() *ListOfCategory { @@ -8199,7 +8289,7 @@ type ResolveCategoryOptionalCategoriesResponse struct { func (x *ResolveCategoryOptionalCategoriesResponse) Reset() { *x = ResolveCategoryOptionalCategoriesResponse{} - mi := &file_product_proto_msgTypes[176] + mi := &file_product_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8211,7 +8301,7 @@ func (x *ResolveCategoryOptionalCategoriesResponse) String() string { func (*ResolveCategoryOptionalCategoriesResponse) ProtoMessage() {} func (x *ResolveCategoryOptionalCategoriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[176] + mi := &file_product_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8224,7 +8314,7 @@ func (x *ResolveCategoryOptionalCategoriesResponse) ProtoReflect() protoreflect. // Deprecated: Use ResolveCategoryOptionalCategoriesResponse.ProtoReflect.Descriptor instead. func (*ResolveCategoryOptionalCategoriesResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{176} + return file_product_proto_rawDescGZIP(), []int{178} } func (x *ResolveCategoryOptionalCategoriesResponse) GetResult() []*ResolveCategoryOptionalCategoriesResult { @@ -8243,7 +8333,7 @@ type ResolveSubcategoryItemCountArgs struct { func (x *ResolveSubcategoryItemCountArgs) Reset() { *x = ResolveSubcategoryItemCountArgs{} - mi := &file_product_proto_msgTypes[177] + mi := &file_product_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8255,7 +8345,7 @@ func (x *ResolveSubcategoryItemCountArgs) String() string { func (*ResolveSubcategoryItemCountArgs) ProtoMessage() {} func (x *ResolveSubcategoryItemCountArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[177] + mi := &file_product_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8268,7 +8358,7 @@ func (x *ResolveSubcategoryItemCountArgs) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveSubcategoryItemCountArgs.ProtoReflect.Descriptor instead. func (*ResolveSubcategoryItemCountArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{177} + return file_product_proto_rawDescGZIP(), []int{179} } func (x *ResolveSubcategoryItemCountArgs) GetFilters() *SubcategoryItemFilter { @@ -8287,7 +8377,7 @@ type ResolveSubcategoryItemCountContext struct { func (x *ResolveSubcategoryItemCountContext) Reset() { *x = ResolveSubcategoryItemCountContext{} - mi := &file_product_proto_msgTypes[178] + mi := &file_product_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8299,7 +8389,7 @@ func (x *ResolveSubcategoryItemCountContext) String() string { func (*ResolveSubcategoryItemCountContext) ProtoMessage() {} func (x *ResolveSubcategoryItemCountContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[178] + mi := &file_product_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8312,7 +8402,7 @@ func (x *ResolveSubcategoryItemCountContext) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveSubcategoryItemCountContext.ProtoReflect.Descriptor instead. func (*ResolveSubcategoryItemCountContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{178} + return file_product_proto_rawDescGZIP(), []int{180} } func (x *ResolveSubcategoryItemCountContext) GetId() string { @@ -8334,7 +8424,7 @@ type ResolveSubcategoryItemCountRequest struct { func (x *ResolveSubcategoryItemCountRequest) Reset() { *x = ResolveSubcategoryItemCountRequest{} - mi := &file_product_proto_msgTypes[179] + mi := &file_product_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8346,7 +8436,7 @@ func (x *ResolveSubcategoryItemCountRequest) String() string { func (*ResolveSubcategoryItemCountRequest) ProtoMessage() {} func (x *ResolveSubcategoryItemCountRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[179] + mi := &file_product_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8359,7 +8449,7 @@ func (x *ResolveSubcategoryItemCountRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveSubcategoryItemCountRequest.ProtoReflect.Descriptor instead. func (*ResolveSubcategoryItemCountRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{179} + return file_product_proto_rawDescGZIP(), []int{181} } func (x *ResolveSubcategoryItemCountRequest) GetContext() []*ResolveSubcategoryItemCountContext { @@ -8385,7 +8475,7 @@ type ResolveSubcategoryItemCountResult struct { func (x *ResolveSubcategoryItemCountResult) Reset() { *x = ResolveSubcategoryItemCountResult{} - mi := &file_product_proto_msgTypes[180] + mi := &file_product_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8397,7 +8487,7 @@ func (x *ResolveSubcategoryItemCountResult) String() string { func (*ResolveSubcategoryItemCountResult) ProtoMessage() {} func (x *ResolveSubcategoryItemCountResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[180] + mi := &file_product_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8410,7 +8500,7 @@ func (x *ResolveSubcategoryItemCountResult) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveSubcategoryItemCountResult.ProtoReflect.Descriptor instead. func (*ResolveSubcategoryItemCountResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{180} + return file_product_proto_rawDescGZIP(), []int{182} } func (x *ResolveSubcategoryItemCountResult) GetItemCount() int32 { @@ -8429,7 +8519,7 @@ type ResolveSubcategoryItemCountResponse struct { func (x *ResolveSubcategoryItemCountResponse) Reset() { *x = ResolveSubcategoryItemCountResponse{} - mi := &file_product_proto_msgTypes[181] + mi := &file_product_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8441,7 +8531,7 @@ func (x *ResolveSubcategoryItemCountResponse) String() string { func (*ResolveSubcategoryItemCountResponse) ProtoMessage() {} func (x *ResolveSubcategoryItemCountResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[181] + mi := &file_product_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8454,7 +8544,7 @@ func (x *ResolveSubcategoryItemCountResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use ResolveSubcategoryItemCountResponse.ProtoReflect.Descriptor instead. func (*ResolveSubcategoryItemCountResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{181} + return file_product_proto_rawDescGZIP(), []int{183} } func (x *ResolveSubcategoryItemCountResponse) GetResult() []*ResolveSubcategoryItemCountResult { @@ -8464,28 +8554,72 @@ func (x *ResolveSubcategoryItemCountResponse) GetResult() []*ResolveSubcategoryI return nil } -type ResolveCategoryMetricsNormalizedScoreArgs struct { +type ResolveSubcategoryFeaturedCategoryArgs struct { + state protoimpl.MessageState `protogen:"open.v1"` + IncludeChildren bool `protobuf:"varint,1,opt,name=include_children,json=includeChildren,proto3" json:"include_children,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveSubcategoryFeaturedCategoryArgs) Reset() { + *x = ResolveSubcategoryFeaturedCategoryArgs{} + mi := &file_product_proto_msgTypes[184] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveSubcategoryFeaturedCategoryArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveSubcategoryFeaturedCategoryArgs) ProtoMessage() {} + +func (x *ResolveSubcategoryFeaturedCategoryArgs) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[184] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveSubcategoryFeaturedCategoryArgs.ProtoReflect.Descriptor instead. +func (*ResolveSubcategoryFeaturedCategoryArgs) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{184} +} + +func (x *ResolveSubcategoryFeaturedCategoryArgs) GetIncludeChildren() bool { + if x != nil { + return x.IncludeChildren + } + return false +} + +type ResolveSubcategoryFeaturedCategoryContext struct { state protoimpl.MessageState `protogen:"open.v1"` - Baseline float64 `protobuf:"fixed64,1,opt,name=baseline,proto3" json:"baseline,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ResolveCategoryMetricsNormalizedScoreArgs) Reset() { - *x = ResolveCategoryMetricsNormalizedScoreArgs{} - mi := &file_product_proto_msgTypes[182] +func (x *ResolveSubcategoryFeaturedCategoryContext) Reset() { + *x = ResolveSubcategoryFeaturedCategoryContext{} + mi := &file_product_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ResolveCategoryMetricsNormalizedScoreArgs) String() string { +func (x *ResolveSubcategoryFeaturedCategoryContext) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResolveCategoryMetricsNormalizedScoreArgs) ProtoMessage() {} +func (*ResolveSubcategoryFeaturedCategoryContext) ProtoMessage() {} -func (x *ResolveCategoryMetricsNormalizedScoreArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[182] +func (x *ResolveSubcategoryFeaturedCategoryContext) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[185] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8496,42 +8630,472 @@ func (x *ResolveCategoryMetricsNormalizedScoreArgs) ProtoReflect() protoreflect. return mi.MessageOf(x) } -// Deprecated: Use ResolveCategoryMetricsNormalizedScoreArgs.ProtoReflect.Descriptor instead. -func (*ResolveCategoryMetricsNormalizedScoreArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{182} +// Deprecated: Use ResolveSubcategoryFeaturedCategoryContext.ProtoReflect.Descriptor instead. +func (*ResolveSubcategoryFeaturedCategoryContext) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{185} } -func (x *ResolveCategoryMetricsNormalizedScoreArgs) GetBaseline() float64 { +func (x *ResolveSubcategoryFeaturedCategoryContext) GetId() string { if x != nil { - return x.Baseline + return x.Id } - return 0 + return "" } -type ResolveCategoryMetricsNormalizedScoreContext struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - MetricType string `protobuf:"bytes,2,opt,name=metric_type,json=metricType,proto3" json:"metric_type,omitempty"` - Value float64 `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"` +type ResolveSubcategoryFeaturedCategoryRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // context provides the resolver context for the field featuredCategory of type Subcategory. + Context []*ResolveSubcategoryFeaturedCategoryContext `protobuf:"bytes,1,rep,name=context,proto3" json:"context,omitempty"` + // field_args provides the arguments for the resolver field featuredCategory of type Subcategory. + FieldArgs *ResolveSubcategoryFeaturedCategoryArgs `protobuf:"bytes,2,opt,name=field_args,json=fieldArgs,proto3" json:"field_args,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ResolveCategoryMetricsNormalizedScoreContext) Reset() { - *x = ResolveCategoryMetricsNormalizedScoreContext{} - mi := &file_product_proto_msgTypes[183] +func (x *ResolveSubcategoryFeaturedCategoryRequest) Reset() { + *x = ResolveSubcategoryFeaturedCategoryRequest{} + mi := &file_product_proto_msgTypes[186] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveSubcategoryFeaturedCategoryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveSubcategoryFeaturedCategoryRequest) ProtoMessage() {} + +func (x *ResolveSubcategoryFeaturedCategoryRequest) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[186] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveSubcategoryFeaturedCategoryRequest.ProtoReflect.Descriptor instead. +func (*ResolveSubcategoryFeaturedCategoryRequest) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{186} +} + +func (x *ResolveSubcategoryFeaturedCategoryRequest) GetContext() []*ResolveSubcategoryFeaturedCategoryContext { + if x != nil { + return x.Context + } + return nil +} + +func (x *ResolveSubcategoryFeaturedCategoryRequest) GetFieldArgs() *ResolveSubcategoryFeaturedCategoryArgs { + if x != nil { + return x.FieldArgs + } + return nil +} + +type ResolveSubcategoryFeaturedCategoryResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + FeaturedCategory *Category `protobuf:"bytes,1,opt,name=featured_category,json=featuredCategory,proto3" json:"featured_category,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveSubcategoryFeaturedCategoryResult) Reset() { + *x = ResolveSubcategoryFeaturedCategoryResult{} + mi := &file_product_proto_msgTypes[187] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveSubcategoryFeaturedCategoryResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveSubcategoryFeaturedCategoryResult) ProtoMessage() {} + +func (x *ResolveSubcategoryFeaturedCategoryResult) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[187] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveSubcategoryFeaturedCategoryResult.ProtoReflect.Descriptor instead. +func (*ResolveSubcategoryFeaturedCategoryResult) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{187} +} + +func (x *ResolveSubcategoryFeaturedCategoryResult) GetFeaturedCategory() *Category { + if x != nil { + return x.FeaturedCategory + } + return nil +} + +type ResolveSubcategoryFeaturedCategoryResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Result []*ResolveSubcategoryFeaturedCategoryResult `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveSubcategoryFeaturedCategoryResponse) Reset() { + *x = ResolveSubcategoryFeaturedCategoryResponse{} + mi := &file_product_proto_msgTypes[188] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveSubcategoryFeaturedCategoryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveSubcategoryFeaturedCategoryResponse) ProtoMessage() {} + +func (x *ResolveSubcategoryFeaturedCategoryResponse) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[188] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveSubcategoryFeaturedCategoryResponse.ProtoReflect.Descriptor instead. +func (*ResolveSubcategoryFeaturedCategoryResponse) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{188} +} + +func (x *ResolveSubcategoryFeaturedCategoryResponse) GetResult() []*ResolveSubcategoryFeaturedCategoryResult { + if x != nil { + return x.Result + } + return nil +} + +type ResolveCategoryMetricsNormalizedScoreArgs struct { + state protoimpl.MessageState `protogen:"open.v1"` + Baseline float64 `protobuf:"fixed64,1,opt,name=baseline,proto3" json:"baseline,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsNormalizedScoreArgs) Reset() { + *x = ResolveCategoryMetricsNormalizedScoreArgs{} + mi := &file_product_proto_msgTypes[189] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveCategoryMetricsNormalizedScoreArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveCategoryMetricsNormalizedScoreArgs) ProtoMessage() {} + +func (x *ResolveCategoryMetricsNormalizedScoreArgs) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[189] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveCategoryMetricsNormalizedScoreArgs.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsNormalizedScoreArgs) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{189} +} + +func (x *ResolveCategoryMetricsNormalizedScoreArgs) GetBaseline() float64 { + if x != nil { + return x.Baseline + } + return 0 +} + +type ResolveCategoryMetricsNormalizedScoreContext struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + MetricType string `protobuf:"bytes,2,opt,name=metric_type,json=metricType,proto3" json:"metric_type,omitempty"` + Value float64 `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsNormalizedScoreContext) Reset() { + *x = ResolveCategoryMetricsNormalizedScoreContext{} + mi := &file_product_proto_msgTypes[190] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveCategoryMetricsNormalizedScoreContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveCategoryMetricsNormalizedScoreContext) ProtoMessage() {} + +func (x *ResolveCategoryMetricsNormalizedScoreContext) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[190] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveCategoryMetricsNormalizedScoreContext.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsNormalizedScoreContext) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{190} +} + +func (x *ResolveCategoryMetricsNormalizedScoreContext) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ResolveCategoryMetricsNormalizedScoreContext) GetMetricType() string { + if x != nil { + return x.MetricType + } + return "" +} + +func (x *ResolveCategoryMetricsNormalizedScoreContext) GetValue() float64 { + if x != nil { + return x.Value + } + return 0 +} + +type ResolveCategoryMetricsNormalizedScoreRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // context provides the resolver context for the field normalizedScore of type CategoryMetrics. + Context []*ResolveCategoryMetricsNormalizedScoreContext `protobuf:"bytes,1,rep,name=context,proto3" json:"context,omitempty"` + // field_args provides the arguments for the resolver field normalizedScore of type CategoryMetrics. + FieldArgs *ResolveCategoryMetricsNormalizedScoreArgs `protobuf:"bytes,2,opt,name=field_args,json=fieldArgs,proto3" json:"field_args,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsNormalizedScoreRequest) Reset() { + *x = ResolveCategoryMetricsNormalizedScoreRequest{} + mi := &file_product_proto_msgTypes[191] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveCategoryMetricsNormalizedScoreRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveCategoryMetricsNormalizedScoreRequest) ProtoMessage() {} + +func (x *ResolveCategoryMetricsNormalizedScoreRequest) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[191] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveCategoryMetricsNormalizedScoreRequest.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsNormalizedScoreRequest) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{191} +} + +func (x *ResolveCategoryMetricsNormalizedScoreRequest) GetContext() []*ResolveCategoryMetricsNormalizedScoreContext { + if x != nil { + return x.Context + } + return nil +} + +func (x *ResolveCategoryMetricsNormalizedScoreRequest) GetFieldArgs() *ResolveCategoryMetricsNormalizedScoreArgs { + if x != nil { + return x.FieldArgs + } + return nil +} + +type ResolveCategoryMetricsNormalizedScoreResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + NormalizedScore float64 `protobuf:"fixed64,1,opt,name=normalized_score,json=normalizedScore,proto3" json:"normalized_score,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsNormalizedScoreResult) Reset() { + *x = ResolveCategoryMetricsNormalizedScoreResult{} + mi := &file_product_proto_msgTypes[192] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveCategoryMetricsNormalizedScoreResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveCategoryMetricsNormalizedScoreResult) ProtoMessage() {} + +func (x *ResolveCategoryMetricsNormalizedScoreResult) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[192] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveCategoryMetricsNormalizedScoreResult.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsNormalizedScoreResult) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{192} +} + +func (x *ResolveCategoryMetricsNormalizedScoreResult) GetNormalizedScore() float64 { + if x != nil { + return x.NormalizedScore + } + return 0 +} + +type ResolveCategoryMetricsNormalizedScoreResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Result []*ResolveCategoryMetricsNormalizedScoreResult `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsNormalizedScoreResponse) Reset() { + *x = ResolveCategoryMetricsNormalizedScoreResponse{} + mi := &file_product_proto_msgTypes[193] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveCategoryMetricsNormalizedScoreResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveCategoryMetricsNormalizedScoreResponse) ProtoMessage() {} + +func (x *ResolveCategoryMetricsNormalizedScoreResponse) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[193] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveCategoryMetricsNormalizedScoreResponse.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsNormalizedScoreResponse) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{193} +} + +func (x *ResolveCategoryMetricsNormalizedScoreResponse) GetResult() []*ResolveCategoryMetricsNormalizedScoreResult { + if x != nil { + return x.Result + } + return nil +} + +type ResolveCategoryMetricsRelatedCategoryArgs struct { + state protoimpl.MessageState `protogen:"open.v1"` + Include *wrapperspb.BoolValue `protobuf:"bytes,1,opt,name=include,proto3" json:"include,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsRelatedCategoryArgs) Reset() { + *x = ResolveCategoryMetricsRelatedCategoryArgs{} + mi := &file_product_proto_msgTypes[194] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResolveCategoryMetricsRelatedCategoryArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveCategoryMetricsRelatedCategoryArgs) ProtoMessage() {} + +func (x *ResolveCategoryMetricsRelatedCategoryArgs) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[194] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveCategoryMetricsRelatedCategoryArgs.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsRelatedCategoryArgs) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{194} +} + +func (x *ResolveCategoryMetricsRelatedCategoryArgs) GetInclude() *wrapperspb.BoolValue { + if x != nil { + return x.Include + } + return nil +} + +type ResolveCategoryMetricsRelatedCategoryContext struct { + state protoimpl.MessageState `protogen:"open.v1"` + CategoryId string `protobuf:"bytes,1,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResolveCategoryMetricsRelatedCategoryContext) Reset() { + *x = ResolveCategoryMetricsRelatedCategoryContext{} + mi := &file_product_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ResolveCategoryMetricsNormalizedScoreContext) String() string { +func (x *ResolveCategoryMetricsRelatedCategoryContext) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResolveCategoryMetricsNormalizedScoreContext) ProtoMessage() {} +func (*ResolveCategoryMetricsRelatedCategoryContext) ProtoMessage() {} -func (x *ResolveCategoryMetricsNormalizedScoreContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[183] +func (x *ResolveCategoryMetricsRelatedCategoryContext) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[195] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8542,57 +9106,43 @@ func (x *ResolveCategoryMetricsNormalizedScoreContext) ProtoReflect() protorefle return mi.MessageOf(x) } -// Deprecated: Use ResolveCategoryMetricsNormalizedScoreContext.ProtoReflect.Descriptor instead. -func (*ResolveCategoryMetricsNormalizedScoreContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{183} -} - -func (x *ResolveCategoryMetricsNormalizedScoreContext) GetId() string { - if x != nil { - return x.Id - } - return "" +// Deprecated: Use ResolveCategoryMetricsRelatedCategoryContext.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsRelatedCategoryContext) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{195} } -func (x *ResolveCategoryMetricsNormalizedScoreContext) GetMetricType() string { +func (x *ResolveCategoryMetricsRelatedCategoryContext) GetCategoryId() string { if x != nil { - return x.MetricType + return x.CategoryId } return "" } -func (x *ResolveCategoryMetricsNormalizedScoreContext) GetValue() float64 { - if x != nil { - return x.Value - } - return 0 -} - -type ResolveCategoryMetricsNormalizedScoreRequest struct { +type ResolveCategoryMetricsRelatedCategoryRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - // context provides the resolver context for the field normalizedScore of type CategoryMetrics. - Context []*ResolveCategoryMetricsNormalizedScoreContext `protobuf:"bytes,1,rep,name=context,proto3" json:"context,omitempty"` - // field_args provides the arguments for the resolver field normalizedScore of type CategoryMetrics. - FieldArgs *ResolveCategoryMetricsNormalizedScoreArgs `protobuf:"bytes,2,opt,name=field_args,json=fieldArgs,proto3" json:"field_args,omitempty"` + // context provides the resolver context for the field relatedCategory of type CategoryMetrics. + Context []*ResolveCategoryMetricsRelatedCategoryContext `protobuf:"bytes,1,rep,name=context,proto3" json:"context,omitempty"` + // field_args provides the arguments for the resolver field relatedCategory of type CategoryMetrics. + FieldArgs *ResolveCategoryMetricsRelatedCategoryArgs `protobuf:"bytes,2,opt,name=field_args,json=fieldArgs,proto3" json:"field_args,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ResolveCategoryMetricsNormalizedScoreRequest) Reset() { - *x = ResolveCategoryMetricsNormalizedScoreRequest{} - mi := &file_product_proto_msgTypes[184] +func (x *ResolveCategoryMetricsRelatedCategoryRequest) Reset() { + *x = ResolveCategoryMetricsRelatedCategoryRequest{} + mi := &file_product_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ResolveCategoryMetricsNormalizedScoreRequest) String() string { +func (x *ResolveCategoryMetricsRelatedCategoryRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResolveCategoryMetricsNormalizedScoreRequest) ProtoMessage() {} +func (*ResolveCategoryMetricsRelatedCategoryRequest) ProtoMessage() {} -func (x *ResolveCategoryMetricsNormalizedScoreRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[184] +func (x *ResolveCategoryMetricsRelatedCategoryRequest) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[196] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8603,47 +9153,47 @@ func (x *ResolveCategoryMetricsNormalizedScoreRequest) ProtoReflect() protorefle return mi.MessageOf(x) } -// Deprecated: Use ResolveCategoryMetricsNormalizedScoreRequest.ProtoReflect.Descriptor instead. -func (*ResolveCategoryMetricsNormalizedScoreRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{184} +// Deprecated: Use ResolveCategoryMetricsRelatedCategoryRequest.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsRelatedCategoryRequest) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{196} } -func (x *ResolveCategoryMetricsNormalizedScoreRequest) GetContext() []*ResolveCategoryMetricsNormalizedScoreContext { +func (x *ResolveCategoryMetricsRelatedCategoryRequest) GetContext() []*ResolveCategoryMetricsRelatedCategoryContext { if x != nil { return x.Context } return nil } -func (x *ResolveCategoryMetricsNormalizedScoreRequest) GetFieldArgs() *ResolveCategoryMetricsNormalizedScoreArgs { +func (x *ResolveCategoryMetricsRelatedCategoryRequest) GetFieldArgs() *ResolveCategoryMetricsRelatedCategoryArgs { if x != nil { return x.FieldArgs } return nil } -type ResolveCategoryMetricsNormalizedScoreResult struct { +type ResolveCategoryMetricsRelatedCategoryResult struct { state protoimpl.MessageState `protogen:"open.v1"` - NormalizedScore float64 `protobuf:"fixed64,1,opt,name=normalized_score,json=normalizedScore,proto3" json:"normalized_score,omitempty"` + RelatedCategory *Category `protobuf:"bytes,1,opt,name=related_category,json=relatedCategory,proto3" json:"related_category,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ResolveCategoryMetricsNormalizedScoreResult) Reset() { - *x = ResolveCategoryMetricsNormalizedScoreResult{} - mi := &file_product_proto_msgTypes[185] +func (x *ResolveCategoryMetricsRelatedCategoryResult) Reset() { + *x = ResolveCategoryMetricsRelatedCategoryResult{} + mi := &file_product_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ResolveCategoryMetricsNormalizedScoreResult) String() string { +func (x *ResolveCategoryMetricsRelatedCategoryResult) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResolveCategoryMetricsNormalizedScoreResult) ProtoMessage() {} +func (*ResolveCategoryMetricsRelatedCategoryResult) ProtoMessage() {} -func (x *ResolveCategoryMetricsNormalizedScoreResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[185] +func (x *ResolveCategoryMetricsRelatedCategoryResult) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[197] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8654,40 +9204,40 @@ func (x *ResolveCategoryMetricsNormalizedScoreResult) ProtoReflect() protoreflec return mi.MessageOf(x) } -// Deprecated: Use ResolveCategoryMetricsNormalizedScoreResult.ProtoReflect.Descriptor instead. -func (*ResolveCategoryMetricsNormalizedScoreResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{185} +// Deprecated: Use ResolveCategoryMetricsRelatedCategoryResult.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsRelatedCategoryResult) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{197} } -func (x *ResolveCategoryMetricsNormalizedScoreResult) GetNormalizedScore() float64 { +func (x *ResolveCategoryMetricsRelatedCategoryResult) GetRelatedCategory() *Category { if x != nil { - return x.NormalizedScore + return x.RelatedCategory } - return 0 + return nil } -type ResolveCategoryMetricsNormalizedScoreResponse struct { +type ResolveCategoryMetricsRelatedCategoryResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Result []*ResolveCategoryMetricsNormalizedScoreResult `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` + Result []*ResolveCategoryMetricsRelatedCategoryResult `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ResolveCategoryMetricsNormalizedScoreResponse) Reset() { - *x = ResolveCategoryMetricsNormalizedScoreResponse{} - mi := &file_product_proto_msgTypes[186] +func (x *ResolveCategoryMetricsRelatedCategoryResponse) Reset() { + *x = ResolveCategoryMetricsRelatedCategoryResponse{} + mi := &file_product_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ResolveCategoryMetricsNormalizedScoreResponse) String() string { +func (x *ResolveCategoryMetricsRelatedCategoryResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResolveCategoryMetricsNormalizedScoreResponse) ProtoMessage() {} +func (*ResolveCategoryMetricsRelatedCategoryResponse) ProtoMessage() {} -func (x *ResolveCategoryMetricsNormalizedScoreResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[186] +func (x *ResolveCategoryMetricsRelatedCategoryResponse) ProtoReflect() protoreflect.Message { + mi := &file_product_proto_msgTypes[198] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8698,12 +9248,12 @@ func (x *ResolveCategoryMetricsNormalizedScoreResponse) ProtoReflect() protorefl return mi.MessageOf(x) } -// Deprecated: Use ResolveCategoryMetricsNormalizedScoreResponse.ProtoReflect.Descriptor instead. -func (*ResolveCategoryMetricsNormalizedScoreResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{186} +// Deprecated: Use ResolveCategoryMetricsRelatedCategoryResponse.ProtoReflect.Descriptor instead. +func (*ResolveCategoryMetricsRelatedCategoryResponse) Descriptor() ([]byte, []int) { + return file_product_proto_rawDescGZIP(), []int{198} } -func (x *ResolveCategoryMetricsNormalizedScoreResponse) GetResult() []*ResolveCategoryMetricsNormalizedScoreResult { +func (x *ResolveCategoryMetricsRelatedCategoryResponse) GetResult() []*ResolveCategoryMetricsRelatedCategoryResult { if x != nil { return x.Result } @@ -8719,7 +9269,7 @@ type ResolveTestContainerDetailsArgs struct { func (x *ResolveTestContainerDetailsArgs) Reset() { *x = ResolveTestContainerDetailsArgs{} - mi := &file_product_proto_msgTypes[187] + mi := &file_product_proto_msgTypes[199] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8731,7 +9281,7 @@ func (x *ResolveTestContainerDetailsArgs) String() string { func (*ResolveTestContainerDetailsArgs) ProtoMessage() {} func (x *ResolveTestContainerDetailsArgs) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[187] + mi := &file_product_proto_msgTypes[199] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8744,7 +9294,7 @@ func (x *ResolveTestContainerDetailsArgs) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveTestContainerDetailsArgs.ProtoReflect.Descriptor instead. func (*ResolveTestContainerDetailsArgs) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{187} + return file_product_proto_rawDescGZIP(), []int{199} } func (x *ResolveTestContainerDetailsArgs) GetIncludeExtended() bool { @@ -8764,7 +9314,7 @@ type ResolveTestContainerDetailsContext struct { func (x *ResolveTestContainerDetailsContext) Reset() { *x = ResolveTestContainerDetailsContext{} - mi := &file_product_proto_msgTypes[188] + mi := &file_product_proto_msgTypes[200] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8776,7 +9326,7 @@ func (x *ResolveTestContainerDetailsContext) String() string { func (*ResolveTestContainerDetailsContext) ProtoMessage() {} func (x *ResolveTestContainerDetailsContext) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[188] + mi := &file_product_proto_msgTypes[200] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8789,7 +9339,7 @@ func (x *ResolveTestContainerDetailsContext) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveTestContainerDetailsContext.ProtoReflect.Descriptor instead. func (*ResolveTestContainerDetailsContext) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{188} + return file_product_proto_rawDescGZIP(), []int{200} } func (x *ResolveTestContainerDetailsContext) GetId() string { @@ -8818,7 +9368,7 @@ type ResolveTestContainerDetailsRequest struct { func (x *ResolveTestContainerDetailsRequest) Reset() { *x = ResolveTestContainerDetailsRequest{} - mi := &file_product_proto_msgTypes[189] + mi := &file_product_proto_msgTypes[201] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8830,7 +9380,7 @@ func (x *ResolveTestContainerDetailsRequest) String() string { func (*ResolveTestContainerDetailsRequest) ProtoMessage() {} func (x *ResolveTestContainerDetailsRequest) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[189] + mi := &file_product_proto_msgTypes[201] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8843,7 +9393,7 @@ func (x *ResolveTestContainerDetailsRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveTestContainerDetailsRequest.ProtoReflect.Descriptor instead. func (*ResolveTestContainerDetailsRequest) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{189} + return file_product_proto_rawDescGZIP(), []int{201} } func (x *ResolveTestContainerDetailsRequest) GetContext() []*ResolveTestContainerDetailsContext { @@ -8869,7 +9419,7 @@ type ResolveTestContainerDetailsResult struct { func (x *ResolveTestContainerDetailsResult) Reset() { *x = ResolveTestContainerDetailsResult{} - mi := &file_product_proto_msgTypes[190] + mi := &file_product_proto_msgTypes[202] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8881,7 +9431,7 @@ func (x *ResolveTestContainerDetailsResult) String() string { func (*ResolveTestContainerDetailsResult) ProtoMessage() {} func (x *ResolveTestContainerDetailsResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[190] + mi := &file_product_proto_msgTypes[202] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8894,7 +9444,7 @@ func (x *ResolveTestContainerDetailsResult) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveTestContainerDetailsResult.ProtoReflect.Descriptor instead. func (*ResolveTestContainerDetailsResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{190} + return file_product_proto_rawDescGZIP(), []int{202} } func (x *ResolveTestContainerDetailsResult) GetDetails() *TestDetails { @@ -8913,7 +9463,7 @@ type ResolveTestContainerDetailsResponse struct { func (x *ResolveTestContainerDetailsResponse) Reset() { *x = ResolveTestContainerDetailsResponse{} - mi := &file_product_proto_msgTypes[191] + mi := &file_product_proto_msgTypes[203] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8925,7 +9475,7 @@ func (x *ResolveTestContainerDetailsResponse) String() string { func (*ResolveTestContainerDetailsResponse) ProtoMessage() {} func (x *ResolveTestContainerDetailsResponse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[191] + mi := &file_product_proto_msgTypes[203] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8938,7 +9488,7 @@ func (x *ResolveTestContainerDetailsResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use ResolveTestContainerDetailsResponse.ProtoReflect.Descriptor instead. func (*ResolveTestContainerDetailsResponse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{191} + return file_product_proto_rawDescGZIP(), []int{203} } func (x *ResolveTestContainerDetailsResponse) GetResult() []*ResolveTestContainerDetailsResult { @@ -8959,7 +9509,7 @@ type Product struct { func (x *Product) Reset() { *x = Product{} - mi := &file_product_proto_msgTypes[192] + mi := &file_product_proto_msgTypes[204] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8971,7 +9521,7 @@ func (x *Product) String() string { func (*Product) ProtoMessage() {} func (x *Product) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[192] + mi := &file_product_proto_msgTypes[204] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8984,7 +9534,7 @@ func (x *Product) ProtoReflect() protoreflect.Message { // Deprecated: Use Product.ProtoReflect.Descriptor instead. func (*Product) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{192} + return file_product_proto_rawDescGZIP(), []int{204} } func (x *Product) GetId() string { @@ -9019,7 +9569,7 @@ type Storage struct { func (x *Storage) Reset() { *x = Storage{} - mi := &file_product_proto_msgTypes[193] + mi := &file_product_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9031,7 +9581,7 @@ func (x *Storage) String() string { func (*Storage) ProtoMessage() {} func (x *Storage) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[193] + mi := &file_product_proto_msgTypes[205] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9044,7 +9594,7 @@ func (x *Storage) ProtoReflect() protoreflect.Message { // Deprecated: Use Storage.ProtoReflect.Descriptor instead. func (*Storage) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{193} + return file_product_proto_rawDescGZIP(), []int{205} } func (x *Storage) GetId() string { @@ -9079,7 +9629,7 @@ type Warehouse struct { func (x *Warehouse) Reset() { *x = Warehouse{} - mi := &file_product_proto_msgTypes[194] + mi := &file_product_proto_msgTypes[206] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9091,7 +9641,7 @@ func (x *Warehouse) String() string { func (*Warehouse) ProtoMessage() {} func (x *Warehouse) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[194] + mi := &file_product_proto_msgTypes[206] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9104,7 +9654,7 @@ func (x *Warehouse) ProtoReflect() protoreflect.Message { // Deprecated: Use Warehouse.ProtoReflect.Descriptor instead. func (*Warehouse) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{194} + return file_product_proto_rawDescGZIP(), []int{206} } func (x *Warehouse) GetId() string { @@ -9138,7 +9688,7 @@ type User struct { func (x *User) Reset() { *x = User{} - mi := &file_product_proto_msgTypes[195] + mi := &file_product_proto_msgTypes[207] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9150,7 +9700,7 @@ func (x *User) String() string { func (*User) ProtoMessage() {} func (x *User) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[195] + mi := &file_product_proto_msgTypes[207] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9163,7 +9713,7 @@ func (x *User) ProtoReflect() protoreflect.Message { // Deprecated: Use User.ProtoReflect.Descriptor instead. func (*User) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{195} + return file_product_proto_rawDescGZIP(), []int{207} } func (x *User) GetId() string { @@ -9191,7 +9741,7 @@ type NestedTypeA struct { func (x *NestedTypeA) Reset() { *x = NestedTypeA{} - mi := &file_product_proto_msgTypes[196] + mi := &file_product_proto_msgTypes[208] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9203,7 +9753,7 @@ func (x *NestedTypeA) String() string { func (*NestedTypeA) ProtoMessage() {} func (x *NestedTypeA) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[196] + mi := &file_product_proto_msgTypes[208] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9216,7 +9766,7 @@ func (x *NestedTypeA) ProtoReflect() protoreflect.Message { // Deprecated: Use NestedTypeA.ProtoReflect.Descriptor instead. func (*NestedTypeA) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{196} + return file_product_proto_rawDescGZIP(), []int{208} } func (x *NestedTypeA) GetId() string { @@ -9251,7 +9801,7 @@ type RecursiveType struct { func (x *RecursiveType) Reset() { *x = RecursiveType{} - mi := &file_product_proto_msgTypes[197] + mi := &file_product_proto_msgTypes[209] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9263,7 +9813,7 @@ func (x *RecursiveType) String() string { func (*RecursiveType) ProtoMessage() {} func (x *RecursiveType) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[197] + mi := &file_product_proto_msgTypes[209] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9276,7 +9826,7 @@ func (x *RecursiveType) ProtoReflect() protoreflect.Message { // Deprecated: Use RecursiveType.ProtoReflect.Descriptor instead. func (*RecursiveType) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{197} + return file_product_proto_rawDescGZIP(), []int{209} } func (x *RecursiveType) GetId() string { @@ -9312,7 +9862,7 @@ type TypeWithMultipleFilterFields struct { func (x *TypeWithMultipleFilterFields) Reset() { *x = TypeWithMultipleFilterFields{} - mi := &file_product_proto_msgTypes[198] + mi := &file_product_proto_msgTypes[210] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9324,7 +9874,7 @@ func (x *TypeWithMultipleFilterFields) String() string { func (*TypeWithMultipleFilterFields) ProtoMessage() {} func (x *TypeWithMultipleFilterFields) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[198] + mi := &file_product_proto_msgTypes[210] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9337,7 +9887,7 @@ func (x *TypeWithMultipleFilterFields) ProtoReflect() protoreflect.Message { // Deprecated: Use TypeWithMultipleFilterFields.ProtoReflect.Descriptor instead. func (*TypeWithMultipleFilterFields) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{198} + return file_product_proto_rawDescGZIP(), []int{210} } func (x *TypeWithMultipleFilterFields) GetId() string { @@ -9378,7 +9928,7 @@ type FilterTypeInput struct { func (x *FilterTypeInput) Reset() { *x = FilterTypeInput{} - mi := &file_product_proto_msgTypes[199] + mi := &file_product_proto_msgTypes[211] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9390,7 +9940,7 @@ func (x *FilterTypeInput) String() string { func (*FilterTypeInput) ProtoMessage() {} func (x *FilterTypeInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[199] + mi := &file_product_proto_msgTypes[211] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9403,7 +9953,7 @@ func (x *FilterTypeInput) ProtoReflect() protoreflect.Message { // Deprecated: Use FilterTypeInput.ProtoReflect.Descriptor instead. func (*FilterTypeInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{199} + return file_product_proto_rawDescGZIP(), []int{211} } func (x *FilterTypeInput) GetFilterField_1() string { @@ -9429,7 +9979,7 @@ type ComplexFilterTypeInput struct { func (x *ComplexFilterTypeInput) Reset() { *x = ComplexFilterTypeInput{} - mi := &file_product_proto_msgTypes[200] + mi := &file_product_proto_msgTypes[212] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9441,7 +9991,7 @@ func (x *ComplexFilterTypeInput) String() string { func (*ComplexFilterTypeInput) ProtoMessage() {} func (x *ComplexFilterTypeInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[200] + mi := &file_product_proto_msgTypes[212] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9454,7 +10004,7 @@ func (x *ComplexFilterTypeInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ComplexFilterTypeInput.ProtoReflect.Descriptor instead. func (*ComplexFilterTypeInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{200} + return file_product_proto_rawDescGZIP(), []int{212} } func (x *ComplexFilterTypeInput) GetFilter() *FilterType { @@ -9474,7 +10024,7 @@ type TypeWithComplexFilterInput struct { func (x *TypeWithComplexFilterInput) Reset() { *x = TypeWithComplexFilterInput{} - mi := &file_product_proto_msgTypes[201] + mi := &file_product_proto_msgTypes[213] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9486,7 +10036,7 @@ func (x *TypeWithComplexFilterInput) String() string { func (*TypeWithComplexFilterInput) ProtoMessage() {} func (x *TypeWithComplexFilterInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[201] + mi := &file_product_proto_msgTypes[213] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9499,7 +10049,7 @@ func (x *TypeWithComplexFilterInput) ProtoReflect() protoreflect.Message { // Deprecated: Use TypeWithComplexFilterInput.ProtoReflect.Descriptor instead. func (*TypeWithComplexFilterInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{201} + return file_product_proto_rawDescGZIP(), []int{213} } func (x *TypeWithComplexFilterInput) GetId() string { @@ -9527,7 +10077,7 @@ type OrderInput struct { func (x *OrderInput) Reset() { *x = OrderInput{} - mi := &file_product_proto_msgTypes[202] + mi := &file_product_proto_msgTypes[214] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9539,7 +10089,7 @@ func (x *OrderInput) String() string { func (*OrderInput) ProtoMessage() {} func (x *OrderInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[202] + mi := &file_product_proto_msgTypes[214] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9552,7 +10102,7 @@ func (x *OrderInput) ProtoReflect() protoreflect.Message { // Deprecated: Use OrderInput.ProtoReflect.Descriptor instead. func (*OrderInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{202} + return file_product_proto_rawDescGZIP(), []int{214} } func (x *OrderInput) GetOrderId() string { @@ -9588,7 +10138,7 @@ type Order struct { func (x *Order) Reset() { *x = Order{} - mi := &file_product_proto_msgTypes[203] + mi := &file_product_proto_msgTypes[215] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9600,7 +10150,7 @@ func (x *Order) String() string { func (*Order) ProtoMessage() {} func (x *Order) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[203] + mi := &file_product_proto_msgTypes[215] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9613,7 +10163,7 @@ func (x *Order) ProtoReflect() protoreflect.Message { // Deprecated: Use Order.ProtoReflect.Descriptor instead. func (*Order) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{203} + return file_product_proto_rawDescGZIP(), []int{215} } func (x *Order) GetOrderId() string { @@ -9649,14 +10199,15 @@ type Category struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Kind CategoryKind `protobuf:"varint,3,opt,name=kind,proto3,enum=productv1.CategoryKind" json:"kind,omitempty"` - Subcategories *ListOfSubcategory `protobuf:"bytes,5,opt,name=subcategories,proto3" json:"subcategories,omitempty"` + Subcategories *ListOfSubcategory `protobuf:"bytes,4,opt,name=subcategories,proto3" json:"subcategories,omitempty"` + NullMetrics *CategoryMetrics `protobuf:"bytes,5,opt,name=null_metrics,json=nullMetrics,proto3" json:"null_metrics,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *Category) Reset() { *x = Category{} - mi := &file_product_proto_msgTypes[204] + mi := &file_product_proto_msgTypes[216] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9668,7 +10219,7 @@ func (x *Category) String() string { func (*Category) ProtoMessage() {} func (x *Category) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[204] + mi := &file_product_proto_msgTypes[216] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9681,7 +10232,7 @@ func (x *Category) ProtoReflect() protoreflect.Message { // Deprecated: Use Category.ProtoReflect.Descriptor instead. func (*Category) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{204} + return file_product_proto_rawDescGZIP(), []int{216} } func (x *Category) GetId() string { @@ -9712,6 +10263,13 @@ func (x *Category) GetSubcategories() *ListOfSubcategory { return nil } +func (x *Category) GetNullMetrics() *CategoryMetrics { + if x != nil { + return x.NullMetrics + } + return nil +} + type CategoryFilter struct { state protoimpl.MessageState `protogen:"open.v1"` Category CategoryKind `protobuf:"varint,1,opt,name=category,proto3,enum=productv1.CategoryKind" json:"category,omitempty"` @@ -9722,7 +10280,7 @@ type CategoryFilter struct { func (x *CategoryFilter) Reset() { *x = CategoryFilter{} - mi := &file_product_proto_msgTypes[205] + mi := &file_product_proto_msgTypes[217] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9734,7 +10292,7 @@ func (x *CategoryFilter) String() string { func (*CategoryFilter) ProtoMessage() {} func (x *CategoryFilter) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[205] + mi := &file_product_proto_msgTypes[217] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9747,7 +10305,7 @@ func (x *CategoryFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use CategoryFilter.ProtoReflect.Descriptor instead. func (*CategoryFilter) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{205} + return file_product_proto_rawDescGZIP(), []int{217} } func (x *CategoryFilter) GetCategory() CategoryKind { @@ -9777,7 +10335,7 @@ type Animal struct { func (x *Animal) Reset() { *x = Animal{} - mi := &file_product_proto_msgTypes[206] + mi := &file_product_proto_msgTypes[218] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9789,7 +10347,7 @@ func (x *Animal) String() string { func (*Animal) ProtoMessage() {} func (x *Animal) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[206] + mi := &file_product_proto_msgTypes[218] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9802,7 +10360,7 @@ func (x *Animal) ProtoReflect() protoreflect.Message { // Deprecated: Use Animal.ProtoReflect.Descriptor instead. func (*Animal) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{206} + return file_product_proto_rawDescGZIP(), []int{218} } func (x *Animal) GetInstance() isAnimal_Instance { @@ -9856,7 +10414,7 @@ type SearchInput struct { func (x *SearchInput) Reset() { *x = SearchInput{} - mi := &file_product_proto_msgTypes[207] + mi := &file_product_proto_msgTypes[219] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9868,7 +10426,7 @@ func (x *SearchInput) String() string { func (*SearchInput) ProtoMessage() {} func (x *SearchInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[207] + mi := &file_product_proto_msgTypes[219] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9881,7 +10439,7 @@ func (x *SearchInput) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchInput.ProtoReflect.Descriptor instead. func (*SearchInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{207} + return file_product_proto_rawDescGZIP(), []int{219} } func (x *SearchInput) GetQuery() string { @@ -9912,7 +10470,7 @@ type SearchResult struct { func (x *SearchResult) Reset() { *x = SearchResult{} - mi := &file_product_proto_msgTypes[208] + mi := &file_product_proto_msgTypes[220] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9924,7 +10482,7 @@ func (x *SearchResult) String() string { func (*SearchResult) ProtoMessage() {} func (x *SearchResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[208] + mi := &file_product_proto_msgTypes[220] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9937,7 +10495,7 @@ func (x *SearchResult) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchResult.ProtoReflect.Descriptor instead. func (*SearchResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{208} + return file_product_proto_rawDescGZIP(), []int{220} } func (x *SearchResult) GetValue() isSearchResult_Value { @@ -10012,7 +10570,7 @@ type NullableFieldsType struct { func (x *NullableFieldsType) Reset() { *x = NullableFieldsType{} - mi := &file_product_proto_msgTypes[209] + mi := &file_product_proto_msgTypes[221] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10024,7 +10582,7 @@ func (x *NullableFieldsType) String() string { func (*NullableFieldsType) ProtoMessage() {} func (x *NullableFieldsType) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[209] + mi := &file_product_proto_msgTypes[221] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10037,7 +10595,7 @@ func (x *NullableFieldsType) ProtoReflect() protoreflect.Message { // Deprecated: Use NullableFieldsType.ProtoReflect.Descriptor instead. func (*NullableFieldsType) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{209} + return file_product_proto_rawDescGZIP(), []int{221} } func (x *NullableFieldsType) GetId() string { @@ -10107,7 +10665,7 @@ type NullableFieldsFilter struct { func (x *NullableFieldsFilter) Reset() { *x = NullableFieldsFilter{} - mi := &file_product_proto_msgTypes[210] + mi := &file_product_proto_msgTypes[222] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10119,7 +10677,7 @@ func (x *NullableFieldsFilter) String() string { func (*NullableFieldsFilter) ProtoMessage() {} func (x *NullableFieldsFilter) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[210] + mi := &file_product_proto_msgTypes[222] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10132,7 +10690,7 @@ func (x *NullableFieldsFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use NullableFieldsFilter.ProtoReflect.Descriptor instead. func (*NullableFieldsFilter) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{210} + return file_product_proto_rawDescGZIP(), []int{222} } func (x *NullableFieldsFilter) GetName() *wrapperspb.StringValue { @@ -10184,7 +10742,7 @@ type BlogPost struct { func (x *BlogPost) Reset() { *x = BlogPost{} - mi := &file_product_proto_msgTypes[211] + mi := &file_product_proto_msgTypes[223] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10196,7 +10754,7 @@ func (x *BlogPost) String() string { func (*BlogPost) ProtoMessage() {} func (x *BlogPost) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[211] + mi := &file_product_proto_msgTypes[223] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10209,7 +10767,7 @@ func (x *BlogPost) ProtoReflect() protoreflect.Message { // Deprecated: Use BlogPost.ProtoReflect.Descriptor instead. func (*BlogPost) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{211} + return file_product_proto_rawDescGZIP(), []int{223} } func (x *BlogPost) GetId() string { @@ -10363,7 +10921,7 @@ type BlogPostFilter struct { func (x *BlogPostFilter) Reset() { *x = BlogPostFilter{} - mi := &file_product_proto_msgTypes[212] + mi := &file_product_proto_msgTypes[224] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10375,7 +10933,7 @@ func (x *BlogPostFilter) String() string { func (*BlogPostFilter) ProtoMessage() {} func (x *BlogPostFilter) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[212] + mi := &file_product_proto_msgTypes[224] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10388,7 +10946,7 @@ func (x *BlogPostFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use BlogPostFilter.ProtoReflect.Descriptor instead. func (*BlogPostFilter) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{212} + return file_product_proto_rawDescGZIP(), []int{224} } func (x *BlogPostFilter) GetTitle() *wrapperspb.StringValue { @@ -10435,7 +10993,7 @@ type Author struct { func (x *Author) Reset() { *x = Author{} - mi := &file_product_proto_msgTypes[213] + mi := &file_product_proto_msgTypes[225] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10447,7 +11005,7 @@ func (x *Author) String() string { func (*Author) ProtoMessage() {} func (x *Author) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[213] + mi := &file_product_proto_msgTypes[225] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10460,7 +11018,7 @@ func (x *Author) ProtoReflect() protoreflect.Message { // Deprecated: Use Author.ProtoReflect.Descriptor instead. func (*Author) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{213} + return file_product_proto_rawDescGZIP(), []int{225} } func (x *Author) GetId() string { @@ -10579,7 +11137,7 @@ type AuthorFilter struct { func (x *AuthorFilter) Reset() { *x = AuthorFilter{} - mi := &file_product_proto_msgTypes[214] + mi := &file_product_proto_msgTypes[226] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10591,7 +11149,7 @@ func (x *AuthorFilter) String() string { func (*AuthorFilter) ProtoMessage() {} func (x *AuthorFilter) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[214] + mi := &file_product_proto_msgTypes[226] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10604,7 +11162,7 @@ func (x *AuthorFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthorFilter.ProtoReflect.Descriptor instead. func (*AuthorFilter) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{214} + return file_product_proto_rawDescGZIP(), []int{226} } func (x *AuthorFilter) GetName() *wrapperspb.StringValue { @@ -10639,7 +11197,7 @@ type TestContainer struct { func (x *TestContainer) Reset() { *x = TestContainer{} - mi := &file_product_proto_msgTypes[215] + mi := &file_product_proto_msgTypes[227] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10651,7 +11209,7 @@ func (x *TestContainer) String() string { func (*TestContainer) ProtoMessage() {} func (x *TestContainer) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[215] + mi := &file_product_proto_msgTypes[227] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10664,7 +11222,7 @@ func (x *TestContainer) ProtoReflect() protoreflect.Message { // Deprecated: Use TestContainer.ProtoReflect.Descriptor instead. func (*TestContainer) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{215} + return file_product_proto_rawDescGZIP(), []int{227} } func (x *TestContainer) GetId() string { @@ -10697,7 +11255,7 @@ type UserInput struct { func (x *UserInput) Reset() { *x = UserInput{} - mi := &file_product_proto_msgTypes[216] + mi := &file_product_proto_msgTypes[228] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10709,7 +11267,7 @@ func (x *UserInput) String() string { func (*UserInput) ProtoMessage() {} func (x *UserInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[216] + mi := &file_product_proto_msgTypes[228] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10722,7 +11280,7 @@ func (x *UserInput) ProtoReflect() protoreflect.Message { // Deprecated: Use UserInput.ProtoReflect.Descriptor instead. func (*UserInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{216} + return file_product_proto_rawDescGZIP(), []int{228} } func (x *UserInput) GetName() string { @@ -10742,7 +11300,7 @@ type ActionInput struct { func (x *ActionInput) Reset() { *x = ActionInput{} - mi := &file_product_proto_msgTypes[217] + mi := &file_product_proto_msgTypes[229] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10754,7 +11312,7 @@ func (x *ActionInput) String() string { func (*ActionInput) ProtoMessage() {} func (x *ActionInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[217] + mi := &file_product_proto_msgTypes[229] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10767,7 +11325,7 @@ func (x *ActionInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ActionInput.ProtoReflect.Descriptor instead. func (*ActionInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{217} + return file_product_proto_rawDescGZIP(), []int{229} } func (x *ActionInput) GetType() string { @@ -10797,7 +11355,7 @@ type ActionResult struct { func (x *ActionResult) Reset() { *x = ActionResult{} - mi := &file_product_proto_msgTypes[218] + mi := &file_product_proto_msgTypes[230] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10809,7 +11367,7 @@ func (x *ActionResult) String() string { func (*ActionResult) ProtoMessage() {} func (x *ActionResult) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[218] + mi := &file_product_proto_msgTypes[230] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10822,7 +11380,7 @@ func (x *ActionResult) ProtoReflect() protoreflect.Message { // Deprecated: Use ActionResult.ProtoReflect.Descriptor instead. func (*ActionResult) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{218} + return file_product_proto_rawDescGZIP(), []int{230} } func (x *ActionResult) GetValue() isActionResult_Value { @@ -10881,7 +11439,7 @@ type NullableFieldsInput struct { func (x *NullableFieldsInput) Reset() { *x = NullableFieldsInput{} - mi := &file_product_proto_msgTypes[219] + mi := &file_product_proto_msgTypes[231] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10893,7 +11451,7 @@ func (x *NullableFieldsInput) String() string { func (*NullableFieldsInput) ProtoMessage() {} func (x *NullableFieldsInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[219] + mi := &file_product_proto_msgTypes[231] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10906,7 +11464,7 @@ func (x *NullableFieldsInput) ProtoReflect() protoreflect.Message { // Deprecated: Use NullableFieldsInput.ProtoReflect.Descriptor instead. func (*NullableFieldsInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{219} + return file_product_proto_rawDescGZIP(), []int{231} } func (x *NullableFieldsInput) GetName() string { @@ -10982,7 +11540,7 @@ type BlogPostInput struct { func (x *BlogPostInput) Reset() { *x = BlogPostInput{} - mi := &file_product_proto_msgTypes[220] + mi := &file_product_proto_msgTypes[232] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10994,7 +11552,7 @@ func (x *BlogPostInput) String() string { func (*BlogPostInput) ProtoMessage() {} func (x *BlogPostInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[220] + mi := &file_product_proto_msgTypes[232] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11007,7 +11565,7 @@ func (x *BlogPostInput) ProtoReflect() protoreflect.Message { // Deprecated: Use BlogPostInput.ProtoReflect.Descriptor instead. func (*BlogPostInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{220} + return file_product_proto_rawDescGZIP(), []int{232} } func (x *BlogPostInput) GetTitle() string { @@ -11140,7 +11698,7 @@ type AuthorInput struct { func (x *AuthorInput) Reset() { *x = AuthorInput{} - mi := &file_product_proto_msgTypes[221] + mi := &file_product_proto_msgTypes[233] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11152,7 +11710,7 @@ func (x *AuthorInput) String() string { func (*AuthorInput) ProtoMessage() {} func (x *AuthorInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[221] + mi := &file_product_proto_msgTypes[233] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11165,7 +11723,7 @@ func (x *AuthorInput) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthorInput.ProtoReflect.Descriptor instead. func (*AuthorInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{221} + return file_product_proto_rawDescGZIP(), []int{233} } func (x *AuthorInput) GetName() string { @@ -11250,7 +11808,7 @@ type ProductDetails struct { func (x *ProductDetails) Reset() { *x = ProductDetails{} - mi := &file_product_proto_msgTypes[222] + mi := &file_product_proto_msgTypes[234] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11262,7 +11820,7 @@ func (x *ProductDetails) String() string { func (*ProductDetails) ProtoMessage() {} func (x *ProductDetails) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[222] + mi := &file_product_proto_msgTypes[234] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11275,7 +11833,7 @@ func (x *ProductDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use ProductDetails.ProtoReflect.Descriptor instead. func (*ProductDetails) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{222} + return file_product_proto_rawDescGZIP(), []int{234} } func (x *ProductDetails) GetId() string { @@ -11317,7 +11875,7 @@ type NestedTypeB struct { func (x *NestedTypeB) Reset() { *x = NestedTypeB{} - mi := &file_product_proto_msgTypes[223] + mi := &file_product_proto_msgTypes[235] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11329,7 +11887,7 @@ func (x *NestedTypeB) String() string { func (*NestedTypeB) ProtoMessage() {} func (x *NestedTypeB) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[223] + mi := &file_product_proto_msgTypes[235] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11342,7 +11900,7 @@ func (x *NestedTypeB) ProtoReflect() protoreflect.Message { // Deprecated: Use NestedTypeB.ProtoReflect.Descriptor instead. func (*NestedTypeB) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{223} + return file_product_proto_rawDescGZIP(), []int{235} } func (x *NestedTypeB) GetId() string { @@ -11376,7 +11934,7 @@ type NestedTypeC struct { func (x *NestedTypeC) Reset() { *x = NestedTypeC{} - mi := &file_product_proto_msgTypes[224] + mi := &file_product_proto_msgTypes[236] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11388,7 +11946,7 @@ func (x *NestedTypeC) String() string { func (*NestedTypeC) ProtoMessage() {} func (x *NestedTypeC) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[224] + mi := &file_product_proto_msgTypes[236] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11401,7 +11959,7 @@ func (x *NestedTypeC) ProtoReflect() protoreflect.Message { // Deprecated: Use NestedTypeC.ProtoReflect.Descriptor instead. func (*NestedTypeC) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{224} + return file_product_proto_rawDescGZIP(), []int{236} } func (x *NestedTypeC) GetId() string { @@ -11430,7 +11988,7 @@ type FilterType struct { func (x *FilterType) Reset() { *x = FilterType{} - mi := &file_product_proto_msgTypes[225] + mi := &file_product_proto_msgTypes[237] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11442,7 +12000,7 @@ func (x *FilterType) String() string { func (*FilterType) ProtoMessage() {} func (x *FilterType) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[225] + mi := &file_product_proto_msgTypes[237] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11455,7 +12013,7 @@ func (x *FilterType) ProtoReflect() protoreflect.Message { // Deprecated: Use FilterType.ProtoReflect.Descriptor instead. func (*FilterType) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{225} + return file_product_proto_rawDescGZIP(), []int{237} } func (x *FilterType) GetName() string { @@ -11496,7 +12054,7 @@ type Pagination struct { func (x *Pagination) Reset() { *x = Pagination{} - mi := &file_product_proto_msgTypes[226] + mi := &file_product_proto_msgTypes[238] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11508,7 +12066,7 @@ func (x *Pagination) String() string { func (*Pagination) ProtoMessage() {} func (x *Pagination) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[226] + mi := &file_product_proto_msgTypes[238] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11521,7 +12079,7 @@ func (x *Pagination) ProtoReflect() protoreflect.Message { // Deprecated: Use Pagination.ProtoReflect.Descriptor instead. func (*Pagination) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{226} + return file_product_proto_rawDescGZIP(), []int{238} } func (x *Pagination) GetPage() int32 { @@ -11549,7 +12107,7 @@ type OrderLineInput struct { func (x *OrderLineInput) Reset() { *x = OrderLineInput{} - mi := &file_product_proto_msgTypes[227] + mi := &file_product_proto_msgTypes[239] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11561,7 +12119,7 @@ func (x *OrderLineInput) String() string { func (*OrderLineInput) ProtoMessage() {} func (x *OrderLineInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[227] + mi := &file_product_proto_msgTypes[239] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11574,7 +12132,7 @@ func (x *OrderLineInput) ProtoReflect() protoreflect.Message { // Deprecated: Use OrderLineInput.ProtoReflect.Descriptor instead. func (*OrderLineInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{227} + return file_product_proto_rawDescGZIP(), []int{239} } func (x *OrderLineInput) GetProductId() string { @@ -11609,7 +12167,7 @@ type OrderLine struct { func (x *OrderLine) Reset() { *x = OrderLine{} - mi := &file_product_proto_msgTypes[228] + mi := &file_product_proto_msgTypes[240] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11621,7 +12179,7 @@ func (x *OrderLine) String() string { func (*OrderLine) ProtoMessage() {} func (x *OrderLine) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[228] + mi := &file_product_proto_msgTypes[240] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11634,7 +12192,7 @@ func (x *OrderLine) ProtoReflect() protoreflect.Message { // Deprecated: Use OrderLine.ProtoReflect.Descriptor instead. func (*OrderLine) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{228} + return file_product_proto_rawDescGZIP(), []int{240} } func (x *OrderLine) GetProductId() string { @@ -11670,7 +12228,7 @@ type Subcategory struct { func (x *Subcategory) Reset() { *x = Subcategory{} - mi := &file_product_proto_msgTypes[229] + mi := &file_product_proto_msgTypes[241] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11682,7 +12240,7 @@ func (x *Subcategory) String() string { func (*Subcategory) ProtoMessage() {} func (x *Subcategory) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[229] + mi := &file_product_proto_msgTypes[241] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11695,7 +12253,7 @@ func (x *Subcategory) ProtoReflect() protoreflect.Message { // Deprecated: Use Subcategory.ProtoReflect.Descriptor instead. func (*Subcategory) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{229} + return file_product_proto_rawDescGZIP(), []int{241} } func (x *Subcategory) GetId() string { @@ -11727,20 +12285,19 @@ func (x *Subcategory) GetIsActive() bool { } type CategoryMetrics struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - MetricType string `protobuf:"bytes,2,opt,name=metric_type,json=metricType,proto3" json:"metric_type,omitempty"` - Value float64 `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"` - Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - CategoryId string `protobuf:"bytes,5,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"` - RelatedCategory *Category `protobuf:"bytes,6,opt,name=related_category,json=relatedCategory,proto3" json:"related_category,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + MetricType string `protobuf:"bytes,2,opt,name=metric_type,json=metricType,proto3" json:"metric_type,omitempty"` + Value float64 `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"` + Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + CategoryId string `protobuf:"bytes,5,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CategoryMetrics) Reset() { *x = CategoryMetrics{} - mi := &file_product_proto_msgTypes[230] + mi := &file_product_proto_msgTypes[242] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11752,7 +12309,7 @@ func (x *CategoryMetrics) String() string { func (*CategoryMetrics) ProtoMessage() {} func (x *CategoryMetrics) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[230] + mi := &file_product_proto_msgTypes[242] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11765,7 +12322,7 @@ func (x *CategoryMetrics) ProtoReflect() protoreflect.Message { // Deprecated: Use CategoryMetrics.ProtoReflect.Descriptor instead. func (*CategoryMetrics) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{230} + return file_product_proto_rawDescGZIP(), []int{242} } func (x *CategoryMetrics) GetId() string { @@ -11803,13 +12360,6 @@ func (x *CategoryMetrics) GetCategoryId() string { return "" } -func (x *CategoryMetrics) GetRelatedCategory() *Category { - if x != nil { - return x.RelatedCategory - } - return nil -} - type Cat struct { state protoimpl.MessageState `protogen:"open.v1"` Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` @@ -11824,7 +12374,7 @@ type Cat struct { func (x *Cat) Reset() { *x = Cat{} - mi := &file_product_proto_msgTypes[231] + mi := &file_product_proto_msgTypes[243] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11836,7 +12386,7 @@ func (x *Cat) String() string { func (*Cat) ProtoMessage() {} func (x *Cat) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[231] + mi := &file_product_proto_msgTypes[243] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11849,7 +12399,7 @@ func (x *Cat) ProtoReflect() protoreflect.Message { // Deprecated: Use Cat.ProtoReflect.Descriptor instead. func (*Cat) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{231} + return file_product_proto_rawDescGZIP(), []int{243} } func (x *Cat) GetId() string { @@ -11908,7 +12458,7 @@ type Dog struct { func (x *Dog) Reset() { *x = Dog{} - mi := &file_product_proto_msgTypes[232] + mi := &file_product_proto_msgTypes[244] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11920,7 +12470,7 @@ func (x *Dog) String() string { func (*Dog) ProtoMessage() {} func (x *Dog) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[232] + mi := &file_product_proto_msgTypes[244] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11933,7 +12483,7 @@ func (x *Dog) ProtoReflect() protoreflect.Message { // Deprecated: Use Dog.ProtoReflect.Descriptor instead. func (*Dog) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{232} + return file_product_proto_rawDescGZIP(), []int{244} } func (x *Dog) GetId() string { @@ -11983,13 +12533,14 @@ type Owner struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Contact *ContactInfo `protobuf:"bytes,3,opt,name=contact,proto3" json:"contact,omitempty"` + Pet *Animal `protobuf:"bytes,4,opt,name=pet,proto3" json:"pet,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *Owner) Reset() { *x = Owner{} - mi := &file_product_proto_msgTypes[233] + mi := &file_product_proto_msgTypes[245] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12001,7 +12552,7 @@ func (x *Owner) String() string { func (*Owner) ProtoMessage() {} func (x *Owner) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[233] + mi := &file_product_proto_msgTypes[245] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12014,7 +12565,7 @@ func (x *Owner) ProtoReflect() protoreflect.Message { // Deprecated: Use Owner.ProtoReflect.Descriptor instead. func (*Owner) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{233} + return file_product_proto_rawDescGZIP(), []int{245} } func (x *Owner) GetId() string { @@ -12038,6 +12589,13 @@ func (x *Owner) GetContact() *ContactInfo { return nil } +func (x *Owner) GetPet() *Animal { + if x != nil { + return x.Pet + } + return nil +} + type ContactInfo struct { state protoimpl.MessageState `protogen:"open.v1"` Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"` @@ -12049,7 +12607,7 @@ type ContactInfo struct { func (x *ContactInfo) Reset() { *x = ContactInfo{} - mi := &file_product_proto_msgTypes[234] + mi := &file_product_proto_msgTypes[246] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12061,7 +12619,7 @@ func (x *ContactInfo) String() string { func (*ContactInfo) ProtoMessage() {} func (x *ContactInfo) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[234] + mi := &file_product_proto_msgTypes[246] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12074,7 +12632,7 @@ func (x *ContactInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ContactInfo.ProtoReflect.Descriptor instead. func (*ContactInfo) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{234} + return file_product_proto_rawDescGZIP(), []int{246} } func (x *ContactInfo) GetEmail() string { @@ -12110,7 +12668,7 @@ type Address struct { func (x *Address) Reset() { *x = Address{} - mi := &file_product_proto_msgTypes[235] + mi := &file_product_proto_msgTypes[247] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12122,7 +12680,7 @@ func (x *Address) String() string { func (*Address) ProtoMessage() {} func (x *Address) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[235] + mi := &file_product_proto_msgTypes[247] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12135,7 +12693,7 @@ func (x *Address) ProtoReflect() protoreflect.Message { // Deprecated: Use Address.ProtoReflect.Descriptor instead. func (*Address) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{235} + return file_product_proto_rawDescGZIP(), []int{247} } func (x *Address) GetStreet() string { @@ -12178,7 +12736,7 @@ type CatBreed struct { func (x *CatBreed) Reset() { *x = CatBreed{} - mi := &file_product_proto_msgTypes[236] + mi := &file_product_proto_msgTypes[248] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12190,7 +12748,7 @@ func (x *CatBreed) String() string { func (*CatBreed) ProtoMessage() {} func (x *CatBreed) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[236] + mi := &file_product_proto_msgTypes[248] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12203,7 +12761,7 @@ func (x *CatBreed) ProtoReflect() protoreflect.Message { // Deprecated: Use CatBreed.ProtoReflect.Descriptor instead. func (*CatBreed) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{236} + return file_product_proto_rawDescGZIP(), []int{248} } func (x *CatBreed) GetId() string { @@ -12246,7 +12804,7 @@ type DogBreed struct { func (x *DogBreed) Reset() { *x = DogBreed{} - mi := &file_product_proto_msgTypes[237] + mi := &file_product_proto_msgTypes[249] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12258,7 +12816,7 @@ func (x *DogBreed) String() string { func (*DogBreed) ProtoMessage() {} func (x *DogBreed) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[237] + mi := &file_product_proto_msgTypes[249] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12271,7 +12829,7 @@ func (x *DogBreed) ProtoReflect() protoreflect.Message { // Deprecated: Use DogBreed.ProtoReflect.Descriptor instead. func (*DogBreed) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{237} + return file_product_proto_rawDescGZIP(), []int{249} } func (x *DogBreed) GetId() string { @@ -12313,7 +12871,7 @@ type BreedCharacteristics struct { func (x *BreedCharacteristics) Reset() { *x = BreedCharacteristics{} - mi := &file_product_proto_msgTypes[238] + mi := &file_product_proto_msgTypes[250] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12325,7 +12883,7 @@ func (x *BreedCharacteristics) String() string { func (*BreedCharacteristics) ProtoMessage() {} func (x *BreedCharacteristics) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[238] + mi := &file_product_proto_msgTypes[250] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12338,7 +12896,7 @@ func (x *BreedCharacteristics) ProtoReflect() protoreflect.Message { // Deprecated: Use BreedCharacteristics.ProtoReflect.Descriptor instead. func (*BreedCharacteristics) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{238} + return file_product_proto_rawDescGZIP(), []int{250} } func (x *BreedCharacteristics) GetSize() string { @@ -12372,7 +12930,7 @@ type ActionSuccess struct { func (x *ActionSuccess) Reset() { *x = ActionSuccess{} - mi := &file_product_proto_msgTypes[239] + mi := &file_product_proto_msgTypes[251] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12384,7 +12942,7 @@ func (x *ActionSuccess) String() string { func (*ActionSuccess) ProtoMessage() {} func (x *ActionSuccess) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[239] + mi := &file_product_proto_msgTypes[251] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12397,7 +12955,7 @@ func (x *ActionSuccess) ProtoReflect() protoreflect.Message { // Deprecated: Use ActionSuccess.ProtoReflect.Descriptor instead. func (*ActionSuccess) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{239} + return file_product_proto_rawDescGZIP(), []int{251} } func (x *ActionSuccess) GetMessage() string { @@ -12424,7 +12982,7 @@ type ActionError struct { func (x *ActionError) Reset() { *x = ActionError{} - mi := &file_product_proto_msgTypes[240] + mi := &file_product_proto_msgTypes[252] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12436,7 +12994,7 @@ func (x *ActionError) String() string { func (*ActionError) ProtoMessage() {} func (x *ActionError) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[240] + mi := &file_product_proto_msgTypes[252] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12449,7 +13007,7 @@ func (x *ActionError) ProtoReflect() protoreflect.Message { // Deprecated: Use ActionError.ProtoReflect.Descriptor instead. func (*ActionError) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{240} + return file_product_proto_rawDescGZIP(), []int{252} } func (x *ActionError) GetMessage() string { @@ -12478,7 +13036,7 @@ type TestDetails struct { func (x *TestDetails) Reset() { *x = TestDetails{} - mi := &file_product_proto_msgTypes[241] + mi := &file_product_proto_msgTypes[253] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12490,7 +13048,7 @@ func (x *TestDetails) String() string { func (*TestDetails) ProtoMessage() {} func (x *TestDetails) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[241] + mi := &file_product_proto_msgTypes[253] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12503,7 +13061,7 @@ func (x *TestDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use TestDetails.ProtoReflect.Descriptor instead. func (*TestDetails) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{241} + return file_product_proto_rawDescGZIP(), []int{253} } func (x *TestDetails) GetId() string { @@ -12544,7 +13102,7 @@ type CategoryInput struct { func (x *CategoryInput) Reset() { *x = CategoryInput{} - mi := &file_product_proto_msgTypes[242] + mi := &file_product_proto_msgTypes[254] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12556,7 +13114,7 @@ func (x *CategoryInput) String() string { func (*CategoryInput) ProtoMessage() {} func (x *CategoryInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[242] + mi := &file_product_proto_msgTypes[254] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12569,7 +13127,7 @@ func (x *CategoryInput) ProtoReflect() protoreflect.Message { // Deprecated: Use CategoryInput.ProtoReflect.Descriptor instead. func (*CategoryInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{242} + return file_product_proto_rawDescGZIP(), []int{254} } func (x *CategoryInput) GetName() string { @@ -12598,7 +13156,7 @@ type ProductCountFilter struct { func (x *ProductCountFilter) Reset() { *x = ProductCountFilter{} - mi := &file_product_proto_msgTypes[243] + mi := &file_product_proto_msgTypes[255] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12610,7 +13168,7 @@ func (x *ProductCountFilter) String() string { func (*ProductCountFilter) ProtoMessage() {} func (x *ProductCountFilter) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[243] + mi := &file_product_proto_msgTypes[255] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12623,7 +13181,7 @@ func (x *ProductCountFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use ProductCountFilter.ProtoReflect.Descriptor instead. func (*ProductCountFilter) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{243} + return file_product_proto_rawDescGZIP(), []int{255} } func (x *ProductCountFilter) GetMinPrice() *wrapperspb.DoubleValue { @@ -12667,7 +13225,7 @@ type SubcategoryItemFilter struct { func (x *SubcategoryItemFilter) Reset() { *x = SubcategoryItemFilter{} - mi := &file_product_proto_msgTypes[244] + mi := &file_product_proto_msgTypes[256] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12679,7 +13237,7 @@ func (x *SubcategoryItemFilter) String() string { func (*SubcategoryItemFilter) ProtoMessage() {} func (x *SubcategoryItemFilter) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[244] + mi := &file_product_proto_msgTypes[256] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12692,7 +13250,7 @@ func (x *SubcategoryItemFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use SubcategoryItemFilter.ProtoReflect.Descriptor instead. func (*SubcategoryItemFilter) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{244} + return file_product_proto_rawDescGZIP(), []int{256} } func (x *SubcategoryItemFilter) GetMinPrice() *wrapperspb.DoubleValue { @@ -12741,7 +13299,7 @@ type ShippingEstimateInput struct { func (x *ShippingEstimateInput) Reset() { *x = ShippingEstimateInput{} - mi := &file_product_proto_msgTypes[245] + mi := &file_product_proto_msgTypes[257] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12753,7 +13311,7 @@ func (x *ShippingEstimateInput) String() string { func (*ShippingEstimateInput) ProtoMessage() {} func (x *ShippingEstimateInput) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[245] + mi := &file_product_proto_msgTypes[257] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12766,7 +13324,7 @@ func (x *ShippingEstimateInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ShippingEstimateInput.ProtoReflect.Descriptor instead. func (*ShippingEstimateInput) Descriptor() ([]byte, []int) { - return file_product_proto_rawDescGZIP(), []int{245} + return file_product_proto_rawDescGZIP(), []int{257} } func (x *ShippingEstimateInput) GetDestination() ShippingDestination { @@ -12799,7 +13357,7 @@ type ListOfAuthorFilter_List struct { func (x *ListOfAuthorFilter_List) Reset() { *x = ListOfAuthorFilter_List{} - mi := &file_product_proto_msgTypes[246] + mi := &file_product_proto_msgTypes[258] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12811,7 +13369,7 @@ func (x *ListOfAuthorFilter_List) String() string { func (*ListOfAuthorFilter_List) ProtoMessage() {} func (x *ListOfAuthorFilter_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[246] + mi := &file_product_proto_msgTypes[258] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12843,7 +13401,7 @@ type ListOfAuthorInput_List struct { func (x *ListOfAuthorInput_List) Reset() { *x = ListOfAuthorInput_List{} - mi := &file_product_proto_msgTypes[247] + mi := &file_product_proto_msgTypes[259] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12855,7 +13413,7 @@ func (x *ListOfAuthorInput_List) String() string { func (*ListOfAuthorInput_List) ProtoMessage() {} func (x *ListOfAuthorInput_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[247] + mi := &file_product_proto_msgTypes[259] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12887,7 +13445,7 @@ type ListOfBlogPost_List struct { func (x *ListOfBlogPost_List) Reset() { *x = ListOfBlogPost_List{} - mi := &file_product_proto_msgTypes[248] + mi := &file_product_proto_msgTypes[260] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12899,7 +13457,7 @@ func (x *ListOfBlogPost_List) String() string { func (*ListOfBlogPost_List) ProtoMessage() {} func (x *ListOfBlogPost_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[248] + mi := &file_product_proto_msgTypes[260] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12931,7 +13489,7 @@ type ListOfBlogPostFilter_List struct { func (x *ListOfBlogPostFilter_List) Reset() { *x = ListOfBlogPostFilter_List{} - mi := &file_product_proto_msgTypes[249] + mi := &file_product_proto_msgTypes[261] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12943,7 +13501,7 @@ func (x *ListOfBlogPostFilter_List) String() string { func (*ListOfBlogPostFilter_List) ProtoMessage() {} func (x *ListOfBlogPostFilter_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[249] + mi := &file_product_proto_msgTypes[261] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12975,7 +13533,7 @@ type ListOfBlogPostInput_List struct { func (x *ListOfBlogPostInput_List) Reset() { *x = ListOfBlogPostInput_List{} - mi := &file_product_proto_msgTypes[250] + mi := &file_product_proto_msgTypes[262] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12987,7 +13545,7 @@ func (x *ListOfBlogPostInput_List) String() string { func (*ListOfBlogPostInput_List) ProtoMessage() {} func (x *ListOfBlogPostInput_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[250] + mi := &file_product_proto_msgTypes[262] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13019,7 +13577,7 @@ type ListOfBoolean_List struct { func (x *ListOfBoolean_List) Reset() { *x = ListOfBoolean_List{} - mi := &file_product_proto_msgTypes[251] + mi := &file_product_proto_msgTypes[263] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13031,7 +13589,7 @@ func (x *ListOfBoolean_List) String() string { func (*ListOfBoolean_List) ProtoMessage() {} func (x *ListOfBoolean_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[251] + mi := &file_product_proto_msgTypes[263] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13063,7 +13621,7 @@ type ListOfCategory_List struct { func (x *ListOfCategory_List) Reset() { *x = ListOfCategory_List{} - mi := &file_product_proto_msgTypes[252] + mi := &file_product_proto_msgTypes[264] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13075,7 +13633,7 @@ func (x *ListOfCategory_List) String() string { func (*ListOfCategory_List) ProtoMessage() {} func (x *ListOfCategory_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[252] + mi := &file_product_proto_msgTypes[264] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13107,7 +13665,7 @@ type ListOfCategoryInput_List struct { func (x *ListOfCategoryInput_List) Reset() { *x = ListOfCategoryInput_List{} - mi := &file_product_proto_msgTypes[253] + mi := &file_product_proto_msgTypes[265] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13119,7 +13677,7 @@ func (x *ListOfCategoryInput_List) String() string { func (*ListOfCategoryInput_List) ProtoMessage() {} func (x *ListOfCategoryInput_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[253] + mi := &file_product_proto_msgTypes[265] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13151,7 +13709,7 @@ type ListOfFloat_List struct { func (x *ListOfFloat_List) Reset() { *x = ListOfFloat_List{} - mi := &file_product_proto_msgTypes[254] + mi := &file_product_proto_msgTypes[266] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13163,7 +13721,7 @@ func (x *ListOfFloat_List) String() string { func (*ListOfFloat_List) ProtoMessage() {} func (x *ListOfFloat_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[254] + mi := &file_product_proto_msgTypes[266] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13195,7 +13753,7 @@ type ListOfListOfCategory_List struct { func (x *ListOfListOfCategory_List) Reset() { *x = ListOfListOfCategory_List{} - mi := &file_product_proto_msgTypes[255] + mi := &file_product_proto_msgTypes[267] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13207,7 +13765,7 @@ func (x *ListOfListOfCategory_List) String() string { func (*ListOfListOfCategory_List) ProtoMessage() {} func (x *ListOfListOfCategory_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[255] + mi := &file_product_proto_msgTypes[267] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13239,7 +13797,7 @@ type ListOfListOfCategoryInput_List struct { func (x *ListOfListOfCategoryInput_List) Reset() { *x = ListOfListOfCategoryInput_List{} - mi := &file_product_proto_msgTypes[256] + mi := &file_product_proto_msgTypes[268] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13251,7 +13809,7 @@ func (x *ListOfListOfCategoryInput_List) String() string { func (*ListOfListOfCategoryInput_List) ProtoMessage() {} func (x *ListOfListOfCategoryInput_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[256] + mi := &file_product_proto_msgTypes[268] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13283,7 +13841,7 @@ type ListOfListOfString_List struct { func (x *ListOfListOfString_List) Reset() { *x = ListOfListOfString_List{} - mi := &file_product_proto_msgTypes[257] + mi := &file_product_proto_msgTypes[269] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13295,7 +13853,7 @@ func (x *ListOfListOfString_List) String() string { func (*ListOfListOfString_List) ProtoMessage() {} func (x *ListOfListOfString_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[257] + mi := &file_product_proto_msgTypes[269] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13327,7 +13885,7 @@ type ListOfListOfUser_List struct { func (x *ListOfListOfUser_List) Reset() { *x = ListOfListOfUser_List{} - mi := &file_product_proto_msgTypes[258] + mi := &file_product_proto_msgTypes[270] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13339,7 +13897,7 @@ func (x *ListOfListOfUser_List) String() string { func (*ListOfListOfUser_List) ProtoMessage() {} func (x *ListOfListOfUser_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[258] + mi := &file_product_proto_msgTypes[270] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13371,7 +13929,7 @@ type ListOfListOfUserInput_List struct { func (x *ListOfListOfUserInput_List) Reset() { *x = ListOfListOfUserInput_List{} - mi := &file_product_proto_msgTypes[259] + mi := &file_product_proto_msgTypes[271] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13383,7 +13941,7 @@ func (x *ListOfListOfUserInput_List) String() string { func (*ListOfListOfUserInput_List) ProtoMessage() {} func (x *ListOfListOfUserInput_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[259] + mi := &file_product_proto_msgTypes[271] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13415,7 +13973,7 @@ type ListOfOrderLine_List struct { func (x *ListOfOrderLine_List) Reset() { *x = ListOfOrderLine_List{} - mi := &file_product_proto_msgTypes[260] + mi := &file_product_proto_msgTypes[272] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13427,7 +13985,7 @@ func (x *ListOfOrderLine_List) String() string { func (*ListOfOrderLine_List) ProtoMessage() {} func (x *ListOfOrderLine_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[260] + mi := &file_product_proto_msgTypes[272] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13459,7 +14017,7 @@ type ListOfProduct_List struct { func (x *ListOfProduct_List) Reset() { *x = ListOfProduct_List{} - mi := &file_product_proto_msgTypes[261] + mi := &file_product_proto_msgTypes[273] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13471,7 +14029,7 @@ func (x *ListOfProduct_List) String() string { func (*ListOfProduct_List) ProtoMessage() {} func (x *ListOfProduct_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[261] + mi := &file_product_proto_msgTypes[273] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13503,7 +14061,7 @@ type ListOfString_List struct { func (x *ListOfString_List) Reset() { *x = ListOfString_List{} - mi := &file_product_proto_msgTypes[262] + mi := &file_product_proto_msgTypes[274] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13515,7 +14073,7 @@ func (x *ListOfString_List) String() string { func (*ListOfString_List) ProtoMessage() {} func (x *ListOfString_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[262] + mi := &file_product_proto_msgTypes[274] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13547,7 +14105,7 @@ type ListOfSubcategory_List struct { func (x *ListOfSubcategory_List) Reset() { *x = ListOfSubcategory_List{} - mi := &file_product_proto_msgTypes[263] + mi := &file_product_proto_msgTypes[275] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13559,7 +14117,7 @@ func (x *ListOfSubcategory_List) String() string { func (*ListOfSubcategory_List) ProtoMessage() {} func (x *ListOfSubcategory_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[263] + mi := &file_product_proto_msgTypes[275] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13591,7 +14149,7 @@ type ListOfUser_List struct { func (x *ListOfUser_List) Reset() { *x = ListOfUser_List{} - mi := &file_product_proto_msgTypes[264] + mi := &file_product_proto_msgTypes[276] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13603,7 +14161,7 @@ func (x *ListOfUser_List) String() string { func (*ListOfUser_List) ProtoMessage() {} func (x *ListOfUser_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[264] + mi := &file_product_proto_msgTypes[276] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13635,7 +14193,7 @@ type ListOfUserInput_List struct { func (x *ListOfUserInput_List) Reset() { *x = ListOfUserInput_List{} - mi := &file_product_proto_msgTypes[265] + mi := &file_product_proto_msgTypes[277] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13647,7 +14205,7 @@ func (x *ListOfUserInput_List) String() string { func (*ListOfUserInput_List) ProtoMessage() {} func (x *ListOfUserInput_List) ProtoReflect() protoreflect.Message { - mi := &file_product_proto_msgTypes[265] + mi := &file_product_proto_msgTypes[277] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13809,7 +14367,11 @@ const file_product_proto_rawDesc = "" + "\x17QueryCategoriesResponse\x123\n" + "\n" + "categories\x18\x01 \x03(\v2\x13.productv1.CategoryR\n" + - "categories\"K\n" + + "categories\"&\n" + + "\x14QueryCategoryRequest\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\"H\n" + + "\x15QueryCategoryResponse\x12/\n" + + "\bcategory\x18\x01 \x01(\v2\x13.productv1.CategoryR\bcategory\"K\n" + "\x1cQueryCategoriesByKindRequest\x12+\n" + "\x04kind\x18\x01 \x01(\x0e2\x17.productv1.CategoryKindR\x04kind\"b\n" + "\x1dQueryCategoriesByKindResponse\x12A\n" + @@ -14120,7 +14682,19 @@ const file_product_proto_rawDesc = "" + "\n" + "item_count\x18\x01 \x01(\x05R\titemCount\"k\n" + "#ResolveSubcategoryItemCountResponse\x12D\n" + - "\x06result\x18\x01 \x03(\v2,.productv1.ResolveSubcategoryItemCountResultR\x06result\"G\n" + + "\x06result\x18\x01 \x03(\v2,.productv1.ResolveSubcategoryItemCountResultR\x06result\"S\n" + + "&ResolveSubcategoryFeaturedCategoryArgs\x12)\n" + + "\x10include_children\x18\x01 \x01(\bR\x0fincludeChildren\";\n" + + ")ResolveSubcategoryFeaturedCategoryContext\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\"\xcd\x01\n" + + ")ResolveSubcategoryFeaturedCategoryRequest\x12N\n" + + "\acontext\x18\x01 \x03(\v24.productv1.ResolveSubcategoryFeaturedCategoryContextR\acontext\x12P\n" + + "\n" + + "field_args\x18\x02 \x01(\v21.productv1.ResolveSubcategoryFeaturedCategoryArgsR\tfieldArgs\"l\n" + + "(ResolveSubcategoryFeaturedCategoryResult\x12@\n" + + "\x11featured_category\x18\x01 \x01(\v2\x13.productv1.CategoryR\x10featuredCategory\"y\n" + + "*ResolveSubcategoryFeaturedCategoryResponse\x12K\n" + + "\x06result\x18\x01 \x03(\v23.productv1.ResolveSubcategoryFeaturedCategoryResultR\x06result\"G\n" + ")ResolveCategoryMetricsNormalizedScoreArgs\x12\x1a\n" + "\bbaseline\x18\x01 \x01(\x01R\bbaseline\"u\n" + ",ResolveCategoryMetricsNormalizedScoreContext\x12\x0e\n" + @@ -14135,7 +14709,20 @@ const file_product_proto_rawDesc = "" + "+ResolveCategoryMetricsNormalizedScoreResult\x12)\n" + "\x10normalized_score\x18\x01 \x01(\x01R\x0fnormalizedScore\"\x7f\n" + "-ResolveCategoryMetricsNormalizedScoreResponse\x12N\n" + - "\x06result\x18\x01 \x03(\v26.productv1.ResolveCategoryMetricsNormalizedScoreResultR\x06result\"L\n" + + "\x06result\x18\x01 \x03(\v26.productv1.ResolveCategoryMetricsNormalizedScoreResultR\x06result\"a\n" + + ")ResolveCategoryMetricsRelatedCategoryArgs\x124\n" + + "\ainclude\x18\x01 \x01(\v2\x1a.google.protobuf.BoolValueR\ainclude\"O\n" + + ",ResolveCategoryMetricsRelatedCategoryContext\x12\x1f\n" + + "\vcategory_id\x18\x01 \x01(\tR\n" + + "categoryId\"\xd6\x01\n" + + ",ResolveCategoryMetricsRelatedCategoryRequest\x12Q\n" + + "\acontext\x18\x01 \x03(\v27.productv1.ResolveCategoryMetricsRelatedCategoryContextR\acontext\x12S\n" + + "\n" + + "field_args\x18\x02 \x01(\v24.productv1.ResolveCategoryMetricsRelatedCategoryArgsR\tfieldArgs\"m\n" + + "+ResolveCategoryMetricsRelatedCategoryResult\x12>\n" + + "\x10related_category\x18\x01 \x01(\v2\x13.productv1.CategoryR\x0frelatedCategory\"\x7f\n" + + "-ResolveCategoryMetricsRelatedCategoryResponse\x12N\n" + + "\x06result\x18\x01 \x03(\v26.productv1.ResolveCategoryMetricsRelatedCategoryResultR\x06result\"L\n" + "\x1fResolveTestContainerDetailsArgs\x12)\n" + "\x10include_extended\x18\x01 \x01(\bR\x0fincludeExtended\"H\n" + "\"ResolveTestContainerDetailsContext\x12\x0e\n" + @@ -14196,12 +14783,13 @@ const file_product_proto_rawDesc = "" + "\vtotal_items\x18\x03 \x01(\x05R\n" + "totalItems\x12;\n" + "\vorder_lines\x18\x04 \x01(\v2\x1a.productv1.ListOfOrderLineR\n" + - "orderLines\"\x9f\x01\n" + + "orderLines\"\xde\x01\n" + "\bCategory\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\x12+\n" + "\x04kind\x18\x03 \x01(\x0e2\x17.productv1.CategoryKindR\x04kind\x12B\n" + - "\rsubcategories\x18\x05 \x01(\v2\x1c.productv1.ListOfSubcategoryR\rsubcategories\"|\n" + + "\rsubcategories\x18\x04 \x01(\v2\x1c.productv1.ListOfSubcategoryR\rsubcategories\x12=\n" + + "\fnull_metrics\x18\x05 \x01(\v2\x1a.productv1.CategoryMetricsR\vnullMetrics\"|\n" + "\x0eCategoryFilter\x123\n" + "\bcategory\x18\x01 \x01(\x0e2\x17.productv1.CategoryKindR\bcategory\x125\n" + "\n" + @@ -14378,7 +14966,7 @@ const file_product_proto_rawDesc = "" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\x12>\n" + "\vdescription\x18\x03 \x01(\v2\x1c.google.protobuf.StringValueR\vdescription\x12\x1b\n" + - "\tis_active\x18\x04 \x01(\bR\bisActive\"\xd7\x01\n" + + "\tis_active\x18\x04 \x01(\bR\bisActive\"\x97\x01\n" + "\x0fCategoryMetrics\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + "\vmetric_type\x18\x02 \x01(\tR\n" + @@ -14386,8 +14974,7 @@ const file_product_proto_rawDesc = "" + "\x05value\x18\x03 \x01(\x01R\x05value\x12\x1c\n" + "\ttimestamp\x18\x04 \x01(\tR\ttimestamp\x12\x1f\n" + "\vcategory_id\x18\x05 \x01(\tR\n" + - "categoryId\x12>\n" + - "\x10related_category\x18\x06 \x01(\v2\x13.productv1.CategoryR\x0frelatedCategory\"\xb1\x01\n" + + "categoryId\"\xb1\x01\n" + "\x03Cat\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + @@ -14403,11 +14990,12 @@ const file_product_proto_rawDesc = "" + "\vbark_volume\x18\x04 \x01(\x05R\n" + "barkVolume\x12&\n" + "\x05owner\x18\x05 \x01(\v2\x10.productv1.OwnerR\x05owner\x12)\n" + - "\x05breed\x18\x06 \x01(\v2\x13.productv1.DogBreedR\x05breed\"]\n" + + "\x05breed\x18\x06 \x01(\v2\x13.productv1.DogBreedR\x05breed\"\x82\x01\n" + "\x05Owner\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\x120\n" + - "\acontact\x18\x03 \x01(\v2\x16.productv1.ContactInfoR\acontact\"g\n" + + "\acontact\x18\x03 \x01(\v2\x16.productv1.ContactInfoR\acontact\x12#\n" + + "\x03pet\x18\x04 \x01(\v2\x11.productv1.AnimalR\x03pet\"g\n" + "\vContactInfo\x12\x14\n" + "\x05email\x18\x01 \x01(\tR\x05email\x12\x14\n" + "\x05phone\x18\x02 \x01(\tR\x05phone\x12,\n" + @@ -14472,7 +15060,7 @@ const file_product_proto_rawDesc = "" + " SHIPPING_DESTINATION_UNSPECIFIED\x10\x00\x12!\n" + "\x1dSHIPPING_DESTINATION_DOMESTIC\x10\x01\x12 \n" + "\x1cSHIPPING_DESTINATION_EXPRESS\x10\x02\x12&\n" + - "\"SHIPPING_DESTINATION_INTERNATIONAL\x10\x032\xfb7\n" + + "\"SHIPPING_DESTINATION_INTERNATIONAL\x10\x032\x86;\n" + "\x0eProductService\x12`\n" + "\x11LookupProductById\x12#.productv1.LookupProductByIdRequest\x1a$.productv1.LookupProductByIdResponse\"\x00\x12`\n" + "\x11LookupStorageById\x12#.productv1.LookupStorageByIdRequest\x1a$.productv1.LookupStorageByIdResponse\"\x00\x12f\n" + @@ -14504,7 +15092,8 @@ const file_product_proto_rawDesc = "" + "\x14QueryCalculateTotals\x12&.productv1.QueryCalculateTotalsRequest\x1a'.productv1.QueryCalculateTotalsResponse\"\x00\x12Z\n" + "\x0fQueryCategories\x12!.productv1.QueryCategoriesRequest\x1a\".productv1.QueryCategoriesResponse\"\x00\x12l\n" + "\x15QueryCategoriesByKind\x12'.productv1.QueryCategoriesByKindRequest\x1a(.productv1.QueryCategoriesByKindResponse\"\x00\x12o\n" + - "\x16QueryCategoriesByKinds\x12(.productv1.QueryCategoriesByKindsRequest\x1a).productv1.QueryCategoriesByKindsResponse\"\x00\x12o\n" + + "\x16QueryCategoriesByKinds\x12(.productv1.QueryCategoriesByKindsRequest\x1a).productv1.QueryCategoriesByKindsResponse\"\x00\x12T\n" + + "\rQueryCategory\x12\x1f.productv1.QueryCategoryRequest\x1a .productv1.QueryCategoryResponse\"\x00\x12o\n" + "\x16QueryComplexFilterType\x12(.productv1.QueryComplexFilterTypeRequest\x1a).productv1.QueryComplexFilterTypeResponse\"\x00\x12l\n" + "\x15QueryFilterCategories\x12'.productv1.QueryFilterCategoriesRequest\x1a(.productv1.QueryFilterCategoriesResponse\"\x00\x12Z\n" + "\x0fQueryNestedType\x12!.productv1.QueryNestedTypeRequest\x1a\".productv1.QueryNestedTypeResponse\"\x00\x12r\n" + @@ -14526,7 +15115,8 @@ const file_product_proto_rawDesc = "" + "\x1dResolveCategoryCategoryStatus\x12/.productv1.ResolveCategoryCategoryStatusRequest\x1a0.productv1.ResolveCategoryCategoryStatusResponse\"\x00\x12\x87\x01\n" + "\x1eResolveCategoryChildCategories\x120.productv1.ResolveCategoryChildCategoriesRequest\x1a1.productv1.ResolveCategoryChildCategoriesResponse\"\x00\x12l\n" + "\x15ResolveCategoryMascot\x12'.productv1.ResolveCategoryMascotRequest\x1a(.productv1.ResolveCategoryMascotResponse\"\x00\x12\x9c\x01\n" + - "%ResolveCategoryMetricsNormalizedScore\x127.productv1.ResolveCategoryMetricsNormalizedScoreRequest\x1a8.productv1.ResolveCategoryMetricsNormalizedScoreResponse\"\x00\x12\x90\x01\n" + + "%ResolveCategoryMetricsNormalizedScore\x127.productv1.ResolveCategoryMetricsNormalizedScoreRequest\x1a8.productv1.ResolveCategoryMetricsNormalizedScoreResponse\"\x00\x12\x9c\x01\n" + + "%ResolveCategoryMetricsRelatedCategory\x127.productv1.ResolveCategoryMetricsRelatedCategoryRequest\x1a8.productv1.ResolveCategoryMetricsRelatedCategoryResponse\"\x00\x12\x90\x01\n" + "!ResolveCategoryOptionalCategories\x123.productv1.ResolveCategoryOptionalCategoriesRequest\x1a4.productv1.ResolveCategoryOptionalCategoriesResponse\"\x00\x12\x87\x01\n" + "\x1eResolveCategoryPopularityScore\x120.productv1.ResolveCategoryPopularityScoreRequest\x1a1.productv1.ResolveCategoryPopularityScoreResponse\"\x00\x12~\n" + "\x1bResolveCategoryProductCount\x12-.productv1.ResolveCategoryProductCountRequest\x1a..productv1.ResolveCategoryProductCountResponse\"\x00\x12\x93\x01\n" + @@ -14534,7 +15124,8 @@ const file_product_proto_rawDesc = "" + "\x1cResolveProductProductDetails\x12..productv1.ResolveProductProductDetailsRequest\x1a/.productv1.ResolveProductProductDetailsResponse\"\x00\x12\x90\x01\n" + "!ResolveProductRecommendedCategory\x123.productv1.ResolveProductRecommendedCategoryRequest\x1a4.productv1.ResolveProductRecommendedCategoryResponse\"\x00\x12\x87\x01\n" + "\x1eResolveProductShippingEstimate\x120.productv1.ResolveProductShippingEstimateRequest\x1a1.productv1.ResolveProductShippingEstimateResponse\"\x00\x12x\n" + - "\x19ResolveProductStockStatus\x12+.productv1.ResolveProductStockStatusRequest\x1a,.productv1.ResolveProductStockStatusResponse\"\x00\x12~\n" + + "\x19ResolveProductStockStatus\x12+.productv1.ResolveProductStockStatusRequest\x1a,.productv1.ResolveProductStockStatusResponse\"\x00\x12\x93\x01\n" + + "\"ResolveSubcategoryFeaturedCategory\x124.productv1.ResolveSubcategoryFeaturedCategoryRequest\x1a5.productv1.ResolveSubcategoryFeaturedCategoryResponse\"\x00\x12~\n" + "\x1bResolveSubcategoryItemCount\x12-.productv1.ResolveSubcategoryItemCountRequest\x1a..productv1.ResolveSubcategoryItemCountResponse\"\x00\x12~\n" + "\x1bResolveTestContainerDetails\x12-.productv1.ResolveTestContainerDetailsRequest\x1a..productv1.ResolveTestContainerDetailsResponse\"\x00B%Z#cosmo/pkg/proto/productv1;productv1b\x06proto3" @@ -14551,7 +15142,7 @@ func file_product_proto_rawDescGZIP() []byte { } var file_product_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_product_proto_msgTypes = make([]protoimpl.MessageInfo, 266) +var file_product_proto_msgTypes = make([]protoimpl.MessageInfo, 278) var file_product_proto_goTypes = []any{ (CategoryKind)(0), // 0: productv1.CategoryKind (ShippingDestination)(0), // 1: productv1.ShippingDestination @@ -14602,642 +15193,671 @@ var file_product_proto_goTypes = []any{ (*QueryCalculateTotalsResponse)(nil), // 46: productv1.QueryCalculateTotalsResponse (*QueryCategoriesRequest)(nil), // 47: productv1.QueryCategoriesRequest (*QueryCategoriesResponse)(nil), // 48: productv1.QueryCategoriesResponse - (*QueryCategoriesByKindRequest)(nil), // 49: productv1.QueryCategoriesByKindRequest - (*QueryCategoriesByKindResponse)(nil), // 50: productv1.QueryCategoriesByKindResponse - (*QueryCategoriesByKindsRequest)(nil), // 51: productv1.QueryCategoriesByKindsRequest - (*QueryCategoriesByKindsResponse)(nil), // 52: productv1.QueryCategoriesByKindsResponse - (*QueryFilterCategoriesRequest)(nil), // 53: productv1.QueryFilterCategoriesRequest - (*QueryFilterCategoriesResponse)(nil), // 54: productv1.QueryFilterCategoriesResponse - (*QueryRandomPetRequest)(nil), // 55: productv1.QueryRandomPetRequest - (*QueryRandomPetResponse)(nil), // 56: productv1.QueryRandomPetResponse - (*QueryAllPetsRequest)(nil), // 57: productv1.QueryAllPetsRequest - (*QueryAllPetsResponse)(nil), // 58: productv1.QueryAllPetsResponse - (*QuerySearchRequest)(nil), // 59: productv1.QuerySearchRequest - (*QuerySearchResponse)(nil), // 60: productv1.QuerySearchResponse - (*QueryRandomSearchResultRequest)(nil), // 61: productv1.QueryRandomSearchResultRequest - (*QueryRandomSearchResultResponse)(nil), // 62: productv1.QueryRandomSearchResultResponse - (*QueryNullableFieldsTypeRequest)(nil), // 63: productv1.QueryNullableFieldsTypeRequest - (*QueryNullableFieldsTypeResponse)(nil), // 64: productv1.QueryNullableFieldsTypeResponse - (*QueryNullableFieldsTypeByIdRequest)(nil), // 65: productv1.QueryNullableFieldsTypeByIdRequest - (*QueryNullableFieldsTypeByIdResponse)(nil), // 66: productv1.QueryNullableFieldsTypeByIdResponse - (*QueryNullableFieldsTypeWithFilterRequest)(nil), // 67: productv1.QueryNullableFieldsTypeWithFilterRequest - (*QueryNullableFieldsTypeWithFilterResponse)(nil), // 68: productv1.QueryNullableFieldsTypeWithFilterResponse - (*QueryAllNullableFieldsTypesRequest)(nil), // 69: productv1.QueryAllNullableFieldsTypesRequest - (*QueryAllNullableFieldsTypesResponse)(nil), // 70: productv1.QueryAllNullableFieldsTypesResponse - (*QueryBlogPostRequest)(nil), // 71: productv1.QueryBlogPostRequest - (*QueryBlogPostResponse)(nil), // 72: productv1.QueryBlogPostResponse - (*QueryBlogPostByIdRequest)(nil), // 73: productv1.QueryBlogPostByIdRequest - (*QueryBlogPostByIdResponse)(nil), // 74: productv1.QueryBlogPostByIdResponse - (*QueryBlogPostsWithFilterRequest)(nil), // 75: productv1.QueryBlogPostsWithFilterRequest - (*QueryBlogPostsWithFilterResponse)(nil), // 76: productv1.QueryBlogPostsWithFilterResponse - (*QueryAllBlogPostsRequest)(nil), // 77: productv1.QueryAllBlogPostsRequest - (*QueryAllBlogPostsResponse)(nil), // 78: productv1.QueryAllBlogPostsResponse - (*QueryAuthorRequest)(nil), // 79: productv1.QueryAuthorRequest - (*QueryAuthorResponse)(nil), // 80: productv1.QueryAuthorResponse - (*QueryAuthorByIdRequest)(nil), // 81: productv1.QueryAuthorByIdRequest - (*QueryAuthorByIdResponse)(nil), // 82: productv1.QueryAuthorByIdResponse - (*QueryAuthorsWithFilterRequest)(nil), // 83: productv1.QueryAuthorsWithFilterRequest - (*QueryAuthorsWithFilterResponse)(nil), // 84: productv1.QueryAuthorsWithFilterResponse - (*QueryAllAuthorsRequest)(nil), // 85: productv1.QueryAllAuthorsRequest - (*QueryAllAuthorsResponse)(nil), // 86: productv1.QueryAllAuthorsResponse - (*QueryBulkSearchAuthorsRequest)(nil), // 87: productv1.QueryBulkSearchAuthorsRequest - (*QueryBulkSearchAuthorsResponse)(nil), // 88: productv1.QueryBulkSearchAuthorsResponse - (*QueryBulkSearchBlogPostsRequest)(nil), // 89: productv1.QueryBulkSearchBlogPostsRequest - (*QueryBulkSearchBlogPostsResponse)(nil), // 90: productv1.QueryBulkSearchBlogPostsResponse - (*QueryTestContainerRequest)(nil), // 91: productv1.QueryTestContainerRequest - (*QueryTestContainerResponse)(nil), // 92: productv1.QueryTestContainerResponse - (*QueryTestContainersRequest)(nil), // 93: productv1.QueryTestContainersRequest - (*QueryTestContainersResponse)(nil), // 94: productv1.QueryTestContainersResponse - (*MutationCreateUserRequest)(nil), // 95: productv1.MutationCreateUserRequest - (*MutationCreateUserResponse)(nil), // 96: productv1.MutationCreateUserResponse - (*MutationPerformActionRequest)(nil), // 97: productv1.MutationPerformActionRequest - (*MutationPerformActionResponse)(nil), // 98: productv1.MutationPerformActionResponse - (*MutationCreateNullableFieldsTypeRequest)(nil), // 99: productv1.MutationCreateNullableFieldsTypeRequest - (*MutationCreateNullableFieldsTypeResponse)(nil), // 100: productv1.MutationCreateNullableFieldsTypeResponse - (*MutationUpdateNullableFieldsTypeRequest)(nil), // 101: productv1.MutationUpdateNullableFieldsTypeRequest - (*MutationUpdateNullableFieldsTypeResponse)(nil), // 102: productv1.MutationUpdateNullableFieldsTypeResponse - (*MutationCreateBlogPostRequest)(nil), // 103: productv1.MutationCreateBlogPostRequest - (*MutationCreateBlogPostResponse)(nil), // 104: productv1.MutationCreateBlogPostResponse - (*MutationUpdateBlogPostRequest)(nil), // 105: productv1.MutationUpdateBlogPostRequest - (*MutationUpdateBlogPostResponse)(nil), // 106: productv1.MutationUpdateBlogPostResponse - (*MutationCreateAuthorRequest)(nil), // 107: productv1.MutationCreateAuthorRequest - (*MutationCreateAuthorResponse)(nil), // 108: productv1.MutationCreateAuthorResponse - (*MutationUpdateAuthorRequest)(nil), // 109: productv1.MutationUpdateAuthorRequest - (*MutationUpdateAuthorResponse)(nil), // 110: productv1.MutationUpdateAuthorResponse - (*MutationBulkCreateAuthorsRequest)(nil), // 111: productv1.MutationBulkCreateAuthorsRequest - (*MutationBulkCreateAuthorsResponse)(nil), // 112: productv1.MutationBulkCreateAuthorsResponse - (*MutationBulkUpdateAuthorsRequest)(nil), // 113: productv1.MutationBulkUpdateAuthorsRequest - (*MutationBulkUpdateAuthorsResponse)(nil), // 114: productv1.MutationBulkUpdateAuthorsResponse - (*MutationBulkCreateBlogPostsRequest)(nil), // 115: productv1.MutationBulkCreateBlogPostsRequest - (*MutationBulkCreateBlogPostsResponse)(nil), // 116: productv1.MutationBulkCreateBlogPostsResponse - (*MutationBulkUpdateBlogPostsRequest)(nil), // 117: productv1.MutationBulkUpdateBlogPostsRequest - (*MutationBulkUpdateBlogPostsResponse)(nil), // 118: productv1.MutationBulkUpdateBlogPostsResponse - (*ResolveProductShippingEstimateArgs)(nil), // 119: productv1.ResolveProductShippingEstimateArgs - (*ResolveProductShippingEstimateContext)(nil), // 120: productv1.ResolveProductShippingEstimateContext - (*ResolveProductShippingEstimateRequest)(nil), // 121: productv1.ResolveProductShippingEstimateRequest - (*ResolveProductShippingEstimateResult)(nil), // 122: productv1.ResolveProductShippingEstimateResult - (*ResolveProductShippingEstimateResponse)(nil), // 123: productv1.ResolveProductShippingEstimateResponse - (*ResolveProductRecommendedCategoryArgs)(nil), // 124: productv1.ResolveProductRecommendedCategoryArgs - (*ResolveProductRecommendedCategoryContext)(nil), // 125: productv1.ResolveProductRecommendedCategoryContext - (*ResolveProductRecommendedCategoryRequest)(nil), // 126: productv1.ResolveProductRecommendedCategoryRequest - (*ResolveProductRecommendedCategoryResult)(nil), // 127: productv1.ResolveProductRecommendedCategoryResult - (*ResolveProductRecommendedCategoryResponse)(nil), // 128: productv1.ResolveProductRecommendedCategoryResponse - (*ResolveProductMascotRecommendationArgs)(nil), // 129: productv1.ResolveProductMascotRecommendationArgs - (*ResolveProductMascotRecommendationContext)(nil), // 130: productv1.ResolveProductMascotRecommendationContext - (*ResolveProductMascotRecommendationRequest)(nil), // 131: productv1.ResolveProductMascotRecommendationRequest - (*ResolveProductMascotRecommendationResult)(nil), // 132: productv1.ResolveProductMascotRecommendationResult - (*ResolveProductMascotRecommendationResponse)(nil), // 133: productv1.ResolveProductMascotRecommendationResponse - (*ResolveProductStockStatusArgs)(nil), // 134: productv1.ResolveProductStockStatusArgs - (*ResolveProductStockStatusContext)(nil), // 135: productv1.ResolveProductStockStatusContext - (*ResolveProductStockStatusRequest)(nil), // 136: productv1.ResolveProductStockStatusRequest - (*ResolveProductStockStatusResult)(nil), // 137: productv1.ResolveProductStockStatusResult - (*ResolveProductStockStatusResponse)(nil), // 138: productv1.ResolveProductStockStatusResponse - (*ResolveProductProductDetailsArgs)(nil), // 139: productv1.ResolveProductProductDetailsArgs - (*ResolveProductProductDetailsContext)(nil), // 140: productv1.ResolveProductProductDetailsContext - (*ResolveProductProductDetailsRequest)(nil), // 141: productv1.ResolveProductProductDetailsRequest - (*ResolveProductProductDetailsResult)(nil), // 142: productv1.ResolveProductProductDetailsResult - (*ResolveProductProductDetailsResponse)(nil), // 143: productv1.ResolveProductProductDetailsResponse - (*ResolveCategoryProductCountArgs)(nil), // 144: productv1.ResolveCategoryProductCountArgs - (*ResolveCategoryProductCountContext)(nil), // 145: productv1.ResolveCategoryProductCountContext - (*ResolveCategoryProductCountRequest)(nil), // 146: productv1.ResolveCategoryProductCountRequest - (*ResolveCategoryProductCountResult)(nil), // 147: productv1.ResolveCategoryProductCountResult - (*ResolveCategoryProductCountResponse)(nil), // 148: productv1.ResolveCategoryProductCountResponse - (*ResolveCategoryPopularityScoreArgs)(nil), // 149: productv1.ResolveCategoryPopularityScoreArgs - (*ResolveCategoryPopularityScoreContext)(nil), // 150: productv1.ResolveCategoryPopularityScoreContext - (*ResolveCategoryPopularityScoreRequest)(nil), // 151: productv1.ResolveCategoryPopularityScoreRequest - (*ResolveCategoryPopularityScoreResult)(nil), // 152: productv1.ResolveCategoryPopularityScoreResult - (*ResolveCategoryPopularityScoreResponse)(nil), // 153: productv1.ResolveCategoryPopularityScoreResponse - (*ResolveCategoryCategoryMetricsArgs)(nil), // 154: productv1.ResolveCategoryCategoryMetricsArgs - (*ResolveCategoryCategoryMetricsContext)(nil), // 155: productv1.ResolveCategoryCategoryMetricsContext - (*ResolveCategoryCategoryMetricsRequest)(nil), // 156: productv1.ResolveCategoryCategoryMetricsRequest - (*ResolveCategoryCategoryMetricsResult)(nil), // 157: productv1.ResolveCategoryCategoryMetricsResult - (*ResolveCategoryCategoryMetricsResponse)(nil), // 158: productv1.ResolveCategoryCategoryMetricsResponse - (*ResolveCategoryMascotArgs)(nil), // 159: productv1.ResolveCategoryMascotArgs - (*ResolveCategoryMascotContext)(nil), // 160: productv1.ResolveCategoryMascotContext - (*ResolveCategoryMascotRequest)(nil), // 161: productv1.ResolveCategoryMascotRequest - (*ResolveCategoryMascotResult)(nil), // 162: productv1.ResolveCategoryMascotResult - (*ResolveCategoryMascotResponse)(nil), // 163: productv1.ResolveCategoryMascotResponse - (*ResolveCategoryCategoryStatusArgs)(nil), // 164: productv1.ResolveCategoryCategoryStatusArgs - (*ResolveCategoryCategoryStatusContext)(nil), // 165: productv1.ResolveCategoryCategoryStatusContext - (*ResolveCategoryCategoryStatusRequest)(nil), // 166: productv1.ResolveCategoryCategoryStatusRequest - (*ResolveCategoryCategoryStatusResult)(nil), // 167: productv1.ResolveCategoryCategoryStatusResult - (*ResolveCategoryCategoryStatusResponse)(nil), // 168: productv1.ResolveCategoryCategoryStatusResponse - (*ResolveCategoryChildCategoriesArgs)(nil), // 169: productv1.ResolveCategoryChildCategoriesArgs - (*ResolveCategoryChildCategoriesContext)(nil), // 170: productv1.ResolveCategoryChildCategoriesContext - (*ResolveCategoryChildCategoriesRequest)(nil), // 171: productv1.ResolveCategoryChildCategoriesRequest - (*ResolveCategoryChildCategoriesResult)(nil), // 172: productv1.ResolveCategoryChildCategoriesResult - (*ResolveCategoryChildCategoriesResponse)(nil), // 173: productv1.ResolveCategoryChildCategoriesResponse - (*ResolveCategoryOptionalCategoriesArgs)(nil), // 174: productv1.ResolveCategoryOptionalCategoriesArgs - (*ResolveCategoryOptionalCategoriesContext)(nil), // 175: productv1.ResolveCategoryOptionalCategoriesContext - (*ResolveCategoryOptionalCategoriesRequest)(nil), // 176: productv1.ResolveCategoryOptionalCategoriesRequest - (*ResolveCategoryOptionalCategoriesResult)(nil), // 177: productv1.ResolveCategoryOptionalCategoriesResult - (*ResolveCategoryOptionalCategoriesResponse)(nil), // 178: productv1.ResolveCategoryOptionalCategoriesResponse - (*ResolveSubcategoryItemCountArgs)(nil), // 179: productv1.ResolveSubcategoryItemCountArgs - (*ResolveSubcategoryItemCountContext)(nil), // 180: productv1.ResolveSubcategoryItemCountContext - (*ResolveSubcategoryItemCountRequest)(nil), // 181: productv1.ResolveSubcategoryItemCountRequest - (*ResolveSubcategoryItemCountResult)(nil), // 182: productv1.ResolveSubcategoryItemCountResult - (*ResolveSubcategoryItemCountResponse)(nil), // 183: productv1.ResolveSubcategoryItemCountResponse - (*ResolveCategoryMetricsNormalizedScoreArgs)(nil), // 184: productv1.ResolveCategoryMetricsNormalizedScoreArgs - (*ResolveCategoryMetricsNormalizedScoreContext)(nil), // 185: productv1.ResolveCategoryMetricsNormalizedScoreContext - (*ResolveCategoryMetricsNormalizedScoreRequest)(nil), // 186: productv1.ResolveCategoryMetricsNormalizedScoreRequest - (*ResolveCategoryMetricsNormalizedScoreResult)(nil), // 187: productv1.ResolveCategoryMetricsNormalizedScoreResult - (*ResolveCategoryMetricsNormalizedScoreResponse)(nil), // 188: productv1.ResolveCategoryMetricsNormalizedScoreResponse - (*ResolveTestContainerDetailsArgs)(nil), // 189: productv1.ResolveTestContainerDetailsArgs - (*ResolveTestContainerDetailsContext)(nil), // 190: productv1.ResolveTestContainerDetailsContext - (*ResolveTestContainerDetailsRequest)(nil), // 191: productv1.ResolveTestContainerDetailsRequest - (*ResolveTestContainerDetailsResult)(nil), // 192: productv1.ResolveTestContainerDetailsResult - (*ResolveTestContainerDetailsResponse)(nil), // 193: productv1.ResolveTestContainerDetailsResponse - (*Product)(nil), // 194: productv1.Product - (*Storage)(nil), // 195: productv1.Storage - (*Warehouse)(nil), // 196: productv1.Warehouse - (*User)(nil), // 197: productv1.User - (*NestedTypeA)(nil), // 198: productv1.NestedTypeA - (*RecursiveType)(nil), // 199: productv1.RecursiveType - (*TypeWithMultipleFilterFields)(nil), // 200: productv1.TypeWithMultipleFilterFields - (*FilterTypeInput)(nil), // 201: productv1.FilterTypeInput - (*ComplexFilterTypeInput)(nil), // 202: productv1.ComplexFilterTypeInput - (*TypeWithComplexFilterInput)(nil), // 203: productv1.TypeWithComplexFilterInput - (*OrderInput)(nil), // 204: productv1.OrderInput - (*Order)(nil), // 205: productv1.Order - (*Category)(nil), // 206: productv1.Category - (*CategoryFilter)(nil), // 207: productv1.CategoryFilter - (*Animal)(nil), // 208: productv1.Animal - (*SearchInput)(nil), // 209: productv1.SearchInput - (*SearchResult)(nil), // 210: productv1.SearchResult - (*NullableFieldsType)(nil), // 211: productv1.NullableFieldsType - (*NullableFieldsFilter)(nil), // 212: productv1.NullableFieldsFilter - (*BlogPost)(nil), // 213: productv1.BlogPost - (*BlogPostFilter)(nil), // 214: productv1.BlogPostFilter - (*Author)(nil), // 215: productv1.Author - (*AuthorFilter)(nil), // 216: productv1.AuthorFilter - (*TestContainer)(nil), // 217: productv1.TestContainer - (*UserInput)(nil), // 218: productv1.UserInput - (*ActionInput)(nil), // 219: productv1.ActionInput - (*ActionResult)(nil), // 220: productv1.ActionResult - (*NullableFieldsInput)(nil), // 221: productv1.NullableFieldsInput - (*BlogPostInput)(nil), // 222: productv1.BlogPostInput - (*AuthorInput)(nil), // 223: productv1.AuthorInput - (*ProductDetails)(nil), // 224: productv1.ProductDetails - (*NestedTypeB)(nil), // 225: productv1.NestedTypeB - (*NestedTypeC)(nil), // 226: productv1.NestedTypeC - (*FilterType)(nil), // 227: productv1.FilterType - (*Pagination)(nil), // 228: productv1.Pagination - (*OrderLineInput)(nil), // 229: productv1.OrderLineInput - (*OrderLine)(nil), // 230: productv1.OrderLine - (*Subcategory)(nil), // 231: productv1.Subcategory - (*CategoryMetrics)(nil), // 232: productv1.CategoryMetrics - (*Cat)(nil), // 233: productv1.Cat - (*Dog)(nil), // 234: productv1.Dog - (*Owner)(nil), // 235: productv1.Owner - (*ContactInfo)(nil), // 236: productv1.ContactInfo - (*Address)(nil), // 237: productv1.Address - (*CatBreed)(nil), // 238: productv1.CatBreed - (*DogBreed)(nil), // 239: productv1.DogBreed - (*BreedCharacteristics)(nil), // 240: productv1.BreedCharacteristics - (*ActionSuccess)(nil), // 241: productv1.ActionSuccess - (*ActionError)(nil), // 242: productv1.ActionError - (*TestDetails)(nil), // 243: productv1.TestDetails - (*CategoryInput)(nil), // 244: productv1.CategoryInput - (*ProductCountFilter)(nil), // 245: productv1.ProductCountFilter - (*SubcategoryItemFilter)(nil), // 246: productv1.SubcategoryItemFilter - (*ShippingEstimateInput)(nil), // 247: productv1.ShippingEstimateInput - (*ListOfAuthorFilter_List)(nil), // 248: productv1.ListOfAuthorFilter.List - (*ListOfAuthorInput_List)(nil), // 249: productv1.ListOfAuthorInput.List - (*ListOfBlogPost_List)(nil), // 250: productv1.ListOfBlogPost.List - (*ListOfBlogPostFilter_List)(nil), // 251: productv1.ListOfBlogPostFilter.List - (*ListOfBlogPostInput_List)(nil), // 252: productv1.ListOfBlogPostInput.List - (*ListOfBoolean_List)(nil), // 253: productv1.ListOfBoolean.List - (*ListOfCategory_List)(nil), // 254: productv1.ListOfCategory.List - (*ListOfCategoryInput_List)(nil), // 255: productv1.ListOfCategoryInput.List - (*ListOfFloat_List)(nil), // 256: productv1.ListOfFloat.List - (*ListOfListOfCategory_List)(nil), // 257: productv1.ListOfListOfCategory.List - (*ListOfListOfCategoryInput_List)(nil), // 258: productv1.ListOfListOfCategoryInput.List - (*ListOfListOfString_List)(nil), // 259: productv1.ListOfListOfString.List - (*ListOfListOfUser_List)(nil), // 260: productv1.ListOfListOfUser.List - (*ListOfListOfUserInput_List)(nil), // 261: productv1.ListOfListOfUserInput.List - (*ListOfOrderLine_List)(nil), // 262: productv1.ListOfOrderLine.List - (*ListOfProduct_List)(nil), // 263: productv1.ListOfProduct.List - (*ListOfString_List)(nil), // 264: productv1.ListOfString.List - (*ListOfSubcategory_List)(nil), // 265: productv1.ListOfSubcategory.List - (*ListOfUser_List)(nil), // 266: productv1.ListOfUser.List - (*ListOfUserInput_List)(nil), // 267: productv1.ListOfUserInput.List - (*wrapperspb.Int32Value)(nil), // 268: google.protobuf.Int32Value - (*wrapperspb.BoolValue)(nil), // 269: google.protobuf.BoolValue - (*wrapperspb.StringValue)(nil), // 270: google.protobuf.StringValue - (*wrapperspb.DoubleValue)(nil), // 271: google.protobuf.DoubleValue + (*QueryCategoryRequest)(nil), // 49: productv1.QueryCategoryRequest + (*QueryCategoryResponse)(nil), // 50: productv1.QueryCategoryResponse + (*QueryCategoriesByKindRequest)(nil), // 51: productv1.QueryCategoriesByKindRequest + (*QueryCategoriesByKindResponse)(nil), // 52: productv1.QueryCategoriesByKindResponse + (*QueryCategoriesByKindsRequest)(nil), // 53: productv1.QueryCategoriesByKindsRequest + (*QueryCategoriesByKindsResponse)(nil), // 54: productv1.QueryCategoriesByKindsResponse + (*QueryFilterCategoriesRequest)(nil), // 55: productv1.QueryFilterCategoriesRequest + (*QueryFilterCategoriesResponse)(nil), // 56: productv1.QueryFilterCategoriesResponse + (*QueryRandomPetRequest)(nil), // 57: productv1.QueryRandomPetRequest + (*QueryRandomPetResponse)(nil), // 58: productv1.QueryRandomPetResponse + (*QueryAllPetsRequest)(nil), // 59: productv1.QueryAllPetsRequest + (*QueryAllPetsResponse)(nil), // 60: productv1.QueryAllPetsResponse + (*QuerySearchRequest)(nil), // 61: productv1.QuerySearchRequest + (*QuerySearchResponse)(nil), // 62: productv1.QuerySearchResponse + (*QueryRandomSearchResultRequest)(nil), // 63: productv1.QueryRandomSearchResultRequest + (*QueryRandomSearchResultResponse)(nil), // 64: productv1.QueryRandomSearchResultResponse + (*QueryNullableFieldsTypeRequest)(nil), // 65: productv1.QueryNullableFieldsTypeRequest + (*QueryNullableFieldsTypeResponse)(nil), // 66: productv1.QueryNullableFieldsTypeResponse + (*QueryNullableFieldsTypeByIdRequest)(nil), // 67: productv1.QueryNullableFieldsTypeByIdRequest + (*QueryNullableFieldsTypeByIdResponse)(nil), // 68: productv1.QueryNullableFieldsTypeByIdResponse + (*QueryNullableFieldsTypeWithFilterRequest)(nil), // 69: productv1.QueryNullableFieldsTypeWithFilterRequest + (*QueryNullableFieldsTypeWithFilterResponse)(nil), // 70: productv1.QueryNullableFieldsTypeWithFilterResponse + (*QueryAllNullableFieldsTypesRequest)(nil), // 71: productv1.QueryAllNullableFieldsTypesRequest + (*QueryAllNullableFieldsTypesResponse)(nil), // 72: productv1.QueryAllNullableFieldsTypesResponse + (*QueryBlogPostRequest)(nil), // 73: productv1.QueryBlogPostRequest + (*QueryBlogPostResponse)(nil), // 74: productv1.QueryBlogPostResponse + (*QueryBlogPostByIdRequest)(nil), // 75: productv1.QueryBlogPostByIdRequest + (*QueryBlogPostByIdResponse)(nil), // 76: productv1.QueryBlogPostByIdResponse + (*QueryBlogPostsWithFilterRequest)(nil), // 77: productv1.QueryBlogPostsWithFilterRequest + (*QueryBlogPostsWithFilterResponse)(nil), // 78: productv1.QueryBlogPostsWithFilterResponse + (*QueryAllBlogPostsRequest)(nil), // 79: productv1.QueryAllBlogPostsRequest + (*QueryAllBlogPostsResponse)(nil), // 80: productv1.QueryAllBlogPostsResponse + (*QueryAuthorRequest)(nil), // 81: productv1.QueryAuthorRequest + (*QueryAuthorResponse)(nil), // 82: productv1.QueryAuthorResponse + (*QueryAuthorByIdRequest)(nil), // 83: productv1.QueryAuthorByIdRequest + (*QueryAuthorByIdResponse)(nil), // 84: productv1.QueryAuthorByIdResponse + (*QueryAuthorsWithFilterRequest)(nil), // 85: productv1.QueryAuthorsWithFilterRequest + (*QueryAuthorsWithFilterResponse)(nil), // 86: productv1.QueryAuthorsWithFilterResponse + (*QueryAllAuthorsRequest)(nil), // 87: productv1.QueryAllAuthorsRequest + (*QueryAllAuthorsResponse)(nil), // 88: productv1.QueryAllAuthorsResponse + (*QueryBulkSearchAuthorsRequest)(nil), // 89: productv1.QueryBulkSearchAuthorsRequest + (*QueryBulkSearchAuthorsResponse)(nil), // 90: productv1.QueryBulkSearchAuthorsResponse + (*QueryBulkSearchBlogPostsRequest)(nil), // 91: productv1.QueryBulkSearchBlogPostsRequest + (*QueryBulkSearchBlogPostsResponse)(nil), // 92: productv1.QueryBulkSearchBlogPostsResponse + (*QueryTestContainerRequest)(nil), // 93: productv1.QueryTestContainerRequest + (*QueryTestContainerResponse)(nil), // 94: productv1.QueryTestContainerResponse + (*QueryTestContainersRequest)(nil), // 95: productv1.QueryTestContainersRequest + (*QueryTestContainersResponse)(nil), // 96: productv1.QueryTestContainersResponse + (*MutationCreateUserRequest)(nil), // 97: productv1.MutationCreateUserRequest + (*MutationCreateUserResponse)(nil), // 98: productv1.MutationCreateUserResponse + (*MutationPerformActionRequest)(nil), // 99: productv1.MutationPerformActionRequest + (*MutationPerformActionResponse)(nil), // 100: productv1.MutationPerformActionResponse + (*MutationCreateNullableFieldsTypeRequest)(nil), // 101: productv1.MutationCreateNullableFieldsTypeRequest + (*MutationCreateNullableFieldsTypeResponse)(nil), // 102: productv1.MutationCreateNullableFieldsTypeResponse + (*MutationUpdateNullableFieldsTypeRequest)(nil), // 103: productv1.MutationUpdateNullableFieldsTypeRequest + (*MutationUpdateNullableFieldsTypeResponse)(nil), // 104: productv1.MutationUpdateNullableFieldsTypeResponse + (*MutationCreateBlogPostRequest)(nil), // 105: productv1.MutationCreateBlogPostRequest + (*MutationCreateBlogPostResponse)(nil), // 106: productv1.MutationCreateBlogPostResponse + (*MutationUpdateBlogPostRequest)(nil), // 107: productv1.MutationUpdateBlogPostRequest + (*MutationUpdateBlogPostResponse)(nil), // 108: productv1.MutationUpdateBlogPostResponse + (*MutationCreateAuthorRequest)(nil), // 109: productv1.MutationCreateAuthorRequest + (*MutationCreateAuthorResponse)(nil), // 110: productv1.MutationCreateAuthorResponse + (*MutationUpdateAuthorRequest)(nil), // 111: productv1.MutationUpdateAuthorRequest + (*MutationUpdateAuthorResponse)(nil), // 112: productv1.MutationUpdateAuthorResponse + (*MutationBulkCreateAuthorsRequest)(nil), // 113: productv1.MutationBulkCreateAuthorsRequest + (*MutationBulkCreateAuthorsResponse)(nil), // 114: productv1.MutationBulkCreateAuthorsResponse + (*MutationBulkUpdateAuthorsRequest)(nil), // 115: productv1.MutationBulkUpdateAuthorsRequest + (*MutationBulkUpdateAuthorsResponse)(nil), // 116: productv1.MutationBulkUpdateAuthorsResponse + (*MutationBulkCreateBlogPostsRequest)(nil), // 117: productv1.MutationBulkCreateBlogPostsRequest + (*MutationBulkCreateBlogPostsResponse)(nil), // 118: productv1.MutationBulkCreateBlogPostsResponse + (*MutationBulkUpdateBlogPostsRequest)(nil), // 119: productv1.MutationBulkUpdateBlogPostsRequest + (*MutationBulkUpdateBlogPostsResponse)(nil), // 120: productv1.MutationBulkUpdateBlogPostsResponse + (*ResolveProductShippingEstimateArgs)(nil), // 121: productv1.ResolveProductShippingEstimateArgs + (*ResolveProductShippingEstimateContext)(nil), // 122: productv1.ResolveProductShippingEstimateContext + (*ResolveProductShippingEstimateRequest)(nil), // 123: productv1.ResolveProductShippingEstimateRequest + (*ResolveProductShippingEstimateResult)(nil), // 124: productv1.ResolveProductShippingEstimateResult + (*ResolveProductShippingEstimateResponse)(nil), // 125: productv1.ResolveProductShippingEstimateResponse + (*ResolveProductRecommendedCategoryArgs)(nil), // 126: productv1.ResolveProductRecommendedCategoryArgs + (*ResolveProductRecommendedCategoryContext)(nil), // 127: productv1.ResolveProductRecommendedCategoryContext + (*ResolveProductRecommendedCategoryRequest)(nil), // 128: productv1.ResolveProductRecommendedCategoryRequest + (*ResolveProductRecommendedCategoryResult)(nil), // 129: productv1.ResolveProductRecommendedCategoryResult + (*ResolveProductRecommendedCategoryResponse)(nil), // 130: productv1.ResolveProductRecommendedCategoryResponse + (*ResolveProductMascotRecommendationArgs)(nil), // 131: productv1.ResolveProductMascotRecommendationArgs + (*ResolveProductMascotRecommendationContext)(nil), // 132: productv1.ResolveProductMascotRecommendationContext + (*ResolveProductMascotRecommendationRequest)(nil), // 133: productv1.ResolveProductMascotRecommendationRequest + (*ResolveProductMascotRecommendationResult)(nil), // 134: productv1.ResolveProductMascotRecommendationResult + (*ResolveProductMascotRecommendationResponse)(nil), // 135: productv1.ResolveProductMascotRecommendationResponse + (*ResolveProductStockStatusArgs)(nil), // 136: productv1.ResolveProductStockStatusArgs + (*ResolveProductStockStatusContext)(nil), // 137: productv1.ResolveProductStockStatusContext + (*ResolveProductStockStatusRequest)(nil), // 138: productv1.ResolveProductStockStatusRequest + (*ResolveProductStockStatusResult)(nil), // 139: productv1.ResolveProductStockStatusResult + (*ResolveProductStockStatusResponse)(nil), // 140: productv1.ResolveProductStockStatusResponse + (*ResolveProductProductDetailsArgs)(nil), // 141: productv1.ResolveProductProductDetailsArgs + (*ResolveProductProductDetailsContext)(nil), // 142: productv1.ResolveProductProductDetailsContext + (*ResolveProductProductDetailsRequest)(nil), // 143: productv1.ResolveProductProductDetailsRequest + (*ResolveProductProductDetailsResult)(nil), // 144: productv1.ResolveProductProductDetailsResult + (*ResolveProductProductDetailsResponse)(nil), // 145: productv1.ResolveProductProductDetailsResponse + (*ResolveCategoryProductCountArgs)(nil), // 146: productv1.ResolveCategoryProductCountArgs + (*ResolveCategoryProductCountContext)(nil), // 147: productv1.ResolveCategoryProductCountContext + (*ResolveCategoryProductCountRequest)(nil), // 148: productv1.ResolveCategoryProductCountRequest + (*ResolveCategoryProductCountResult)(nil), // 149: productv1.ResolveCategoryProductCountResult + (*ResolveCategoryProductCountResponse)(nil), // 150: productv1.ResolveCategoryProductCountResponse + (*ResolveCategoryPopularityScoreArgs)(nil), // 151: productv1.ResolveCategoryPopularityScoreArgs + (*ResolveCategoryPopularityScoreContext)(nil), // 152: productv1.ResolveCategoryPopularityScoreContext + (*ResolveCategoryPopularityScoreRequest)(nil), // 153: productv1.ResolveCategoryPopularityScoreRequest + (*ResolveCategoryPopularityScoreResult)(nil), // 154: productv1.ResolveCategoryPopularityScoreResult + (*ResolveCategoryPopularityScoreResponse)(nil), // 155: productv1.ResolveCategoryPopularityScoreResponse + (*ResolveCategoryCategoryMetricsArgs)(nil), // 156: productv1.ResolveCategoryCategoryMetricsArgs + (*ResolveCategoryCategoryMetricsContext)(nil), // 157: productv1.ResolveCategoryCategoryMetricsContext + (*ResolveCategoryCategoryMetricsRequest)(nil), // 158: productv1.ResolveCategoryCategoryMetricsRequest + (*ResolveCategoryCategoryMetricsResult)(nil), // 159: productv1.ResolveCategoryCategoryMetricsResult + (*ResolveCategoryCategoryMetricsResponse)(nil), // 160: productv1.ResolveCategoryCategoryMetricsResponse + (*ResolveCategoryMascotArgs)(nil), // 161: productv1.ResolveCategoryMascotArgs + (*ResolveCategoryMascotContext)(nil), // 162: productv1.ResolveCategoryMascotContext + (*ResolveCategoryMascotRequest)(nil), // 163: productv1.ResolveCategoryMascotRequest + (*ResolveCategoryMascotResult)(nil), // 164: productv1.ResolveCategoryMascotResult + (*ResolveCategoryMascotResponse)(nil), // 165: productv1.ResolveCategoryMascotResponse + (*ResolveCategoryCategoryStatusArgs)(nil), // 166: productv1.ResolveCategoryCategoryStatusArgs + (*ResolveCategoryCategoryStatusContext)(nil), // 167: productv1.ResolveCategoryCategoryStatusContext + (*ResolveCategoryCategoryStatusRequest)(nil), // 168: productv1.ResolveCategoryCategoryStatusRequest + (*ResolveCategoryCategoryStatusResult)(nil), // 169: productv1.ResolveCategoryCategoryStatusResult + (*ResolveCategoryCategoryStatusResponse)(nil), // 170: productv1.ResolveCategoryCategoryStatusResponse + (*ResolveCategoryChildCategoriesArgs)(nil), // 171: productv1.ResolveCategoryChildCategoriesArgs + (*ResolveCategoryChildCategoriesContext)(nil), // 172: productv1.ResolveCategoryChildCategoriesContext + (*ResolveCategoryChildCategoriesRequest)(nil), // 173: productv1.ResolveCategoryChildCategoriesRequest + (*ResolveCategoryChildCategoriesResult)(nil), // 174: productv1.ResolveCategoryChildCategoriesResult + (*ResolveCategoryChildCategoriesResponse)(nil), // 175: productv1.ResolveCategoryChildCategoriesResponse + (*ResolveCategoryOptionalCategoriesArgs)(nil), // 176: productv1.ResolveCategoryOptionalCategoriesArgs + (*ResolveCategoryOptionalCategoriesContext)(nil), // 177: productv1.ResolveCategoryOptionalCategoriesContext + (*ResolveCategoryOptionalCategoriesRequest)(nil), // 178: productv1.ResolveCategoryOptionalCategoriesRequest + (*ResolveCategoryOptionalCategoriesResult)(nil), // 179: productv1.ResolveCategoryOptionalCategoriesResult + (*ResolveCategoryOptionalCategoriesResponse)(nil), // 180: productv1.ResolveCategoryOptionalCategoriesResponse + (*ResolveSubcategoryItemCountArgs)(nil), // 181: productv1.ResolveSubcategoryItemCountArgs + (*ResolveSubcategoryItemCountContext)(nil), // 182: productv1.ResolveSubcategoryItemCountContext + (*ResolveSubcategoryItemCountRequest)(nil), // 183: productv1.ResolveSubcategoryItemCountRequest + (*ResolveSubcategoryItemCountResult)(nil), // 184: productv1.ResolveSubcategoryItemCountResult + (*ResolveSubcategoryItemCountResponse)(nil), // 185: productv1.ResolveSubcategoryItemCountResponse + (*ResolveSubcategoryFeaturedCategoryArgs)(nil), // 186: productv1.ResolveSubcategoryFeaturedCategoryArgs + (*ResolveSubcategoryFeaturedCategoryContext)(nil), // 187: productv1.ResolveSubcategoryFeaturedCategoryContext + (*ResolveSubcategoryFeaturedCategoryRequest)(nil), // 188: productv1.ResolveSubcategoryFeaturedCategoryRequest + (*ResolveSubcategoryFeaturedCategoryResult)(nil), // 189: productv1.ResolveSubcategoryFeaturedCategoryResult + (*ResolveSubcategoryFeaturedCategoryResponse)(nil), // 190: productv1.ResolveSubcategoryFeaturedCategoryResponse + (*ResolveCategoryMetricsNormalizedScoreArgs)(nil), // 191: productv1.ResolveCategoryMetricsNormalizedScoreArgs + (*ResolveCategoryMetricsNormalizedScoreContext)(nil), // 192: productv1.ResolveCategoryMetricsNormalizedScoreContext + (*ResolveCategoryMetricsNormalizedScoreRequest)(nil), // 193: productv1.ResolveCategoryMetricsNormalizedScoreRequest + (*ResolveCategoryMetricsNormalizedScoreResult)(nil), // 194: productv1.ResolveCategoryMetricsNormalizedScoreResult + (*ResolveCategoryMetricsNormalizedScoreResponse)(nil), // 195: productv1.ResolveCategoryMetricsNormalizedScoreResponse + (*ResolveCategoryMetricsRelatedCategoryArgs)(nil), // 196: productv1.ResolveCategoryMetricsRelatedCategoryArgs + (*ResolveCategoryMetricsRelatedCategoryContext)(nil), // 197: productv1.ResolveCategoryMetricsRelatedCategoryContext + (*ResolveCategoryMetricsRelatedCategoryRequest)(nil), // 198: productv1.ResolveCategoryMetricsRelatedCategoryRequest + (*ResolveCategoryMetricsRelatedCategoryResult)(nil), // 199: productv1.ResolveCategoryMetricsRelatedCategoryResult + (*ResolveCategoryMetricsRelatedCategoryResponse)(nil), // 200: productv1.ResolveCategoryMetricsRelatedCategoryResponse + (*ResolveTestContainerDetailsArgs)(nil), // 201: productv1.ResolveTestContainerDetailsArgs + (*ResolveTestContainerDetailsContext)(nil), // 202: productv1.ResolveTestContainerDetailsContext + (*ResolveTestContainerDetailsRequest)(nil), // 203: productv1.ResolveTestContainerDetailsRequest + (*ResolveTestContainerDetailsResult)(nil), // 204: productv1.ResolveTestContainerDetailsResult + (*ResolveTestContainerDetailsResponse)(nil), // 205: productv1.ResolveTestContainerDetailsResponse + (*Product)(nil), // 206: productv1.Product + (*Storage)(nil), // 207: productv1.Storage + (*Warehouse)(nil), // 208: productv1.Warehouse + (*User)(nil), // 209: productv1.User + (*NestedTypeA)(nil), // 210: productv1.NestedTypeA + (*RecursiveType)(nil), // 211: productv1.RecursiveType + (*TypeWithMultipleFilterFields)(nil), // 212: productv1.TypeWithMultipleFilterFields + (*FilterTypeInput)(nil), // 213: productv1.FilterTypeInput + (*ComplexFilterTypeInput)(nil), // 214: productv1.ComplexFilterTypeInput + (*TypeWithComplexFilterInput)(nil), // 215: productv1.TypeWithComplexFilterInput + (*OrderInput)(nil), // 216: productv1.OrderInput + (*Order)(nil), // 217: productv1.Order + (*Category)(nil), // 218: productv1.Category + (*CategoryFilter)(nil), // 219: productv1.CategoryFilter + (*Animal)(nil), // 220: productv1.Animal + (*SearchInput)(nil), // 221: productv1.SearchInput + (*SearchResult)(nil), // 222: productv1.SearchResult + (*NullableFieldsType)(nil), // 223: productv1.NullableFieldsType + (*NullableFieldsFilter)(nil), // 224: productv1.NullableFieldsFilter + (*BlogPost)(nil), // 225: productv1.BlogPost + (*BlogPostFilter)(nil), // 226: productv1.BlogPostFilter + (*Author)(nil), // 227: productv1.Author + (*AuthorFilter)(nil), // 228: productv1.AuthorFilter + (*TestContainer)(nil), // 229: productv1.TestContainer + (*UserInput)(nil), // 230: productv1.UserInput + (*ActionInput)(nil), // 231: productv1.ActionInput + (*ActionResult)(nil), // 232: productv1.ActionResult + (*NullableFieldsInput)(nil), // 233: productv1.NullableFieldsInput + (*BlogPostInput)(nil), // 234: productv1.BlogPostInput + (*AuthorInput)(nil), // 235: productv1.AuthorInput + (*ProductDetails)(nil), // 236: productv1.ProductDetails + (*NestedTypeB)(nil), // 237: productv1.NestedTypeB + (*NestedTypeC)(nil), // 238: productv1.NestedTypeC + (*FilterType)(nil), // 239: productv1.FilterType + (*Pagination)(nil), // 240: productv1.Pagination + (*OrderLineInput)(nil), // 241: productv1.OrderLineInput + (*OrderLine)(nil), // 242: productv1.OrderLine + (*Subcategory)(nil), // 243: productv1.Subcategory + (*CategoryMetrics)(nil), // 244: productv1.CategoryMetrics + (*Cat)(nil), // 245: productv1.Cat + (*Dog)(nil), // 246: productv1.Dog + (*Owner)(nil), // 247: productv1.Owner + (*ContactInfo)(nil), // 248: productv1.ContactInfo + (*Address)(nil), // 249: productv1.Address + (*CatBreed)(nil), // 250: productv1.CatBreed + (*DogBreed)(nil), // 251: productv1.DogBreed + (*BreedCharacteristics)(nil), // 252: productv1.BreedCharacteristics + (*ActionSuccess)(nil), // 253: productv1.ActionSuccess + (*ActionError)(nil), // 254: productv1.ActionError + (*TestDetails)(nil), // 255: productv1.TestDetails + (*CategoryInput)(nil), // 256: productv1.CategoryInput + (*ProductCountFilter)(nil), // 257: productv1.ProductCountFilter + (*SubcategoryItemFilter)(nil), // 258: productv1.SubcategoryItemFilter + (*ShippingEstimateInput)(nil), // 259: productv1.ShippingEstimateInput + (*ListOfAuthorFilter_List)(nil), // 260: productv1.ListOfAuthorFilter.List + (*ListOfAuthorInput_List)(nil), // 261: productv1.ListOfAuthorInput.List + (*ListOfBlogPost_List)(nil), // 262: productv1.ListOfBlogPost.List + (*ListOfBlogPostFilter_List)(nil), // 263: productv1.ListOfBlogPostFilter.List + (*ListOfBlogPostInput_List)(nil), // 264: productv1.ListOfBlogPostInput.List + (*ListOfBoolean_List)(nil), // 265: productv1.ListOfBoolean.List + (*ListOfCategory_List)(nil), // 266: productv1.ListOfCategory.List + (*ListOfCategoryInput_List)(nil), // 267: productv1.ListOfCategoryInput.List + (*ListOfFloat_List)(nil), // 268: productv1.ListOfFloat.List + (*ListOfListOfCategory_List)(nil), // 269: productv1.ListOfListOfCategory.List + (*ListOfListOfCategoryInput_List)(nil), // 270: productv1.ListOfListOfCategoryInput.List + (*ListOfListOfString_List)(nil), // 271: productv1.ListOfListOfString.List + (*ListOfListOfUser_List)(nil), // 272: productv1.ListOfListOfUser.List + (*ListOfListOfUserInput_List)(nil), // 273: productv1.ListOfListOfUserInput.List + (*ListOfOrderLine_List)(nil), // 274: productv1.ListOfOrderLine.List + (*ListOfProduct_List)(nil), // 275: productv1.ListOfProduct.List + (*ListOfString_List)(nil), // 276: productv1.ListOfString.List + (*ListOfSubcategory_List)(nil), // 277: productv1.ListOfSubcategory.List + (*ListOfUser_List)(nil), // 278: productv1.ListOfUser.List + (*ListOfUserInput_List)(nil), // 279: productv1.ListOfUserInput.List + (*wrapperspb.Int32Value)(nil), // 280: google.protobuf.Int32Value + (*wrapperspb.BoolValue)(nil), // 281: google.protobuf.BoolValue + (*wrapperspb.StringValue)(nil), // 282: google.protobuf.StringValue + (*wrapperspb.DoubleValue)(nil), // 283: google.protobuf.DoubleValue } var file_product_proto_depIdxs = []int32{ - 248, // 0: productv1.ListOfAuthorFilter.list:type_name -> productv1.ListOfAuthorFilter.List - 249, // 1: productv1.ListOfAuthorInput.list:type_name -> productv1.ListOfAuthorInput.List - 250, // 2: productv1.ListOfBlogPost.list:type_name -> productv1.ListOfBlogPost.List - 251, // 3: productv1.ListOfBlogPostFilter.list:type_name -> productv1.ListOfBlogPostFilter.List - 252, // 4: productv1.ListOfBlogPostInput.list:type_name -> productv1.ListOfBlogPostInput.List - 253, // 5: productv1.ListOfBoolean.list:type_name -> productv1.ListOfBoolean.List - 254, // 6: productv1.ListOfCategory.list:type_name -> productv1.ListOfCategory.List - 255, // 7: productv1.ListOfCategoryInput.list:type_name -> productv1.ListOfCategoryInput.List - 256, // 8: productv1.ListOfFloat.list:type_name -> productv1.ListOfFloat.List - 257, // 9: productv1.ListOfListOfCategory.list:type_name -> productv1.ListOfListOfCategory.List - 258, // 10: productv1.ListOfListOfCategoryInput.list:type_name -> productv1.ListOfListOfCategoryInput.List - 259, // 11: productv1.ListOfListOfString.list:type_name -> productv1.ListOfListOfString.List - 260, // 12: productv1.ListOfListOfUser.list:type_name -> productv1.ListOfListOfUser.List - 261, // 13: productv1.ListOfListOfUserInput.list:type_name -> productv1.ListOfListOfUserInput.List - 262, // 14: productv1.ListOfOrderLine.list:type_name -> productv1.ListOfOrderLine.List - 263, // 15: productv1.ListOfProduct.list:type_name -> productv1.ListOfProduct.List - 264, // 16: productv1.ListOfString.list:type_name -> productv1.ListOfString.List - 265, // 17: productv1.ListOfSubcategory.list:type_name -> productv1.ListOfSubcategory.List - 266, // 18: productv1.ListOfUser.list:type_name -> productv1.ListOfUser.List - 267, // 19: productv1.ListOfUserInput.list:type_name -> productv1.ListOfUserInput.List + 260, // 0: productv1.ListOfAuthorFilter.list:type_name -> productv1.ListOfAuthorFilter.List + 261, // 1: productv1.ListOfAuthorInput.list:type_name -> productv1.ListOfAuthorInput.List + 262, // 2: productv1.ListOfBlogPost.list:type_name -> productv1.ListOfBlogPost.List + 263, // 3: productv1.ListOfBlogPostFilter.list:type_name -> productv1.ListOfBlogPostFilter.List + 264, // 4: productv1.ListOfBlogPostInput.list:type_name -> productv1.ListOfBlogPostInput.List + 265, // 5: productv1.ListOfBoolean.list:type_name -> productv1.ListOfBoolean.List + 266, // 6: productv1.ListOfCategory.list:type_name -> productv1.ListOfCategory.List + 267, // 7: productv1.ListOfCategoryInput.list:type_name -> productv1.ListOfCategoryInput.List + 268, // 8: productv1.ListOfFloat.list:type_name -> productv1.ListOfFloat.List + 269, // 9: productv1.ListOfListOfCategory.list:type_name -> productv1.ListOfListOfCategory.List + 270, // 10: productv1.ListOfListOfCategoryInput.list:type_name -> productv1.ListOfListOfCategoryInput.List + 271, // 11: productv1.ListOfListOfString.list:type_name -> productv1.ListOfListOfString.List + 272, // 12: productv1.ListOfListOfUser.list:type_name -> productv1.ListOfListOfUser.List + 273, // 13: productv1.ListOfListOfUserInput.list:type_name -> productv1.ListOfListOfUserInput.List + 274, // 14: productv1.ListOfOrderLine.list:type_name -> productv1.ListOfOrderLine.List + 275, // 15: productv1.ListOfProduct.list:type_name -> productv1.ListOfProduct.List + 276, // 16: productv1.ListOfString.list:type_name -> productv1.ListOfString.List + 277, // 17: productv1.ListOfSubcategory.list:type_name -> productv1.ListOfSubcategory.List + 278, // 18: productv1.ListOfUser.list:type_name -> productv1.ListOfUser.List + 279, // 19: productv1.ListOfUserInput.list:type_name -> productv1.ListOfUserInput.List 22, // 20: productv1.LookupProductByIdRequest.keys:type_name -> productv1.LookupProductByIdRequestKey - 194, // 21: productv1.LookupProductByIdResponse.result:type_name -> productv1.Product + 206, // 21: productv1.LookupProductByIdResponse.result:type_name -> productv1.Product 25, // 22: productv1.LookupStorageByIdRequest.keys:type_name -> productv1.LookupStorageByIdRequestKey - 195, // 23: productv1.LookupStorageByIdResponse.result:type_name -> productv1.Storage + 207, // 23: productv1.LookupStorageByIdResponse.result:type_name -> productv1.Storage 28, // 24: productv1.LookupWarehouseByIdRequest.keys:type_name -> productv1.LookupWarehouseByIdRequestKey - 196, // 25: productv1.LookupWarehouseByIdResponse.result:type_name -> productv1.Warehouse - 197, // 26: productv1.QueryUsersResponse.users:type_name -> productv1.User - 197, // 27: productv1.QueryUserResponse.user:type_name -> productv1.User - 198, // 28: productv1.QueryNestedTypeResponse.nested_type:type_name -> productv1.NestedTypeA - 199, // 29: productv1.QueryRecursiveTypeResponse.recursive_type:type_name -> productv1.RecursiveType - 200, // 30: productv1.QueryTypeFilterWithArgumentsResponse.type_filter_with_arguments:type_name -> productv1.TypeWithMultipleFilterFields - 201, // 31: productv1.QueryTypeWithMultipleFilterFieldsRequest.filter:type_name -> productv1.FilterTypeInput - 200, // 32: productv1.QueryTypeWithMultipleFilterFieldsResponse.type_with_multiple_filter_fields:type_name -> productv1.TypeWithMultipleFilterFields - 202, // 33: productv1.QueryComplexFilterTypeRequest.filter:type_name -> productv1.ComplexFilterTypeInput - 203, // 34: productv1.QueryComplexFilterTypeResponse.complex_filter_type:type_name -> productv1.TypeWithComplexFilterInput - 204, // 35: productv1.QueryCalculateTotalsRequest.orders:type_name -> productv1.OrderInput - 205, // 36: productv1.QueryCalculateTotalsResponse.calculate_totals:type_name -> productv1.Order - 206, // 37: productv1.QueryCategoriesResponse.categories:type_name -> productv1.Category - 0, // 38: productv1.QueryCategoriesByKindRequest.kind:type_name -> productv1.CategoryKind - 206, // 39: productv1.QueryCategoriesByKindResponse.categories_by_kind:type_name -> productv1.Category - 0, // 40: productv1.QueryCategoriesByKindsRequest.kinds:type_name -> productv1.CategoryKind - 206, // 41: productv1.QueryCategoriesByKindsResponse.categories_by_kinds:type_name -> productv1.Category - 207, // 42: productv1.QueryFilterCategoriesRequest.filter:type_name -> productv1.CategoryFilter - 206, // 43: productv1.QueryFilterCategoriesResponse.filter_categories:type_name -> productv1.Category - 208, // 44: productv1.QueryRandomPetResponse.random_pet:type_name -> productv1.Animal - 208, // 45: productv1.QueryAllPetsResponse.all_pets:type_name -> productv1.Animal - 209, // 46: productv1.QuerySearchRequest.input:type_name -> productv1.SearchInput - 210, // 47: productv1.QuerySearchResponse.search:type_name -> productv1.SearchResult - 210, // 48: productv1.QueryRandomSearchResultResponse.random_search_result:type_name -> productv1.SearchResult - 211, // 49: productv1.QueryNullableFieldsTypeResponse.nullable_fields_type:type_name -> productv1.NullableFieldsType - 211, // 50: productv1.QueryNullableFieldsTypeByIdResponse.nullable_fields_type_by_id:type_name -> productv1.NullableFieldsType - 212, // 51: productv1.QueryNullableFieldsTypeWithFilterRequest.filter:type_name -> productv1.NullableFieldsFilter - 211, // 52: productv1.QueryNullableFieldsTypeWithFilterResponse.nullable_fields_type_with_filter:type_name -> productv1.NullableFieldsType - 211, // 53: productv1.QueryAllNullableFieldsTypesResponse.all_nullable_fields_types:type_name -> productv1.NullableFieldsType - 213, // 54: productv1.QueryBlogPostResponse.blog_post:type_name -> productv1.BlogPost - 213, // 55: productv1.QueryBlogPostByIdResponse.blog_post_by_id:type_name -> productv1.BlogPost - 214, // 56: productv1.QueryBlogPostsWithFilterRequest.filter:type_name -> productv1.BlogPostFilter - 213, // 57: productv1.QueryBlogPostsWithFilterResponse.blog_posts_with_filter:type_name -> productv1.BlogPost - 213, // 58: productv1.QueryAllBlogPostsResponse.all_blog_posts:type_name -> productv1.BlogPost - 215, // 59: productv1.QueryAuthorResponse.author:type_name -> productv1.Author - 215, // 60: productv1.QueryAuthorByIdResponse.author_by_id:type_name -> productv1.Author - 216, // 61: productv1.QueryAuthorsWithFilterRequest.filter:type_name -> productv1.AuthorFilter - 215, // 62: productv1.QueryAuthorsWithFilterResponse.authors_with_filter:type_name -> productv1.Author - 215, // 63: productv1.QueryAllAuthorsResponse.all_authors:type_name -> productv1.Author - 2, // 64: productv1.QueryBulkSearchAuthorsRequest.filters:type_name -> productv1.ListOfAuthorFilter - 215, // 65: productv1.QueryBulkSearchAuthorsResponse.bulk_search_authors:type_name -> productv1.Author - 5, // 66: productv1.QueryBulkSearchBlogPostsRequest.filters:type_name -> productv1.ListOfBlogPostFilter - 213, // 67: productv1.QueryBulkSearchBlogPostsResponse.bulk_search_blog_posts:type_name -> productv1.BlogPost - 217, // 68: productv1.QueryTestContainerResponse.test_container:type_name -> productv1.TestContainer - 217, // 69: productv1.QueryTestContainersResponse.test_containers:type_name -> productv1.TestContainer - 218, // 70: productv1.MutationCreateUserRequest.input:type_name -> productv1.UserInput - 197, // 71: productv1.MutationCreateUserResponse.create_user:type_name -> productv1.User - 219, // 72: productv1.MutationPerformActionRequest.input:type_name -> productv1.ActionInput - 220, // 73: productv1.MutationPerformActionResponse.perform_action:type_name -> productv1.ActionResult - 221, // 74: productv1.MutationCreateNullableFieldsTypeRequest.input:type_name -> productv1.NullableFieldsInput - 211, // 75: productv1.MutationCreateNullableFieldsTypeResponse.create_nullable_fields_type:type_name -> productv1.NullableFieldsType - 221, // 76: productv1.MutationUpdateNullableFieldsTypeRequest.input:type_name -> productv1.NullableFieldsInput - 211, // 77: productv1.MutationUpdateNullableFieldsTypeResponse.update_nullable_fields_type:type_name -> productv1.NullableFieldsType - 222, // 78: productv1.MutationCreateBlogPostRequest.input:type_name -> productv1.BlogPostInput - 213, // 79: productv1.MutationCreateBlogPostResponse.create_blog_post:type_name -> productv1.BlogPost - 222, // 80: productv1.MutationUpdateBlogPostRequest.input:type_name -> productv1.BlogPostInput - 213, // 81: productv1.MutationUpdateBlogPostResponse.update_blog_post:type_name -> productv1.BlogPost - 223, // 82: productv1.MutationCreateAuthorRequest.input:type_name -> productv1.AuthorInput - 215, // 83: productv1.MutationCreateAuthorResponse.create_author:type_name -> productv1.Author - 223, // 84: productv1.MutationUpdateAuthorRequest.input:type_name -> productv1.AuthorInput - 215, // 85: productv1.MutationUpdateAuthorResponse.update_author:type_name -> productv1.Author - 3, // 86: productv1.MutationBulkCreateAuthorsRequest.authors:type_name -> productv1.ListOfAuthorInput - 215, // 87: productv1.MutationBulkCreateAuthorsResponse.bulk_create_authors:type_name -> productv1.Author - 3, // 88: productv1.MutationBulkUpdateAuthorsRequest.authors:type_name -> productv1.ListOfAuthorInput - 215, // 89: productv1.MutationBulkUpdateAuthorsResponse.bulk_update_authors:type_name -> productv1.Author - 6, // 90: productv1.MutationBulkCreateBlogPostsRequest.blog_posts:type_name -> productv1.ListOfBlogPostInput - 213, // 91: productv1.MutationBulkCreateBlogPostsResponse.bulk_create_blog_posts:type_name -> productv1.BlogPost - 6, // 92: productv1.MutationBulkUpdateBlogPostsRequest.blog_posts:type_name -> productv1.ListOfBlogPostInput - 213, // 93: productv1.MutationBulkUpdateBlogPostsResponse.bulk_update_blog_posts:type_name -> productv1.BlogPost - 247, // 94: productv1.ResolveProductShippingEstimateArgs.input:type_name -> productv1.ShippingEstimateInput - 120, // 95: productv1.ResolveProductShippingEstimateRequest.context:type_name -> productv1.ResolveProductShippingEstimateContext - 119, // 96: productv1.ResolveProductShippingEstimateRequest.field_args:type_name -> productv1.ResolveProductShippingEstimateArgs - 122, // 97: productv1.ResolveProductShippingEstimateResponse.result:type_name -> productv1.ResolveProductShippingEstimateResult - 125, // 98: productv1.ResolveProductRecommendedCategoryRequest.context:type_name -> productv1.ResolveProductRecommendedCategoryContext - 124, // 99: productv1.ResolveProductRecommendedCategoryRequest.field_args:type_name -> productv1.ResolveProductRecommendedCategoryArgs - 206, // 100: productv1.ResolveProductRecommendedCategoryResult.recommended_category:type_name -> productv1.Category - 127, // 101: productv1.ResolveProductRecommendedCategoryResponse.result:type_name -> productv1.ResolveProductRecommendedCategoryResult - 130, // 102: productv1.ResolveProductMascotRecommendationRequest.context:type_name -> productv1.ResolveProductMascotRecommendationContext - 129, // 103: productv1.ResolveProductMascotRecommendationRequest.field_args:type_name -> productv1.ResolveProductMascotRecommendationArgs - 208, // 104: productv1.ResolveProductMascotRecommendationResult.mascot_recommendation:type_name -> productv1.Animal - 132, // 105: productv1.ResolveProductMascotRecommendationResponse.result:type_name -> productv1.ResolveProductMascotRecommendationResult - 135, // 106: productv1.ResolveProductStockStatusRequest.context:type_name -> productv1.ResolveProductStockStatusContext - 134, // 107: productv1.ResolveProductStockStatusRequest.field_args:type_name -> productv1.ResolveProductStockStatusArgs - 220, // 108: productv1.ResolveProductStockStatusResult.stock_status:type_name -> productv1.ActionResult - 137, // 109: productv1.ResolveProductStockStatusResponse.result:type_name -> productv1.ResolveProductStockStatusResult - 140, // 110: productv1.ResolveProductProductDetailsRequest.context:type_name -> productv1.ResolveProductProductDetailsContext - 139, // 111: productv1.ResolveProductProductDetailsRequest.field_args:type_name -> productv1.ResolveProductProductDetailsArgs - 224, // 112: productv1.ResolveProductProductDetailsResult.product_details:type_name -> productv1.ProductDetails - 142, // 113: productv1.ResolveProductProductDetailsResponse.result:type_name -> productv1.ResolveProductProductDetailsResult - 245, // 114: productv1.ResolveCategoryProductCountArgs.filters:type_name -> productv1.ProductCountFilter - 145, // 115: productv1.ResolveCategoryProductCountRequest.context:type_name -> productv1.ResolveCategoryProductCountContext - 144, // 116: productv1.ResolveCategoryProductCountRequest.field_args:type_name -> productv1.ResolveCategoryProductCountArgs - 147, // 117: productv1.ResolveCategoryProductCountResponse.result:type_name -> productv1.ResolveCategoryProductCountResult - 268, // 118: productv1.ResolveCategoryPopularityScoreArgs.threshold:type_name -> google.protobuf.Int32Value - 150, // 119: productv1.ResolveCategoryPopularityScoreRequest.context:type_name -> productv1.ResolveCategoryPopularityScoreContext - 149, // 120: productv1.ResolveCategoryPopularityScoreRequest.field_args:type_name -> productv1.ResolveCategoryPopularityScoreArgs - 268, // 121: productv1.ResolveCategoryPopularityScoreResult.popularity_score:type_name -> google.protobuf.Int32Value - 152, // 122: productv1.ResolveCategoryPopularityScoreResponse.result:type_name -> productv1.ResolveCategoryPopularityScoreResult - 155, // 123: productv1.ResolveCategoryCategoryMetricsRequest.context:type_name -> productv1.ResolveCategoryCategoryMetricsContext - 154, // 124: productv1.ResolveCategoryCategoryMetricsRequest.field_args:type_name -> productv1.ResolveCategoryCategoryMetricsArgs - 232, // 125: productv1.ResolveCategoryCategoryMetricsResult.category_metrics:type_name -> productv1.CategoryMetrics - 157, // 126: productv1.ResolveCategoryCategoryMetricsResponse.result:type_name -> productv1.ResolveCategoryCategoryMetricsResult - 0, // 127: productv1.ResolveCategoryMascotContext.kind:type_name -> productv1.CategoryKind - 160, // 128: productv1.ResolveCategoryMascotRequest.context:type_name -> productv1.ResolveCategoryMascotContext - 159, // 129: productv1.ResolveCategoryMascotRequest.field_args:type_name -> productv1.ResolveCategoryMascotArgs - 208, // 130: productv1.ResolveCategoryMascotResult.mascot:type_name -> productv1.Animal - 162, // 131: productv1.ResolveCategoryMascotResponse.result:type_name -> productv1.ResolveCategoryMascotResult - 165, // 132: productv1.ResolveCategoryCategoryStatusRequest.context:type_name -> productv1.ResolveCategoryCategoryStatusContext - 164, // 133: productv1.ResolveCategoryCategoryStatusRequest.field_args:type_name -> productv1.ResolveCategoryCategoryStatusArgs - 220, // 134: productv1.ResolveCategoryCategoryStatusResult.category_status:type_name -> productv1.ActionResult - 167, // 135: productv1.ResolveCategoryCategoryStatusResponse.result:type_name -> productv1.ResolveCategoryCategoryStatusResult - 269, // 136: productv1.ResolveCategoryChildCategoriesArgs.include:type_name -> google.protobuf.BoolValue - 170, // 137: productv1.ResolveCategoryChildCategoriesRequest.context:type_name -> productv1.ResolveCategoryChildCategoriesContext - 169, // 138: productv1.ResolveCategoryChildCategoriesRequest.field_args:type_name -> productv1.ResolveCategoryChildCategoriesArgs - 206, // 139: productv1.ResolveCategoryChildCategoriesResult.child_categories:type_name -> productv1.Category - 172, // 140: productv1.ResolveCategoryChildCategoriesResponse.result:type_name -> productv1.ResolveCategoryChildCategoriesResult - 269, // 141: productv1.ResolveCategoryOptionalCategoriesArgs.include:type_name -> google.protobuf.BoolValue - 175, // 142: productv1.ResolveCategoryOptionalCategoriesRequest.context:type_name -> productv1.ResolveCategoryOptionalCategoriesContext - 174, // 143: productv1.ResolveCategoryOptionalCategoriesRequest.field_args:type_name -> productv1.ResolveCategoryOptionalCategoriesArgs - 8, // 144: productv1.ResolveCategoryOptionalCategoriesResult.optional_categories:type_name -> productv1.ListOfCategory - 177, // 145: productv1.ResolveCategoryOptionalCategoriesResponse.result:type_name -> productv1.ResolveCategoryOptionalCategoriesResult - 246, // 146: productv1.ResolveSubcategoryItemCountArgs.filters:type_name -> productv1.SubcategoryItemFilter - 180, // 147: productv1.ResolveSubcategoryItemCountRequest.context:type_name -> productv1.ResolveSubcategoryItemCountContext - 179, // 148: productv1.ResolveSubcategoryItemCountRequest.field_args:type_name -> productv1.ResolveSubcategoryItemCountArgs - 182, // 149: productv1.ResolveSubcategoryItemCountResponse.result:type_name -> productv1.ResolveSubcategoryItemCountResult - 185, // 150: productv1.ResolveCategoryMetricsNormalizedScoreRequest.context:type_name -> productv1.ResolveCategoryMetricsNormalizedScoreContext - 184, // 151: productv1.ResolveCategoryMetricsNormalizedScoreRequest.field_args:type_name -> productv1.ResolveCategoryMetricsNormalizedScoreArgs - 187, // 152: productv1.ResolveCategoryMetricsNormalizedScoreResponse.result:type_name -> productv1.ResolveCategoryMetricsNormalizedScoreResult - 190, // 153: productv1.ResolveTestContainerDetailsRequest.context:type_name -> productv1.ResolveTestContainerDetailsContext - 189, // 154: productv1.ResolveTestContainerDetailsRequest.field_args:type_name -> productv1.ResolveTestContainerDetailsArgs - 243, // 155: productv1.ResolveTestContainerDetailsResult.details:type_name -> productv1.TestDetails - 192, // 156: productv1.ResolveTestContainerDetailsResponse.result:type_name -> productv1.ResolveTestContainerDetailsResult - 225, // 157: productv1.NestedTypeA.b:type_name -> productv1.NestedTypeB - 199, // 158: productv1.RecursiveType.recursive_type:type_name -> productv1.RecursiveType - 227, // 159: productv1.ComplexFilterTypeInput.filter:type_name -> productv1.FilterType - 229, // 160: productv1.OrderInput.lines:type_name -> productv1.OrderLineInput - 16, // 161: productv1.Order.order_lines:type_name -> productv1.ListOfOrderLine - 0, // 162: productv1.Category.kind:type_name -> productv1.CategoryKind - 19, // 163: productv1.Category.subcategories:type_name -> productv1.ListOfSubcategory - 0, // 164: productv1.CategoryFilter.category:type_name -> productv1.CategoryKind - 228, // 165: productv1.CategoryFilter.pagination:type_name -> productv1.Pagination - 233, // 166: productv1.Animal.cat:type_name -> productv1.Cat - 234, // 167: productv1.Animal.dog:type_name -> productv1.Dog - 268, // 168: productv1.SearchInput.limit:type_name -> google.protobuf.Int32Value - 194, // 169: productv1.SearchResult.product:type_name -> productv1.Product - 197, // 170: productv1.SearchResult.user:type_name -> productv1.User - 206, // 171: productv1.SearchResult.category:type_name -> productv1.Category - 270, // 172: productv1.NullableFieldsType.optional_string:type_name -> google.protobuf.StringValue - 268, // 173: productv1.NullableFieldsType.optional_int:type_name -> google.protobuf.Int32Value - 271, // 174: productv1.NullableFieldsType.optional_float:type_name -> google.protobuf.DoubleValue - 269, // 175: productv1.NullableFieldsType.optional_boolean:type_name -> google.protobuf.BoolValue - 270, // 176: productv1.NullableFieldsFilter.name:type_name -> google.protobuf.StringValue - 270, // 177: productv1.NullableFieldsFilter.optional_string:type_name -> google.protobuf.StringValue - 269, // 178: productv1.NullableFieldsFilter.include_nulls:type_name -> google.protobuf.BoolValue - 18, // 179: productv1.BlogPost.optional_tags:type_name -> productv1.ListOfString - 18, // 180: productv1.BlogPost.keywords:type_name -> productv1.ListOfString - 10, // 181: productv1.BlogPost.ratings:type_name -> productv1.ListOfFloat - 7, // 182: productv1.BlogPost.is_published:type_name -> productv1.ListOfBoolean - 13, // 183: productv1.BlogPost.tag_groups:type_name -> productv1.ListOfListOfString - 13, // 184: productv1.BlogPost.related_topics:type_name -> productv1.ListOfListOfString - 13, // 185: productv1.BlogPost.comment_threads:type_name -> productv1.ListOfListOfString - 13, // 186: productv1.BlogPost.suggestions:type_name -> productv1.ListOfListOfString - 206, // 187: productv1.BlogPost.related_categories:type_name -> productv1.Category - 197, // 188: productv1.BlogPost.contributors:type_name -> productv1.User - 17, // 189: productv1.BlogPost.mentioned_products:type_name -> productv1.ListOfProduct - 20, // 190: productv1.BlogPost.mentioned_users:type_name -> productv1.ListOfUser - 11, // 191: productv1.BlogPost.category_groups:type_name -> productv1.ListOfListOfCategory - 14, // 192: productv1.BlogPost.contributor_teams:type_name -> productv1.ListOfListOfUser - 270, // 193: productv1.BlogPostFilter.title:type_name -> google.protobuf.StringValue - 269, // 194: productv1.BlogPostFilter.has_categories:type_name -> google.protobuf.BoolValue - 268, // 195: productv1.BlogPostFilter.min_tags:type_name -> google.protobuf.Int32Value - 270, // 196: productv1.Author.email:type_name -> google.protobuf.StringValue - 18, // 197: productv1.Author.social_links:type_name -> productv1.ListOfString - 13, // 198: productv1.Author.teams_by_project:type_name -> productv1.ListOfListOfString - 13, // 199: productv1.Author.collaborations:type_name -> productv1.ListOfListOfString - 4, // 200: productv1.Author.written_posts:type_name -> productv1.ListOfBlogPost - 206, // 201: productv1.Author.favorite_categories:type_name -> productv1.Category - 20, // 202: productv1.Author.related_authors:type_name -> productv1.ListOfUser - 17, // 203: productv1.Author.product_reviews:type_name -> productv1.ListOfProduct - 14, // 204: productv1.Author.author_groups:type_name -> productv1.ListOfListOfUser - 11, // 205: productv1.Author.category_preferences:type_name -> productv1.ListOfListOfCategory - 14, // 206: productv1.Author.project_teams:type_name -> productv1.ListOfListOfUser - 270, // 207: productv1.AuthorFilter.name:type_name -> google.protobuf.StringValue - 269, // 208: productv1.AuthorFilter.has_teams:type_name -> google.protobuf.BoolValue - 268, // 209: productv1.AuthorFilter.skill_count:type_name -> google.protobuf.Int32Value - 270, // 210: productv1.TestContainer.description:type_name -> google.protobuf.StringValue - 241, // 211: productv1.ActionResult.action_success:type_name -> productv1.ActionSuccess - 242, // 212: productv1.ActionResult.action_error:type_name -> productv1.ActionError - 270, // 213: productv1.NullableFieldsInput.optional_string:type_name -> google.protobuf.StringValue - 268, // 214: productv1.NullableFieldsInput.optional_int:type_name -> google.protobuf.Int32Value - 271, // 215: productv1.NullableFieldsInput.optional_float:type_name -> google.protobuf.DoubleValue - 269, // 216: productv1.NullableFieldsInput.optional_boolean:type_name -> google.protobuf.BoolValue - 18, // 217: productv1.BlogPostInput.optional_tags:type_name -> productv1.ListOfString - 18, // 218: productv1.BlogPostInput.keywords:type_name -> productv1.ListOfString - 10, // 219: productv1.BlogPostInput.ratings:type_name -> productv1.ListOfFloat - 7, // 220: productv1.BlogPostInput.is_published:type_name -> productv1.ListOfBoolean - 13, // 221: productv1.BlogPostInput.tag_groups:type_name -> productv1.ListOfListOfString - 13, // 222: productv1.BlogPostInput.related_topics:type_name -> productv1.ListOfListOfString - 13, // 223: productv1.BlogPostInput.comment_threads:type_name -> productv1.ListOfListOfString - 13, // 224: productv1.BlogPostInput.suggestions:type_name -> productv1.ListOfListOfString - 9, // 225: productv1.BlogPostInput.related_categories:type_name -> productv1.ListOfCategoryInput - 21, // 226: productv1.BlogPostInput.contributors:type_name -> productv1.ListOfUserInput - 12, // 227: productv1.BlogPostInput.category_groups:type_name -> productv1.ListOfListOfCategoryInput - 270, // 228: productv1.AuthorInput.email:type_name -> google.protobuf.StringValue - 18, // 229: productv1.AuthorInput.social_links:type_name -> productv1.ListOfString - 13, // 230: productv1.AuthorInput.teams_by_project:type_name -> productv1.ListOfListOfString - 13, // 231: productv1.AuthorInput.collaborations:type_name -> productv1.ListOfListOfString - 244, // 232: productv1.AuthorInput.favorite_categories:type_name -> productv1.CategoryInput - 15, // 233: productv1.AuthorInput.author_groups:type_name -> productv1.ListOfListOfUserInput - 15, // 234: productv1.AuthorInput.project_teams:type_name -> productv1.ListOfListOfUserInput - 220, // 235: productv1.ProductDetails.review_summary:type_name -> productv1.ActionResult - 208, // 236: productv1.ProductDetails.recommended_pet:type_name -> productv1.Animal - 226, // 237: productv1.NestedTypeB.c:type_name -> productv1.NestedTypeC - 228, // 238: productv1.FilterType.pagination:type_name -> productv1.Pagination - 18, // 239: productv1.OrderLineInput.modifiers:type_name -> productv1.ListOfString - 18, // 240: productv1.OrderLine.modifiers:type_name -> productv1.ListOfString - 270, // 241: productv1.Subcategory.description:type_name -> google.protobuf.StringValue - 206, // 242: productv1.CategoryMetrics.related_category:type_name -> productv1.Category - 235, // 243: productv1.Cat.owner:type_name -> productv1.Owner - 238, // 244: productv1.Cat.breed:type_name -> productv1.CatBreed - 235, // 245: productv1.Dog.owner:type_name -> productv1.Owner - 239, // 246: productv1.Dog.breed:type_name -> productv1.DogBreed - 236, // 247: productv1.Owner.contact:type_name -> productv1.ContactInfo - 237, // 248: productv1.ContactInfo.address:type_name -> productv1.Address - 240, // 249: productv1.CatBreed.characteristics:type_name -> productv1.BreedCharacteristics - 240, // 250: productv1.DogBreed.characteristics:type_name -> productv1.BreedCharacteristics - 208, // 251: productv1.TestDetails.pet:type_name -> productv1.Animal - 220, // 252: productv1.TestDetails.status:type_name -> productv1.ActionResult - 0, // 253: productv1.CategoryInput.kind:type_name -> productv1.CategoryKind - 271, // 254: productv1.ProductCountFilter.min_price:type_name -> google.protobuf.DoubleValue - 271, // 255: productv1.ProductCountFilter.max_price:type_name -> google.protobuf.DoubleValue - 269, // 256: productv1.ProductCountFilter.in_stock:type_name -> google.protobuf.BoolValue - 270, // 257: productv1.ProductCountFilter.search_term:type_name -> google.protobuf.StringValue - 271, // 258: productv1.SubcategoryItemFilter.min_price:type_name -> google.protobuf.DoubleValue - 271, // 259: productv1.SubcategoryItemFilter.max_price:type_name -> google.protobuf.DoubleValue - 269, // 260: productv1.SubcategoryItemFilter.in_stock:type_name -> google.protobuf.BoolValue - 269, // 261: productv1.SubcategoryItemFilter.is_active:type_name -> google.protobuf.BoolValue - 270, // 262: productv1.SubcategoryItemFilter.search_term:type_name -> google.protobuf.StringValue - 1, // 263: productv1.ShippingEstimateInput.destination:type_name -> productv1.ShippingDestination - 269, // 264: productv1.ShippingEstimateInput.expedited:type_name -> google.protobuf.BoolValue - 216, // 265: productv1.ListOfAuthorFilter.List.items:type_name -> productv1.AuthorFilter - 223, // 266: productv1.ListOfAuthorInput.List.items:type_name -> productv1.AuthorInput - 213, // 267: productv1.ListOfBlogPost.List.items:type_name -> productv1.BlogPost - 214, // 268: productv1.ListOfBlogPostFilter.List.items:type_name -> productv1.BlogPostFilter - 222, // 269: productv1.ListOfBlogPostInput.List.items:type_name -> productv1.BlogPostInput - 206, // 270: productv1.ListOfCategory.List.items:type_name -> productv1.Category - 244, // 271: productv1.ListOfCategoryInput.List.items:type_name -> productv1.CategoryInput - 8, // 272: productv1.ListOfListOfCategory.List.items:type_name -> productv1.ListOfCategory - 9, // 273: productv1.ListOfListOfCategoryInput.List.items:type_name -> productv1.ListOfCategoryInput - 18, // 274: productv1.ListOfListOfString.List.items:type_name -> productv1.ListOfString - 20, // 275: productv1.ListOfListOfUser.List.items:type_name -> productv1.ListOfUser - 21, // 276: productv1.ListOfListOfUserInput.List.items:type_name -> productv1.ListOfUserInput - 230, // 277: productv1.ListOfOrderLine.List.items:type_name -> productv1.OrderLine - 194, // 278: productv1.ListOfProduct.List.items:type_name -> productv1.Product - 231, // 279: productv1.ListOfSubcategory.List.items:type_name -> productv1.Subcategory - 197, // 280: productv1.ListOfUser.List.items:type_name -> productv1.User - 218, // 281: productv1.ListOfUserInput.List.items:type_name -> productv1.UserInput - 23, // 282: productv1.ProductService.LookupProductById:input_type -> productv1.LookupProductByIdRequest - 26, // 283: productv1.ProductService.LookupStorageById:input_type -> productv1.LookupStorageByIdRequest - 29, // 284: productv1.ProductService.LookupWarehouseById:input_type -> productv1.LookupWarehouseByIdRequest - 111, // 285: productv1.ProductService.MutationBulkCreateAuthors:input_type -> productv1.MutationBulkCreateAuthorsRequest - 115, // 286: productv1.ProductService.MutationBulkCreateBlogPosts:input_type -> productv1.MutationBulkCreateBlogPostsRequest - 113, // 287: productv1.ProductService.MutationBulkUpdateAuthors:input_type -> productv1.MutationBulkUpdateAuthorsRequest - 117, // 288: productv1.ProductService.MutationBulkUpdateBlogPosts:input_type -> productv1.MutationBulkUpdateBlogPostsRequest - 107, // 289: productv1.ProductService.MutationCreateAuthor:input_type -> productv1.MutationCreateAuthorRequest - 103, // 290: productv1.ProductService.MutationCreateBlogPost:input_type -> productv1.MutationCreateBlogPostRequest - 99, // 291: productv1.ProductService.MutationCreateNullableFieldsType:input_type -> productv1.MutationCreateNullableFieldsTypeRequest - 95, // 292: productv1.ProductService.MutationCreateUser:input_type -> productv1.MutationCreateUserRequest - 97, // 293: productv1.ProductService.MutationPerformAction:input_type -> productv1.MutationPerformActionRequest - 109, // 294: productv1.ProductService.MutationUpdateAuthor:input_type -> productv1.MutationUpdateAuthorRequest - 105, // 295: productv1.ProductService.MutationUpdateBlogPost:input_type -> productv1.MutationUpdateBlogPostRequest - 101, // 296: productv1.ProductService.MutationUpdateNullableFieldsType:input_type -> productv1.MutationUpdateNullableFieldsTypeRequest - 85, // 297: productv1.ProductService.QueryAllAuthors:input_type -> productv1.QueryAllAuthorsRequest - 77, // 298: productv1.ProductService.QueryAllBlogPosts:input_type -> productv1.QueryAllBlogPostsRequest - 69, // 299: productv1.ProductService.QueryAllNullableFieldsTypes:input_type -> productv1.QueryAllNullableFieldsTypesRequest - 57, // 300: productv1.ProductService.QueryAllPets:input_type -> productv1.QueryAllPetsRequest - 79, // 301: productv1.ProductService.QueryAuthor:input_type -> productv1.QueryAuthorRequest - 81, // 302: productv1.ProductService.QueryAuthorById:input_type -> productv1.QueryAuthorByIdRequest - 83, // 303: productv1.ProductService.QueryAuthorsWithFilter:input_type -> productv1.QueryAuthorsWithFilterRequest - 71, // 304: productv1.ProductService.QueryBlogPost:input_type -> productv1.QueryBlogPostRequest - 73, // 305: productv1.ProductService.QueryBlogPostById:input_type -> productv1.QueryBlogPostByIdRequest - 75, // 306: productv1.ProductService.QueryBlogPostsWithFilter:input_type -> productv1.QueryBlogPostsWithFilterRequest - 87, // 307: productv1.ProductService.QueryBulkSearchAuthors:input_type -> productv1.QueryBulkSearchAuthorsRequest - 89, // 308: productv1.ProductService.QueryBulkSearchBlogPosts:input_type -> productv1.QueryBulkSearchBlogPostsRequest - 45, // 309: productv1.ProductService.QueryCalculateTotals:input_type -> productv1.QueryCalculateTotalsRequest - 47, // 310: productv1.ProductService.QueryCategories:input_type -> productv1.QueryCategoriesRequest - 49, // 311: productv1.ProductService.QueryCategoriesByKind:input_type -> productv1.QueryCategoriesByKindRequest - 51, // 312: productv1.ProductService.QueryCategoriesByKinds:input_type -> productv1.QueryCategoriesByKindsRequest - 43, // 313: productv1.ProductService.QueryComplexFilterType:input_type -> productv1.QueryComplexFilterTypeRequest - 53, // 314: productv1.ProductService.QueryFilterCategories:input_type -> productv1.QueryFilterCategoriesRequest - 35, // 315: productv1.ProductService.QueryNestedType:input_type -> productv1.QueryNestedTypeRequest - 63, // 316: productv1.ProductService.QueryNullableFieldsType:input_type -> productv1.QueryNullableFieldsTypeRequest - 65, // 317: productv1.ProductService.QueryNullableFieldsTypeById:input_type -> productv1.QueryNullableFieldsTypeByIdRequest - 67, // 318: productv1.ProductService.QueryNullableFieldsTypeWithFilter:input_type -> productv1.QueryNullableFieldsTypeWithFilterRequest - 55, // 319: productv1.ProductService.QueryRandomPet:input_type -> productv1.QueryRandomPetRequest - 61, // 320: productv1.ProductService.QueryRandomSearchResult:input_type -> productv1.QueryRandomSearchResultRequest - 37, // 321: productv1.ProductService.QueryRecursiveType:input_type -> productv1.QueryRecursiveTypeRequest - 59, // 322: productv1.ProductService.QuerySearch:input_type -> productv1.QuerySearchRequest - 91, // 323: productv1.ProductService.QueryTestContainer:input_type -> productv1.QueryTestContainerRequest - 93, // 324: productv1.ProductService.QueryTestContainers:input_type -> productv1.QueryTestContainersRequest - 39, // 325: productv1.ProductService.QueryTypeFilterWithArguments:input_type -> productv1.QueryTypeFilterWithArgumentsRequest - 41, // 326: productv1.ProductService.QueryTypeWithMultipleFilterFields:input_type -> productv1.QueryTypeWithMultipleFilterFieldsRequest - 33, // 327: productv1.ProductService.QueryUser:input_type -> productv1.QueryUserRequest - 31, // 328: productv1.ProductService.QueryUsers:input_type -> productv1.QueryUsersRequest - 156, // 329: productv1.ProductService.ResolveCategoryCategoryMetrics:input_type -> productv1.ResolveCategoryCategoryMetricsRequest - 166, // 330: productv1.ProductService.ResolveCategoryCategoryStatus:input_type -> productv1.ResolveCategoryCategoryStatusRequest - 171, // 331: productv1.ProductService.ResolveCategoryChildCategories:input_type -> productv1.ResolveCategoryChildCategoriesRequest - 161, // 332: productv1.ProductService.ResolveCategoryMascot:input_type -> productv1.ResolveCategoryMascotRequest - 186, // 333: productv1.ProductService.ResolveCategoryMetricsNormalizedScore:input_type -> productv1.ResolveCategoryMetricsNormalizedScoreRequest - 176, // 334: productv1.ProductService.ResolveCategoryOptionalCategories:input_type -> productv1.ResolveCategoryOptionalCategoriesRequest - 151, // 335: productv1.ProductService.ResolveCategoryPopularityScore:input_type -> productv1.ResolveCategoryPopularityScoreRequest - 146, // 336: productv1.ProductService.ResolveCategoryProductCount:input_type -> productv1.ResolveCategoryProductCountRequest - 131, // 337: productv1.ProductService.ResolveProductMascotRecommendation:input_type -> productv1.ResolveProductMascotRecommendationRequest - 141, // 338: productv1.ProductService.ResolveProductProductDetails:input_type -> productv1.ResolveProductProductDetailsRequest - 126, // 339: productv1.ProductService.ResolveProductRecommendedCategory:input_type -> productv1.ResolveProductRecommendedCategoryRequest - 121, // 340: productv1.ProductService.ResolveProductShippingEstimate:input_type -> productv1.ResolveProductShippingEstimateRequest - 136, // 341: productv1.ProductService.ResolveProductStockStatus:input_type -> productv1.ResolveProductStockStatusRequest - 181, // 342: productv1.ProductService.ResolveSubcategoryItemCount:input_type -> productv1.ResolveSubcategoryItemCountRequest - 191, // 343: productv1.ProductService.ResolveTestContainerDetails:input_type -> productv1.ResolveTestContainerDetailsRequest - 24, // 344: productv1.ProductService.LookupProductById:output_type -> productv1.LookupProductByIdResponse - 27, // 345: productv1.ProductService.LookupStorageById:output_type -> productv1.LookupStorageByIdResponse - 30, // 346: productv1.ProductService.LookupWarehouseById:output_type -> productv1.LookupWarehouseByIdResponse - 112, // 347: productv1.ProductService.MutationBulkCreateAuthors:output_type -> productv1.MutationBulkCreateAuthorsResponse - 116, // 348: productv1.ProductService.MutationBulkCreateBlogPosts:output_type -> productv1.MutationBulkCreateBlogPostsResponse - 114, // 349: productv1.ProductService.MutationBulkUpdateAuthors:output_type -> productv1.MutationBulkUpdateAuthorsResponse - 118, // 350: productv1.ProductService.MutationBulkUpdateBlogPosts:output_type -> productv1.MutationBulkUpdateBlogPostsResponse - 108, // 351: productv1.ProductService.MutationCreateAuthor:output_type -> productv1.MutationCreateAuthorResponse - 104, // 352: productv1.ProductService.MutationCreateBlogPost:output_type -> productv1.MutationCreateBlogPostResponse - 100, // 353: productv1.ProductService.MutationCreateNullableFieldsType:output_type -> productv1.MutationCreateNullableFieldsTypeResponse - 96, // 354: productv1.ProductService.MutationCreateUser:output_type -> productv1.MutationCreateUserResponse - 98, // 355: productv1.ProductService.MutationPerformAction:output_type -> productv1.MutationPerformActionResponse - 110, // 356: productv1.ProductService.MutationUpdateAuthor:output_type -> productv1.MutationUpdateAuthorResponse - 106, // 357: productv1.ProductService.MutationUpdateBlogPost:output_type -> productv1.MutationUpdateBlogPostResponse - 102, // 358: productv1.ProductService.MutationUpdateNullableFieldsType:output_type -> productv1.MutationUpdateNullableFieldsTypeResponse - 86, // 359: productv1.ProductService.QueryAllAuthors:output_type -> productv1.QueryAllAuthorsResponse - 78, // 360: productv1.ProductService.QueryAllBlogPosts:output_type -> productv1.QueryAllBlogPostsResponse - 70, // 361: productv1.ProductService.QueryAllNullableFieldsTypes:output_type -> productv1.QueryAllNullableFieldsTypesResponse - 58, // 362: productv1.ProductService.QueryAllPets:output_type -> productv1.QueryAllPetsResponse - 80, // 363: productv1.ProductService.QueryAuthor:output_type -> productv1.QueryAuthorResponse - 82, // 364: productv1.ProductService.QueryAuthorById:output_type -> productv1.QueryAuthorByIdResponse - 84, // 365: productv1.ProductService.QueryAuthorsWithFilter:output_type -> productv1.QueryAuthorsWithFilterResponse - 72, // 366: productv1.ProductService.QueryBlogPost:output_type -> productv1.QueryBlogPostResponse - 74, // 367: productv1.ProductService.QueryBlogPostById:output_type -> productv1.QueryBlogPostByIdResponse - 76, // 368: productv1.ProductService.QueryBlogPostsWithFilter:output_type -> productv1.QueryBlogPostsWithFilterResponse - 88, // 369: productv1.ProductService.QueryBulkSearchAuthors:output_type -> productv1.QueryBulkSearchAuthorsResponse - 90, // 370: productv1.ProductService.QueryBulkSearchBlogPosts:output_type -> productv1.QueryBulkSearchBlogPostsResponse - 46, // 371: productv1.ProductService.QueryCalculateTotals:output_type -> productv1.QueryCalculateTotalsResponse - 48, // 372: productv1.ProductService.QueryCategories:output_type -> productv1.QueryCategoriesResponse - 50, // 373: productv1.ProductService.QueryCategoriesByKind:output_type -> productv1.QueryCategoriesByKindResponse - 52, // 374: productv1.ProductService.QueryCategoriesByKinds:output_type -> productv1.QueryCategoriesByKindsResponse - 44, // 375: productv1.ProductService.QueryComplexFilterType:output_type -> productv1.QueryComplexFilterTypeResponse - 54, // 376: productv1.ProductService.QueryFilterCategories:output_type -> productv1.QueryFilterCategoriesResponse - 36, // 377: productv1.ProductService.QueryNestedType:output_type -> productv1.QueryNestedTypeResponse - 64, // 378: productv1.ProductService.QueryNullableFieldsType:output_type -> productv1.QueryNullableFieldsTypeResponse - 66, // 379: productv1.ProductService.QueryNullableFieldsTypeById:output_type -> productv1.QueryNullableFieldsTypeByIdResponse - 68, // 380: productv1.ProductService.QueryNullableFieldsTypeWithFilter:output_type -> productv1.QueryNullableFieldsTypeWithFilterResponse - 56, // 381: productv1.ProductService.QueryRandomPet:output_type -> productv1.QueryRandomPetResponse - 62, // 382: productv1.ProductService.QueryRandomSearchResult:output_type -> productv1.QueryRandomSearchResultResponse - 38, // 383: productv1.ProductService.QueryRecursiveType:output_type -> productv1.QueryRecursiveTypeResponse - 60, // 384: productv1.ProductService.QuerySearch:output_type -> productv1.QuerySearchResponse - 92, // 385: productv1.ProductService.QueryTestContainer:output_type -> productv1.QueryTestContainerResponse - 94, // 386: productv1.ProductService.QueryTestContainers:output_type -> productv1.QueryTestContainersResponse - 40, // 387: productv1.ProductService.QueryTypeFilterWithArguments:output_type -> productv1.QueryTypeFilterWithArgumentsResponse - 42, // 388: productv1.ProductService.QueryTypeWithMultipleFilterFields:output_type -> productv1.QueryTypeWithMultipleFilterFieldsResponse - 34, // 389: productv1.ProductService.QueryUser:output_type -> productv1.QueryUserResponse - 32, // 390: productv1.ProductService.QueryUsers:output_type -> productv1.QueryUsersResponse - 158, // 391: productv1.ProductService.ResolveCategoryCategoryMetrics:output_type -> productv1.ResolveCategoryCategoryMetricsResponse - 168, // 392: productv1.ProductService.ResolveCategoryCategoryStatus:output_type -> productv1.ResolveCategoryCategoryStatusResponse - 173, // 393: productv1.ProductService.ResolveCategoryChildCategories:output_type -> productv1.ResolveCategoryChildCategoriesResponse - 163, // 394: productv1.ProductService.ResolveCategoryMascot:output_type -> productv1.ResolveCategoryMascotResponse - 188, // 395: productv1.ProductService.ResolveCategoryMetricsNormalizedScore:output_type -> productv1.ResolveCategoryMetricsNormalizedScoreResponse - 178, // 396: productv1.ProductService.ResolveCategoryOptionalCategories:output_type -> productv1.ResolveCategoryOptionalCategoriesResponse - 153, // 397: productv1.ProductService.ResolveCategoryPopularityScore:output_type -> productv1.ResolveCategoryPopularityScoreResponse - 148, // 398: productv1.ProductService.ResolveCategoryProductCount:output_type -> productv1.ResolveCategoryProductCountResponse - 133, // 399: productv1.ProductService.ResolveProductMascotRecommendation:output_type -> productv1.ResolveProductMascotRecommendationResponse - 143, // 400: productv1.ProductService.ResolveProductProductDetails:output_type -> productv1.ResolveProductProductDetailsResponse - 128, // 401: productv1.ProductService.ResolveProductRecommendedCategory:output_type -> productv1.ResolveProductRecommendedCategoryResponse - 123, // 402: productv1.ProductService.ResolveProductShippingEstimate:output_type -> productv1.ResolveProductShippingEstimateResponse - 138, // 403: productv1.ProductService.ResolveProductStockStatus:output_type -> productv1.ResolveProductStockStatusResponse - 183, // 404: productv1.ProductService.ResolveSubcategoryItemCount:output_type -> productv1.ResolveSubcategoryItemCountResponse - 193, // 405: productv1.ProductService.ResolveTestContainerDetails:output_type -> productv1.ResolveTestContainerDetailsResponse - 344, // [344:406] is the sub-list for method output_type - 282, // [282:344] is the sub-list for method input_type - 282, // [282:282] is the sub-list for extension type_name - 282, // [282:282] is the sub-list for extension extendee - 0, // [0:282] is the sub-list for field type_name + 208, // 25: productv1.LookupWarehouseByIdResponse.result:type_name -> productv1.Warehouse + 209, // 26: productv1.QueryUsersResponse.users:type_name -> productv1.User + 209, // 27: productv1.QueryUserResponse.user:type_name -> productv1.User + 210, // 28: productv1.QueryNestedTypeResponse.nested_type:type_name -> productv1.NestedTypeA + 211, // 29: productv1.QueryRecursiveTypeResponse.recursive_type:type_name -> productv1.RecursiveType + 212, // 30: productv1.QueryTypeFilterWithArgumentsResponse.type_filter_with_arguments:type_name -> productv1.TypeWithMultipleFilterFields + 213, // 31: productv1.QueryTypeWithMultipleFilterFieldsRequest.filter:type_name -> productv1.FilterTypeInput + 212, // 32: productv1.QueryTypeWithMultipleFilterFieldsResponse.type_with_multiple_filter_fields:type_name -> productv1.TypeWithMultipleFilterFields + 214, // 33: productv1.QueryComplexFilterTypeRequest.filter:type_name -> productv1.ComplexFilterTypeInput + 215, // 34: productv1.QueryComplexFilterTypeResponse.complex_filter_type:type_name -> productv1.TypeWithComplexFilterInput + 216, // 35: productv1.QueryCalculateTotalsRequest.orders:type_name -> productv1.OrderInput + 217, // 36: productv1.QueryCalculateTotalsResponse.calculate_totals:type_name -> productv1.Order + 218, // 37: productv1.QueryCategoriesResponse.categories:type_name -> productv1.Category + 218, // 38: productv1.QueryCategoryResponse.category:type_name -> productv1.Category + 0, // 39: productv1.QueryCategoriesByKindRequest.kind:type_name -> productv1.CategoryKind + 218, // 40: productv1.QueryCategoriesByKindResponse.categories_by_kind:type_name -> productv1.Category + 0, // 41: productv1.QueryCategoriesByKindsRequest.kinds:type_name -> productv1.CategoryKind + 218, // 42: productv1.QueryCategoriesByKindsResponse.categories_by_kinds:type_name -> productv1.Category + 219, // 43: productv1.QueryFilterCategoriesRequest.filter:type_name -> productv1.CategoryFilter + 218, // 44: productv1.QueryFilterCategoriesResponse.filter_categories:type_name -> productv1.Category + 220, // 45: productv1.QueryRandomPetResponse.random_pet:type_name -> productv1.Animal + 220, // 46: productv1.QueryAllPetsResponse.all_pets:type_name -> productv1.Animal + 221, // 47: productv1.QuerySearchRequest.input:type_name -> productv1.SearchInput + 222, // 48: productv1.QuerySearchResponse.search:type_name -> productv1.SearchResult + 222, // 49: productv1.QueryRandomSearchResultResponse.random_search_result:type_name -> productv1.SearchResult + 223, // 50: productv1.QueryNullableFieldsTypeResponse.nullable_fields_type:type_name -> productv1.NullableFieldsType + 223, // 51: productv1.QueryNullableFieldsTypeByIdResponse.nullable_fields_type_by_id:type_name -> productv1.NullableFieldsType + 224, // 52: productv1.QueryNullableFieldsTypeWithFilterRequest.filter:type_name -> productv1.NullableFieldsFilter + 223, // 53: productv1.QueryNullableFieldsTypeWithFilterResponse.nullable_fields_type_with_filter:type_name -> productv1.NullableFieldsType + 223, // 54: productv1.QueryAllNullableFieldsTypesResponse.all_nullable_fields_types:type_name -> productv1.NullableFieldsType + 225, // 55: productv1.QueryBlogPostResponse.blog_post:type_name -> productv1.BlogPost + 225, // 56: productv1.QueryBlogPostByIdResponse.blog_post_by_id:type_name -> productv1.BlogPost + 226, // 57: productv1.QueryBlogPostsWithFilterRequest.filter:type_name -> productv1.BlogPostFilter + 225, // 58: productv1.QueryBlogPostsWithFilterResponse.blog_posts_with_filter:type_name -> productv1.BlogPost + 225, // 59: productv1.QueryAllBlogPostsResponse.all_blog_posts:type_name -> productv1.BlogPost + 227, // 60: productv1.QueryAuthorResponse.author:type_name -> productv1.Author + 227, // 61: productv1.QueryAuthorByIdResponse.author_by_id:type_name -> productv1.Author + 228, // 62: productv1.QueryAuthorsWithFilterRequest.filter:type_name -> productv1.AuthorFilter + 227, // 63: productv1.QueryAuthorsWithFilterResponse.authors_with_filter:type_name -> productv1.Author + 227, // 64: productv1.QueryAllAuthorsResponse.all_authors:type_name -> productv1.Author + 2, // 65: productv1.QueryBulkSearchAuthorsRequest.filters:type_name -> productv1.ListOfAuthorFilter + 227, // 66: productv1.QueryBulkSearchAuthorsResponse.bulk_search_authors:type_name -> productv1.Author + 5, // 67: productv1.QueryBulkSearchBlogPostsRequest.filters:type_name -> productv1.ListOfBlogPostFilter + 225, // 68: productv1.QueryBulkSearchBlogPostsResponse.bulk_search_blog_posts:type_name -> productv1.BlogPost + 229, // 69: productv1.QueryTestContainerResponse.test_container:type_name -> productv1.TestContainer + 229, // 70: productv1.QueryTestContainersResponse.test_containers:type_name -> productv1.TestContainer + 230, // 71: productv1.MutationCreateUserRequest.input:type_name -> productv1.UserInput + 209, // 72: productv1.MutationCreateUserResponse.create_user:type_name -> productv1.User + 231, // 73: productv1.MutationPerformActionRequest.input:type_name -> productv1.ActionInput + 232, // 74: productv1.MutationPerformActionResponse.perform_action:type_name -> productv1.ActionResult + 233, // 75: productv1.MutationCreateNullableFieldsTypeRequest.input:type_name -> productv1.NullableFieldsInput + 223, // 76: productv1.MutationCreateNullableFieldsTypeResponse.create_nullable_fields_type:type_name -> productv1.NullableFieldsType + 233, // 77: productv1.MutationUpdateNullableFieldsTypeRequest.input:type_name -> productv1.NullableFieldsInput + 223, // 78: productv1.MutationUpdateNullableFieldsTypeResponse.update_nullable_fields_type:type_name -> productv1.NullableFieldsType + 234, // 79: productv1.MutationCreateBlogPostRequest.input:type_name -> productv1.BlogPostInput + 225, // 80: productv1.MutationCreateBlogPostResponse.create_blog_post:type_name -> productv1.BlogPost + 234, // 81: productv1.MutationUpdateBlogPostRequest.input:type_name -> productv1.BlogPostInput + 225, // 82: productv1.MutationUpdateBlogPostResponse.update_blog_post:type_name -> productv1.BlogPost + 235, // 83: productv1.MutationCreateAuthorRequest.input:type_name -> productv1.AuthorInput + 227, // 84: productv1.MutationCreateAuthorResponse.create_author:type_name -> productv1.Author + 235, // 85: productv1.MutationUpdateAuthorRequest.input:type_name -> productv1.AuthorInput + 227, // 86: productv1.MutationUpdateAuthorResponse.update_author:type_name -> productv1.Author + 3, // 87: productv1.MutationBulkCreateAuthorsRequest.authors:type_name -> productv1.ListOfAuthorInput + 227, // 88: productv1.MutationBulkCreateAuthorsResponse.bulk_create_authors:type_name -> productv1.Author + 3, // 89: productv1.MutationBulkUpdateAuthorsRequest.authors:type_name -> productv1.ListOfAuthorInput + 227, // 90: productv1.MutationBulkUpdateAuthorsResponse.bulk_update_authors:type_name -> productv1.Author + 6, // 91: productv1.MutationBulkCreateBlogPostsRequest.blog_posts:type_name -> productv1.ListOfBlogPostInput + 225, // 92: productv1.MutationBulkCreateBlogPostsResponse.bulk_create_blog_posts:type_name -> productv1.BlogPost + 6, // 93: productv1.MutationBulkUpdateBlogPostsRequest.blog_posts:type_name -> productv1.ListOfBlogPostInput + 225, // 94: productv1.MutationBulkUpdateBlogPostsResponse.bulk_update_blog_posts:type_name -> productv1.BlogPost + 259, // 95: productv1.ResolveProductShippingEstimateArgs.input:type_name -> productv1.ShippingEstimateInput + 122, // 96: productv1.ResolveProductShippingEstimateRequest.context:type_name -> productv1.ResolveProductShippingEstimateContext + 121, // 97: productv1.ResolveProductShippingEstimateRequest.field_args:type_name -> productv1.ResolveProductShippingEstimateArgs + 124, // 98: productv1.ResolveProductShippingEstimateResponse.result:type_name -> productv1.ResolveProductShippingEstimateResult + 127, // 99: productv1.ResolveProductRecommendedCategoryRequest.context:type_name -> productv1.ResolveProductRecommendedCategoryContext + 126, // 100: productv1.ResolveProductRecommendedCategoryRequest.field_args:type_name -> productv1.ResolveProductRecommendedCategoryArgs + 218, // 101: productv1.ResolveProductRecommendedCategoryResult.recommended_category:type_name -> productv1.Category + 129, // 102: productv1.ResolveProductRecommendedCategoryResponse.result:type_name -> productv1.ResolveProductRecommendedCategoryResult + 132, // 103: productv1.ResolveProductMascotRecommendationRequest.context:type_name -> productv1.ResolveProductMascotRecommendationContext + 131, // 104: productv1.ResolveProductMascotRecommendationRequest.field_args:type_name -> productv1.ResolveProductMascotRecommendationArgs + 220, // 105: productv1.ResolveProductMascotRecommendationResult.mascot_recommendation:type_name -> productv1.Animal + 134, // 106: productv1.ResolveProductMascotRecommendationResponse.result:type_name -> productv1.ResolveProductMascotRecommendationResult + 137, // 107: productv1.ResolveProductStockStatusRequest.context:type_name -> productv1.ResolveProductStockStatusContext + 136, // 108: productv1.ResolveProductStockStatusRequest.field_args:type_name -> productv1.ResolveProductStockStatusArgs + 232, // 109: productv1.ResolveProductStockStatusResult.stock_status:type_name -> productv1.ActionResult + 139, // 110: productv1.ResolveProductStockStatusResponse.result:type_name -> productv1.ResolveProductStockStatusResult + 142, // 111: productv1.ResolveProductProductDetailsRequest.context:type_name -> productv1.ResolveProductProductDetailsContext + 141, // 112: productv1.ResolveProductProductDetailsRequest.field_args:type_name -> productv1.ResolveProductProductDetailsArgs + 236, // 113: productv1.ResolveProductProductDetailsResult.product_details:type_name -> productv1.ProductDetails + 144, // 114: productv1.ResolveProductProductDetailsResponse.result:type_name -> productv1.ResolveProductProductDetailsResult + 257, // 115: productv1.ResolveCategoryProductCountArgs.filters:type_name -> productv1.ProductCountFilter + 147, // 116: productv1.ResolveCategoryProductCountRequest.context:type_name -> productv1.ResolveCategoryProductCountContext + 146, // 117: productv1.ResolveCategoryProductCountRequest.field_args:type_name -> productv1.ResolveCategoryProductCountArgs + 149, // 118: productv1.ResolveCategoryProductCountResponse.result:type_name -> productv1.ResolveCategoryProductCountResult + 280, // 119: productv1.ResolveCategoryPopularityScoreArgs.threshold:type_name -> google.protobuf.Int32Value + 152, // 120: productv1.ResolveCategoryPopularityScoreRequest.context:type_name -> productv1.ResolveCategoryPopularityScoreContext + 151, // 121: productv1.ResolveCategoryPopularityScoreRequest.field_args:type_name -> productv1.ResolveCategoryPopularityScoreArgs + 280, // 122: productv1.ResolveCategoryPopularityScoreResult.popularity_score:type_name -> google.protobuf.Int32Value + 154, // 123: productv1.ResolveCategoryPopularityScoreResponse.result:type_name -> productv1.ResolveCategoryPopularityScoreResult + 157, // 124: productv1.ResolveCategoryCategoryMetricsRequest.context:type_name -> productv1.ResolveCategoryCategoryMetricsContext + 156, // 125: productv1.ResolveCategoryCategoryMetricsRequest.field_args:type_name -> productv1.ResolveCategoryCategoryMetricsArgs + 244, // 126: productv1.ResolveCategoryCategoryMetricsResult.category_metrics:type_name -> productv1.CategoryMetrics + 159, // 127: productv1.ResolveCategoryCategoryMetricsResponse.result:type_name -> productv1.ResolveCategoryCategoryMetricsResult + 0, // 128: productv1.ResolveCategoryMascotContext.kind:type_name -> productv1.CategoryKind + 162, // 129: productv1.ResolveCategoryMascotRequest.context:type_name -> productv1.ResolveCategoryMascotContext + 161, // 130: productv1.ResolveCategoryMascotRequest.field_args:type_name -> productv1.ResolveCategoryMascotArgs + 220, // 131: productv1.ResolveCategoryMascotResult.mascot:type_name -> productv1.Animal + 164, // 132: productv1.ResolveCategoryMascotResponse.result:type_name -> productv1.ResolveCategoryMascotResult + 167, // 133: productv1.ResolveCategoryCategoryStatusRequest.context:type_name -> productv1.ResolveCategoryCategoryStatusContext + 166, // 134: productv1.ResolveCategoryCategoryStatusRequest.field_args:type_name -> productv1.ResolveCategoryCategoryStatusArgs + 232, // 135: productv1.ResolveCategoryCategoryStatusResult.category_status:type_name -> productv1.ActionResult + 169, // 136: productv1.ResolveCategoryCategoryStatusResponse.result:type_name -> productv1.ResolveCategoryCategoryStatusResult + 281, // 137: productv1.ResolveCategoryChildCategoriesArgs.include:type_name -> google.protobuf.BoolValue + 172, // 138: productv1.ResolveCategoryChildCategoriesRequest.context:type_name -> productv1.ResolveCategoryChildCategoriesContext + 171, // 139: productv1.ResolveCategoryChildCategoriesRequest.field_args:type_name -> productv1.ResolveCategoryChildCategoriesArgs + 218, // 140: productv1.ResolveCategoryChildCategoriesResult.child_categories:type_name -> productv1.Category + 174, // 141: productv1.ResolveCategoryChildCategoriesResponse.result:type_name -> productv1.ResolveCategoryChildCategoriesResult + 281, // 142: productv1.ResolveCategoryOptionalCategoriesArgs.include:type_name -> google.protobuf.BoolValue + 177, // 143: productv1.ResolveCategoryOptionalCategoriesRequest.context:type_name -> productv1.ResolveCategoryOptionalCategoriesContext + 176, // 144: productv1.ResolveCategoryOptionalCategoriesRequest.field_args:type_name -> productv1.ResolveCategoryOptionalCategoriesArgs + 8, // 145: productv1.ResolveCategoryOptionalCategoriesResult.optional_categories:type_name -> productv1.ListOfCategory + 179, // 146: productv1.ResolveCategoryOptionalCategoriesResponse.result:type_name -> productv1.ResolveCategoryOptionalCategoriesResult + 258, // 147: productv1.ResolveSubcategoryItemCountArgs.filters:type_name -> productv1.SubcategoryItemFilter + 182, // 148: productv1.ResolveSubcategoryItemCountRequest.context:type_name -> productv1.ResolveSubcategoryItemCountContext + 181, // 149: productv1.ResolveSubcategoryItemCountRequest.field_args:type_name -> productv1.ResolveSubcategoryItemCountArgs + 184, // 150: productv1.ResolveSubcategoryItemCountResponse.result:type_name -> productv1.ResolveSubcategoryItemCountResult + 187, // 151: productv1.ResolveSubcategoryFeaturedCategoryRequest.context:type_name -> productv1.ResolveSubcategoryFeaturedCategoryContext + 186, // 152: productv1.ResolveSubcategoryFeaturedCategoryRequest.field_args:type_name -> productv1.ResolveSubcategoryFeaturedCategoryArgs + 218, // 153: productv1.ResolveSubcategoryFeaturedCategoryResult.featured_category:type_name -> productv1.Category + 189, // 154: productv1.ResolveSubcategoryFeaturedCategoryResponse.result:type_name -> productv1.ResolveSubcategoryFeaturedCategoryResult + 192, // 155: productv1.ResolveCategoryMetricsNormalizedScoreRequest.context:type_name -> productv1.ResolveCategoryMetricsNormalizedScoreContext + 191, // 156: productv1.ResolveCategoryMetricsNormalizedScoreRequest.field_args:type_name -> productv1.ResolveCategoryMetricsNormalizedScoreArgs + 194, // 157: productv1.ResolveCategoryMetricsNormalizedScoreResponse.result:type_name -> productv1.ResolveCategoryMetricsNormalizedScoreResult + 281, // 158: productv1.ResolveCategoryMetricsRelatedCategoryArgs.include:type_name -> google.protobuf.BoolValue + 197, // 159: productv1.ResolveCategoryMetricsRelatedCategoryRequest.context:type_name -> productv1.ResolveCategoryMetricsRelatedCategoryContext + 196, // 160: productv1.ResolveCategoryMetricsRelatedCategoryRequest.field_args:type_name -> productv1.ResolveCategoryMetricsRelatedCategoryArgs + 218, // 161: productv1.ResolveCategoryMetricsRelatedCategoryResult.related_category:type_name -> productv1.Category + 199, // 162: productv1.ResolveCategoryMetricsRelatedCategoryResponse.result:type_name -> productv1.ResolveCategoryMetricsRelatedCategoryResult + 202, // 163: productv1.ResolveTestContainerDetailsRequest.context:type_name -> productv1.ResolveTestContainerDetailsContext + 201, // 164: productv1.ResolveTestContainerDetailsRequest.field_args:type_name -> productv1.ResolveTestContainerDetailsArgs + 255, // 165: productv1.ResolveTestContainerDetailsResult.details:type_name -> productv1.TestDetails + 204, // 166: productv1.ResolveTestContainerDetailsResponse.result:type_name -> productv1.ResolveTestContainerDetailsResult + 237, // 167: productv1.NestedTypeA.b:type_name -> productv1.NestedTypeB + 211, // 168: productv1.RecursiveType.recursive_type:type_name -> productv1.RecursiveType + 239, // 169: productv1.ComplexFilterTypeInput.filter:type_name -> productv1.FilterType + 241, // 170: productv1.OrderInput.lines:type_name -> productv1.OrderLineInput + 16, // 171: productv1.Order.order_lines:type_name -> productv1.ListOfOrderLine + 0, // 172: productv1.Category.kind:type_name -> productv1.CategoryKind + 19, // 173: productv1.Category.subcategories:type_name -> productv1.ListOfSubcategory + 244, // 174: productv1.Category.null_metrics:type_name -> productv1.CategoryMetrics + 0, // 175: productv1.CategoryFilter.category:type_name -> productv1.CategoryKind + 240, // 176: productv1.CategoryFilter.pagination:type_name -> productv1.Pagination + 245, // 177: productv1.Animal.cat:type_name -> productv1.Cat + 246, // 178: productv1.Animal.dog:type_name -> productv1.Dog + 280, // 179: productv1.SearchInput.limit:type_name -> google.protobuf.Int32Value + 206, // 180: productv1.SearchResult.product:type_name -> productv1.Product + 209, // 181: productv1.SearchResult.user:type_name -> productv1.User + 218, // 182: productv1.SearchResult.category:type_name -> productv1.Category + 282, // 183: productv1.NullableFieldsType.optional_string:type_name -> google.protobuf.StringValue + 280, // 184: productv1.NullableFieldsType.optional_int:type_name -> google.protobuf.Int32Value + 283, // 185: productv1.NullableFieldsType.optional_float:type_name -> google.protobuf.DoubleValue + 281, // 186: productv1.NullableFieldsType.optional_boolean:type_name -> google.protobuf.BoolValue + 282, // 187: productv1.NullableFieldsFilter.name:type_name -> google.protobuf.StringValue + 282, // 188: productv1.NullableFieldsFilter.optional_string:type_name -> google.protobuf.StringValue + 281, // 189: productv1.NullableFieldsFilter.include_nulls:type_name -> google.protobuf.BoolValue + 18, // 190: productv1.BlogPost.optional_tags:type_name -> productv1.ListOfString + 18, // 191: productv1.BlogPost.keywords:type_name -> productv1.ListOfString + 10, // 192: productv1.BlogPost.ratings:type_name -> productv1.ListOfFloat + 7, // 193: productv1.BlogPost.is_published:type_name -> productv1.ListOfBoolean + 13, // 194: productv1.BlogPost.tag_groups:type_name -> productv1.ListOfListOfString + 13, // 195: productv1.BlogPost.related_topics:type_name -> productv1.ListOfListOfString + 13, // 196: productv1.BlogPost.comment_threads:type_name -> productv1.ListOfListOfString + 13, // 197: productv1.BlogPost.suggestions:type_name -> productv1.ListOfListOfString + 218, // 198: productv1.BlogPost.related_categories:type_name -> productv1.Category + 209, // 199: productv1.BlogPost.contributors:type_name -> productv1.User + 17, // 200: productv1.BlogPost.mentioned_products:type_name -> productv1.ListOfProduct + 20, // 201: productv1.BlogPost.mentioned_users:type_name -> productv1.ListOfUser + 11, // 202: productv1.BlogPost.category_groups:type_name -> productv1.ListOfListOfCategory + 14, // 203: productv1.BlogPost.contributor_teams:type_name -> productv1.ListOfListOfUser + 282, // 204: productv1.BlogPostFilter.title:type_name -> google.protobuf.StringValue + 281, // 205: productv1.BlogPostFilter.has_categories:type_name -> google.protobuf.BoolValue + 280, // 206: productv1.BlogPostFilter.min_tags:type_name -> google.protobuf.Int32Value + 282, // 207: productv1.Author.email:type_name -> google.protobuf.StringValue + 18, // 208: productv1.Author.social_links:type_name -> productv1.ListOfString + 13, // 209: productv1.Author.teams_by_project:type_name -> productv1.ListOfListOfString + 13, // 210: productv1.Author.collaborations:type_name -> productv1.ListOfListOfString + 4, // 211: productv1.Author.written_posts:type_name -> productv1.ListOfBlogPost + 218, // 212: productv1.Author.favorite_categories:type_name -> productv1.Category + 20, // 213: productv1.Author.related_authors:type_name -> productv1.ListOfUser + 17, // 214: productv1.Author.product_reviews:type_name -> productv1.ListOfProduct + 14, // 215: productv1.Author.author_groups:type_name -> productv1.ListOfListOfUser + 11, // 216: productv1.Author.category_preferences:type_name -> productv1.ListOfListOfCategory + 14, // 217: productv1.Author.project_teams:type_name -> productv1.ListOfListOfUser + 282, // 218: productv1.AuthorFilter.name:type_name -> google.protobuf.StringValue + 281, // 219: productv1.AuthorFilter.has_teams:type_name -> google.protobuf.BoolValue + 280, // 220: productv1.AuthorFilter.skill_count:type_name -> google.protobuf.Int32Value + 282, // 221: productv1.TestContainer.description:type_name -> google.protobuf.StringValue + 253, // 222: productv1.ActionResult.action_success:type_name -> productv1.ActionSuccess + 254, // 223: productv1.ActionResult.action_error:type_name -> productv1.ActionError + 282, // 224: productv1.NullableFieldsInput.optional_string:type_name -> google.protobuf.StringValue + 280, // 225: productv1.NullableFieldsInput.optional_int:type_name -> google.protobuf.Int32Value + 283, // 226: productv1.NullableFieldsInput.optional_float:type_name -> google.protobuf.DoubleValue + 281, // 227: productv1.NullableFieldsInput.optional_boolean:type_name -> google.protobuf.BoolValue + 18, // 228: productv1.BlogPostInput.optional_tags:type_name -> productv1.ListOfString + 18, // 229: productv1.BlogPostInput.keywords:type_name -> productv1.ListOfString + 10, // 230: productv1.BlogPostInput.ratings:type_name -> productv1.ListOfFloat + 7, // 231: productv1.BlogPostInput.is_published:type_name -> productv1.ListOfBoolean + 13, // 232: productv1.BlogPostInput.tag_groups:type_name -> productv1.ListOfListOfString + 13, // 233: productv1.BlogPostInput.related_topics:type_name -> productv1.ListOfListOfString + 13, // 234: productv1.BlogPostInput.comment_threads:type_name -> productv1.ListOfListOfString + 13, // 235: productv1.BlogPostInput.suggestions:type_name -> productv1.ListOfListOfString + 9, // 236: productv1.BlogPostInput.related_categories:type_name -> productv1.ListOfCategoryInput + 21, // 237: productv1.BlogPostInput.contributors:type_name -> productv1.ListOfUserInput + 12, // 238: productv1.BlogPostInput.category_groups:type_name -> productv1.ListOfListOfCategoryInput + 282, // 239: productv1.AuthorInput.email:type_name -> google.protobuf.StringValue + 18, // 240: productv1.AuthorInput.social_links:type_name -> productv1.ListOfString + 13, // 241: productv1.AuthorInput.teams_by_project:type_name -> productv1.ListOfListOfString + 13, // 242: productv1.AuthorInput.collaborations:type_name -> productv1.ListOfListOfString + 256, // 243: productv1.AuthorInput.favorite_categories:type_name -> productv1.CategoryInput + 15, // 244: productv1.AuthorInput.author_groups:type_name -> productv1.ListOfListOfUserInput + 15, // 245: productv1.AuthorInput.project_teams:type_name -> productv1.ListOfListOfUserInput + 232, // 246: productv1.ProductDetails.review_summary:type_name -> productv1.ActionResult + 220, // 247: productv1.ProductDetails.recommended_pet:type_name -> productv1.Animal + 238, // 248: productv1.NestedTypeB.c:type_name -> productv1.NestedTypeC + 240, // 249: productv1.FilterType.pagination:type_name -> productv1.Pagination + 18, // 250: productv1.OrderLineInput.modifiers:type_name -> productv1.ListOfString + 18, // 251: productv1.OrderLine.modifiers:type_name -> productv1.ListOfString + 282, // 252: productv1.Subcategory.description:type_name -> google.protobuf.StringValue + 247, // 253: productv1.Cat.owner:type_name -> productv1.Owner + 250, // 254: productv1.Cat.breed:type_name -> productv1.CatBreed + 247, // 255: productv1.Dog.owner:type_name -> productv1.Owner + 251, // 256: productv1.Dog.breed:type_name -> productv1.DogBreed + 248, // 257: productv1.Owner.contact:type_name -> productv1.ContactInfo + 220, // 258: productv1.Owner.pet:type_name -> productv1.Animal + 249, // 259: productv1.ContactInfo.address:type_name -> productv1.Address + 252, // 260: productv1.CatBreed.characteristics:type_name -> productv1.BreedCharacteristics + 252, // 261: productv1.DogBreed.characteristics:type_name -> productv1.BreedCharacteristics + 220, // 262: productv1.TestDetails.pet:type_name -> productv1.Animal + 232, // 263: productv1.TestDetails.status:type_name -> productv1.ActionResult + 0, // 264: productv1.CategoryInput.kind:type_name -> productv1.CategoryKind + 283, // 265: productv1.ProductCountFilter.min_price:type_name -> google.protobuf.DoubleValue + 283, // 266: productv1.ProductCountFilter.max_price:type_name -> google.protobuf.DoubleValue + 281, // 267: productv1.ProductCountFilter.in_stock:type_name -> google.protobuf.BoolValue + 282, // 268: productv1.ProductCountFilter.search_term:type_name -> google.protobuf.StringValue + 283, // 269: productv1.SubcategoryItemFilter.min_price:type_name -> google.protobuf.DoubleValue + 283, // 270: productv1.SubcategoryItemFilter.max_price:type_name -> google.protobuf.DoubleValue + 281, // 271: productv1.SubcategoryItemFilter.in_stock:type_name -> google.protobuf.BoolValue + 281, // 272: productv1.SubcategoryItemFilter.is_active:type_name -> google.protobuf.BoolValue + 282, // 273: productv1.SubcategoryItemFilter.search_term:type_name -> google.protobuf.StringValue + 1, // 274: productv1.ShippingEstimateInput.destination:type_name -> productv1.ShippingDestination + 281, // 275: productv1.ShippingEstimateInput.expedited:type_name -> google.protobuf.BoolValue + 228, // 276: productv1.ListOfAuthorFilter.List.items:type_name -> productv1.AuthorFilter + 235, // 277: productv1.ListOfAuthorInput.List.items:type_name -> productv1.AuthorInput + 225, // 278: productv1.ListOfBlogPost.List.items:type_name -> productv1.BlogPost + 226, // 279: productv1.ListOfBlogPostFilter.List.items:type_name -> productv1.BlogPostFilter + 234, // 280: productv1.ListOfBlogPostInput.List.items:type_name -> productv1.BlogPostInput + 218, // 281: productv1.ListOfCategory.List.items:type_name -> productv1.Category + 256, // 282: productv1.ListOfCategoryInput.List.items:type_name -> productv1.CategoryInput + 8, // 283: productv1.ListOfListOfCategory.List.items:type_name -> productv1.ListOfCategory + 9, // 284: productv1.ListOfListOfCategoryInput.List.items:type_name -> productv1.ListOfCategoryInput + 18, // 285: productv1.ListOfListOfString.List.items:type_name -> productv1.ListOfString + 20, // 286: productv1.ListOfListOfUser.List.items:type_name -> productv1.ListOfUser + 21, // 287: productv1.ListOfListOfUserInput.List.items:type_name -> productv1.ListOfUserInput + 242, // 288: productv1.ListOfOrderLine.List.items:type_name -> productv1.OrderLine + 206, // 289: productv1.ListOfProduct.List.items:type_name -> productv1.Product + 243, // 290: productv1.ListOfSubcategory.List.items:type_name -> productv1.Subcategory + 209, // 291: productv1.ListOfUser.List.items:type_name -> productv1.User + 230, // 292: productv1.ListOfUserInput.List.items:type_name -> productv1.UserInput + 23, // 293: productv1.ProductService.LookupProductById:input_type -> productv1.LookupProductByIdRequest + 26, // 294: productv1.ProductService.LookupStorageById:input_type -> productv1.LookupStorageByIdRequest + 29, // 295: productv1.ProductService.LookupWarehouseById:input_type -> productv1.LookupWarehouseByIdRequest + 113, // 296: productv1.ProductService.MutationBulkCreateAuthors:input_type -> productv1.MutationBulkCreateAuthorsRequest + 117, // 297: productv1.ProductService.MutationBulkCreateBlogPosts:input_type -> productv1.MutationBulkCreateBlogPostsRequest + 115, // 298: productv1.ProductService.MutationBulkUpdateAuthors:input_type -> productv1.MutationBulkUpdateAuthorsRequest + 119, // 299: productv1.ProductService.MutationBulkUpdateBlogPosts:input_type -> productv1.MutationBulkUpdateBlogPostsRequest + 109, // 300: productv1.ProductService.MutationCreateAuthor:input_type -> productv1.MutationCreateAuthorRequest + 105, // 301: productv1.ProductService.MutationCreateBlogPost:input_type -> productv1.MutationCreateBlogPostRequest + 101, // 302: productv1.ProductService.MutationCreateNullableFieldsType:input_type -> productv1.MutationCreateNullableFieldsTypeRequest + 97, // 303: productv1.ProductService.MutationCreateUser:input_type -> productv1.MutationCreateUserRequest + 99, // 304: productv1.ProductService.MutationPerformAction:input_type -> productv1.MutationPerformActionRequest + 111, // 305: productv1.ProductService.MutationUpdateAuthor:input_type -> productv1.MutationUpdateAuthorRequest + 107, // 306: productv1.ProductService.MutationUpdateBlogPost:input_type -> productv1.MutationUpdateBlogPostRequest + 103, // 307: productv1.ProductService.MutationUpdateNullableFieldsType:input_type -> productv1.MutationUpdateNullableFieldsTypeRequest + 87, // 308: productv1.ProductService.QueryAllAuthors:input_type -> productv1.QueryAllAuthorsRequest + 79, // 309: productv1.ProductService.QueryAllBlogPosts:input_type -> productv1.QueryAllBlogPostsRequest + 71, // 310: productv1.ProductService.QueryAllNullableFieldsTypes:input_type -> productv1.QueryAllNullableFieldsTypesRequest + 59, // 311: productv1.ProductService.QueryAllPets:input_type -> productv1.QueryAllPetsRequest + 81, // 312: productv1.ProductService.QueryAuthor:input_type -> productv1.QueryAuthorRequest + 83, // 313: productv1.ProductService.QueryAuthorById:input_type -> productv1.QueryAuthorByIdRequest + 85, // 314: productv1.ProductService.QueryAuthorsWithFilter:input_type -> productv1.QueryAuthorsWithFilterRequest + 73, // 315: productv1.ProductService.QueryBlogPost:input_type -> productv1.QueryBlogPostRequest + 75, // 316: productv1.ProductService.QueryBlogPostById:input_type -> productv1.QueryBlogPostByIdRequest + 77, // 317: productv1.ProductService.QueryBlogPostsWithFilter:input_type -> productv1.QueryBlogPostsWithFilterRequest + 89, // 318: productv1.ProductService.QueryBulkSearchAuthors:input_type -> productv1.QueryBulkSearchAuthorsRequest + 91, // 319: productv1.ProductService.QueryBulkSearchBlogPosts:input_type -> productv1.QueryBulkSearchBlogPostsRequest + 45, // 320: productv1.ProductService.QueryCalculateTotals:input_type -> productv1.QueryCalculateTotalsRequest + 47, // 321: productv1.ProductService.QueryCategories:input_type -> productv1.QueryCategoriesRequest + 51, // 322: productv1.ProductService.QueryCategoriesByKind:input_type -> productv1.QueryCategoriesByKindRequest + 53, // 323: productv1.ProductService.QueryCategoriesByKinds:input_type -> productv1.QueryCategoriesByKindsRequest + 49, // 324: productv1.ProductService.QueryCategory:input_type -> productv1.QueryCategoryRequest + 43, // 325: productv1.ProductService.QueryComplexFilterType:input_type -> productv1.QueryComplexFilterTypeRequest + 55, // 326: productv1.ProductService.QueryFilterCategories:input_type -> productv1.QueryFilterCategoriesRequest + 35, // 327: productv1.ProductService.QueryNestedType:input_type -> productv1.QueryNestedTypeRequest + 65, // 328: productv1.ProductService.QueryNullableFieldsType:input_type -> productv1.QueryNullableFieldsTypeRequest + 67, // 329: productv1.ProductService.QueryNullableFieldsTypeById:input_type -> productv1.QueryNullableFieldsTypeByIdRequest + 69, // 330: productv1.ProductService.QueryNullableFieldsTypeWithFilter:input_type -> productv1.QueryNullableFieldsTypeWithFilterRequest + 57, // 331: productv1.ProductService.QueryRandomPet:input_type -> productv1.QueryRandomPetRequest + 63, // 332: productv1.ProductService.QueryRandomSearchResult:input_type -> productv1.QueryRandomSearchResultRequest + 37, // 333: productv1.ProductService.QueryRecursiveType:input_type -> productv1.QueryRecursiveTypeRequest + 61, // 334: productv1.ProductService.QuerySearch:input_type -> productv1.QuerySearchRequest + 93, // 335: productv1.ProductService.QueryTestContainer:input_type -> productv1.QueryTestContainerRequest + 95, // 336: productv1.ProductService.QueryTestContainers:input_type -> productv1.QueryTestContainersRequest + 39, // 337: productv1.ProductService.QueryTypeFilterWithArguments:input_type -> productv1.QueryTypeFilterWithArgumentsRequest + 41, // 338: productv1.ProductService.QueryTypeWithMultipleFilterFields:input_type -> productv1.QueryTypeWithMultipleFilterFieldsRequest + 33, // 339: productv1.ProductService.QueryUser:input_type -> productv1.QueryUserRequest + 31, // 340: productv1.ProductService.QueryUsers:input_type -> productv1.QueryUsersRequest + 158, // 341: productv1.ProductService.ResolveCategoryCategoryMetrics:input_type -> productv1.ResolveCategoryCategoryMetricsRequest + 168, // 342: productv1.ProductService.ResolveCategoryCategoryStatus:input_type -> productv1.ResolveCategoryCategoryStatusRequest + 173, // 343: productv1.ProductService.ResolveCategoryChildCategories:input_type -> productv1.ResolveCategoryChildCategoriesRequest + 163, // 344: productv1.ProductService.ResolveCategoryMascot:input_type -> productv1.ResolveCategoryMascotRequest + 193, // 345: productv1.ProductService.ResolveCategoryMetricsNormalizedScore:input_type -> productv1.ResolveCategoryMetricsNormalizedScoreRequest + 198, // 346: productv1.ProductService.ResolveCategoryMetricsRelatedCategory:input_type -> productv1.ResolveCategoryMetricsRelatedCategoryRequest + 178, // 347: productv1.ProductService.ResolveCategoryOptionalCategories:input_type -> productv1.ResolveCategoryOptionalCategoriesRequest + 153, // 348: productv1.ProductService.ResolveCategoryPopularityScore:input_type -> productv1.ResolveCategoryPopularityScoreRequest + 148, // 349: productv1.ProductService.ResolveCategoryProductCount:input_type -> productv1.ResolveCategoryProductCountRequest + 133, // 350: productv1.ProductService.ResolveProductMascotRecommendation:input_type -> productv1.ResolveProductMascotRecommendationRequest + 143, // 351: productv1.ProductService.ResolveProductProductDetails:input_type -> productv1.ResolveProductProductDetailsRequest + 128, // 352: productv1.ProductService.ResolveProductRecommendedCategory:input_type -> productv1.ResolveProductRecommendedCategoryRequest + 123, // 353: productv1.ProductService.ResolveProductShippingEstimate:input_type -> productv1.ResolveProductShippingEstimateRequest + 138, // 354: productv1.ProductService.ResolveProductStockStatus:input_type -> productv1.ResolveProductStockStatusRequest + 188, // 355: productv1.ProductService.ResolveSubcategoryFeaturedCategory:input_type -> productv1.ResolveSubcategoryFeaturedCategoryRequest + 183, // 356: productv1.ProductService.ResolveSubcategoryItemCount:input_type -> productv1.ResolveSubcategoryItemCountRequest + 203, // 357: productv1.ProductService.ResolveTestContainerDetails:input_type -> productv1.ResolveTestContainerDetailsRequest + 24, // 358: productv1.ProductService.LookupProductById:output_type -> productv1.LookupProductByIdResponse + 27, // 359: productv1.ProductService.LookupStorageById:output_type -> productv1.LookupStorageByIdResponse + 30, // 360: productv1.ProductService.LookupWarehouseById:output_type -> productv1.LookupWarehouseByIdResponse + 114, // 361: productv1.ProductService.MutationBulkCreateAuthors:output_type -> productv1.MutationBulkCreateAuthorsResponse + 118, // 362: productv1.ProductService.MutationBulkCreateBlogPosts:output_type -> productv1.MutationBulkCreateBlogPostsResponse + 116, // 363: productv1.ProductService.MutationBulkUpdateAuthors:output_type -> productv1.MutationBulkUpdateAuthorsResponse + 120, // 364: productv1.ProductService.MutationBulkUpdateBlogPosts:output_type -> productv1.MutationBulkUpdateBlogPostsResponse + 110, // 365: productv1.ProductService.MutationCreateAuthor:output_type -> productv1.MutationCreateAuthorResponse + 106, // 366: productv1.ProductService.MutationCreateBlogPost:output_type -> productv1.MutationCreateBlogPostResponse + 102, // 367: productv1.ProductService.MutationCreateNullableFieldsType:output_type -> productv1.MutationCreateNullableFieldsTypeResponse + 98, // 368: productv1.ProductService.MutationCreateUser:output_type -> productv1.MutationCreateUserResponse + 100, // 369: productv1.ProductService.MutationPerformAction:output_type -> productv1.MutationPerformActionResponse + 112, // 370: productv1.ProductService.MutationUpdateAuthor:output_type -> productv1.MutationUpdateAuthorResponse + 108, // 371: productv1.ProductService.MutationUpdateBlogPost:output_type -> productv1.MutationUpdateBlogPostResponse + 104, // 372: productv1.ProductService.MutationUpdateNullableFieldsType:output_type -> productv1.MutationUpdateNullableFieldsTypeResponse + 88, // 373: productv1.ProductService.QueryAllAuthors:output_type -> productv1.QueryAllAuthorsResponse + 80, // 374: productv1.ProductService.QueryAllBlogPosts:output_type -> productv1.QueryAllBlogPostsResponse + 72, // 375: productv1.ProductService.QueryAllNullableFieldsTypes:output_type -> productv1.QueryAllNullableFieldsTypesResponse + 60, // 376: productv1.ProductService.QueryAllPets:output_type -> productv1.QueryAllPetsResponse + 82, // 377: productv1.ProductService.QueryAuthor:output_type -> productv1.QueryAuthorResponse + 84, // 378: productv1.ProductService.QueryAuthorById:output_type -> productv1.QueryAuthorByIdResponse + 86, // 379: productv1.ProductService.QueryAuthorsWithFilter:output_type -> productv1.QueryAuthorsWithFilterResponse + 74, // 380: productv1.ProductService.QueryBlogPost:output_type -> productv1.QueryBlogPostResponse + 76, // 381: productv1.ProductService.QueryBlogPostById:output_type -> productv1.QueryBlogPostByIdResponse + 78, // 382: productv1.ProductService.QueryBlogPostsWithFilter:output_type -> productv1.QueryBlogPostsWithFilterResponse + 90, // 383: productv1.ProductService.QueryBulkSearchAuthors:output_type -> productv1.QueryBulkSearchAuthorsResponse + 92, // 384: productv1.ProductService.QueryBulkSearchBlogPosts:output_type -> productv1.QueryBulkSearchBlogPostsResponse + 46, // 385: productv1.ProductService.QueryCalculateTotals:output_type -> productv1.QueryCalculateTotalsResponse + 48, // 386: productv1.ProductService.QueryCategories:output_type -> productv1.QueryCategoriesResponse + 52, // 387: productv1.ProductService.QueryCategoriesByKind:output_type -> productv1.QueryCategoriesByKindResponse + 54, // 388: productv1.ProductService.QueryCategoriesByKinds:output_type -> productv1.QueryCategoriesByKindsResponse + 50, // 389: productv1.ProductService.QueryCategory:output_type -> productv1.QueryCategoryResponse + 44, // 390: productv1.ProductService.QueryComplexFilterType:output_type -> productv1.QueryComplexFilterTypeResponse + 56, // 391: productv1.ProductService.QueryFilterCategories:output_type -> productv1.QueryFilterCategoriesResponse + 36, // 392: productv1.ProductService.QueryNestedType:output_type -> productv1.QueryNestedTypeResponse + 66, // 393: productv1.ProductService.QueryNullableFieldsType:output_type -> productv1.QueryNullableFieldsTypeResponse + 68, // 394: productv1.ProductService.QueryNullableFieldsTypeById:output_type -> productv1.QueryNullableFieldsTypeByIdResponse + 70, // 395: productv1.ProductService.QueryNullableFieldsTypeWithFilter:output_type -> productv1.QueryNullableFieldsTypeWithFilterResponse + 58, // 396: productv1.ProductService.QueryRandomPet:output_type -> productv1.QueryRandomPetResponse + 64, // 397: productv1.ProductService.QueryRandomSearchResult:output_type -> productv1.QueryRandomSearchResultResponse + 38, // 398: productv1.ProductService.QueryRecursiveType:output_type -> productv1.QueryRecursiveTypeResponse + 62, // 399: productv1.ProductService.QuerySearch:output_type -> productv1.QuerySearchResponse + 94, // 400: productv1.ProductService.QueryTestContainer:output_type -> productv1.QueryTestContainerResponse + 96, // 401: productv1.ProductService.QueryTestContainers:output_type -> productv1.QueryTestContainersResponse + 40, // 402: productv1.ProductService.QueryTypeFilterWithArguments:output_type -> productv1.QueryTypeFilterWithArgumentsResponse + 42, // 403: productv1.ProductService.QueryTypeWithMultipleFilterFields:output_type -> productv1.QueryTypeWithMultipleFilterFieldsResponse + 34, // 404: productv1.ProductService.QueryUser:output_type -> productv1.QueryUserResponse + 32, // 405: productv1.ProductService.QueryUsers:output_type -> productv1.QueryUsersResponse + 160, // 406: productv1.ProductService.ResolveCategoryCategoryMetrics:output_type -> productv1.ResolveCategoryCategoryMetricsResponse + 170, // 407: productv1.ProductService.ResolveCategoryCategoryStatus:output_type -> productv1.ResolveCategoryCategoryStatusResponse + 175, // 408: productv1.ProductService.ResolveCategoryChildCategories:output_type -> productv1.ResolveCategoryChildCategoriesResponse + 165, // 409: productv1.ProductService.ResolveCategoryMascot:output_type -> productv1.ResolveCategoryMascotResponse + 195, // 410: productv1.ProductService.ResolveCategoryMetricsNormalizedScore:output_type -> productv1.ResolveCategoryMetricsNormalizedScoreResponse + 200, // 411: productv1.ProductService.ResolveCategoryMetricsRelatedCategory:output_type -> productv1.ResolveCategoryMetricsRelatedCategoryResponse + 180, // 412: productv1.ProductService.ResolveCategoryOptionalCategories:output_type -> productv1.ResolveCategoryOptionalCategoriesResponse + 155, // 413: productv1.ProductService.ResolveCategoryPopularityScore:output_type -> productv1.ResolveCategoryPopularityScoreResponse + 150, // 414: productv1.ProductService.ResolveCategoryProductCount:output_type -> productv1.ResolveCategoryProductCountResponse + 135, // 415: productv1.ProductService.ResolveProductMascotRecommendation:output_type -> productv1.ResolveProductMascotRecommendationResponse + 145, // 416: productv1.ProductService.ResolveProductProductDetails:output_type -> productv1.ResolveProductProductDetailsResponse + 130, // 417: productv1.ProductService.ResolveProductRecommendedCategory:output_type -> productv1.ResolveProductRecommendedCategoryResponse + 125, // 418: productv1.ProductService.ResolveProductShippingEstimate:output_type -> productv1.ResolveProductShippingEstimateResponse + 140, // 419: productv1.ProductService.ResolveProductStockStatus:output_type -> productv1.ResolveProductStockStatusResponse + 190, // 420: productv1.ProductService.ResolveSubcategoryFeaturedCategory:output_type -> productv1.ResolveSubcategoryFeaturedCategoryResponse + 185, // 421: productv1.ProductService.ResolveSubcategoryItemCount:output_type -> productv1.ResolveSubcategoryItemCountResponse + 205, // 422: productv1.ProductService.ResolveTestContainerDetails:output_type -> productv1.ResolveTestContainerDetailsResponse + 358, // [358:423] is the sub-list for method output_type + 293, // [293:358] is the sub-list for method input_type + 293, // [293:293] is the sub-list for extension type_name + 293, // [293:293] is the sub-list for extension extendee + 0, // [0:293] is the sub-list for field type_name } func init() { file_product_proto_init() } @@ -15245,16 +15865,16 @@ func file_product_proto_init() { if File_product_proto != nil { return } - file_product_proto_msgTypes[206].OneofWrappers = []any{ + file_product_proto_msgTypes[218].OneofWrappers = []any{ (*Animal_Cat)(nil), (*Animal_Dog)(nil), } - file_product_proto_msgTypes[208].OneofWrappers = []any{ + file_product_proto_msgTypes[220].OneofWrappers = []any{ (*SearchResult_Product)(nil), (*SearchResult_User)(nil), (*SearchResult_Category)(nil), } - file_product_proto_msgTypes[218].OneofWrappers = []any{ + file_product_proto_msgTypes[230].OneofWrappers = []any{ (*ActionResult_ActionSuccess)(nil), (*ActionResult_ActionError)(nil), } @@ -15264,7 +15884,7 @@ func file_product_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_product_proto_rawDesc), len(file_product_proto_rawDesc)), NumEnums: 2, - NumMessages: 266, + NumMessages: 278, NumExtensions: 0, NumServices: 1, }, diff --git a/v2/pkg/grpctest/productv1/product_grpc.pb.go b/v2/pkg/grpctest/productv1/product_grpc.pb.go index 3cd40a6eb3..aa2c9d912b 100644 --- a/v2/pkg/grpctest/productv1/product_grpc.pb.go +++ b/v2/pkg/grpctest/productv1/product_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.6.0 +// - protoc-gen-go-grpc v1.6.1 // - protoc v6.32.0 // source: product.proto @@ -50,6 +50,7 @@ const ( ProductService_QueryCategories_FullMethodName = "/productv1.ProductService/QueryCategories" ProductService_QueryCategoriesByKind_FullMethodName = "/productv1.ProductService/QueryCategoriesByKind" ProductService_QueryCategoriesByKinds_FullMethodName = "/productv1.ProductService/QueryCategoriesByKinds" + ProductService_QueryCategory_FullMethodName = "/productv1.ProductService/QueryCategory" ProductService_QueryComplexFilterType_FullMethodName = "/productv1.ProductService/QueryComplexFilterType" ProductService_QueryFilterCategories_FullMethodName = "/productv1.ProductService/QueryFilterCategories" ProductService_QueryNestedType_FullMethodName = "/productv1.ProductService/QueryNestedType" @@ -71,6 +72,7 @@ const ( ProductService_ResolveCategoryChildCategories_FullMethodName = "/productv1.ProductService/ResolveCategoryChildCategories" ProductService_ResolveCategoryMascot_FullMethodName = "/productv1.ProductService/ResolveCategoryMascot" ProductService_ResolveCategoryMetricsNormalizedScore_FullMethodName = "/productv1.ProductService/ResolveCategoryMetricsNormalizedScore" + ProductService_ResolveCategoryMetricsRelatedCategory_FullMethodName = "/productv1.ProductService/ResolveCategoryMetricsRelatedCategory" ProductService_ResolveCategoryOptionalCategories_FullMethodName = "/productv1.ProductService/ResolveCategoryOptionalCategories" ProductService_ResolveCategoryPopularityScore_FullMethodName = "/productv1.ProductService/ResolveCategoryPopularityScore" ProductService_ResolveCategoryProductCount_FullMethodName = "/productv1.ProductService/ResolveCategoryProductCount" @@ -79,6 +81,7 @@ const ( ProductService_ResolveProductRecommendedCategory_FullMethodName = "/productv1.ProductService/ResolveProductRecommendedCategory" ProductService_ResolveProductShippingEstimate_FullMethodName = "/productv1.ProductService/ResolveProductShippingEstimate" ProductService_ResolveProductStockStatus_FullMethodName = "/productv1.ProductService/ResolveProductStockStatus" + ProductService_ResolveSubcategoryFeaturedCategory_FullMethodName = "/productv1.ProductService/ResolveSubcategoryFeaturedCategory" ProductService_ResolveSubcategoryItemCount_FullMethodName = "/productv1.ProductService/ResolveSubcategoryItemCount" ProductService_ResolveTestContainerDetails_FullMethodName = "/productv1.ProductService/ResolveTestContainerDetails" ) @@ -123,6 +126,7 @@ type ProductServiceClient interface { QueryCategories(ctx context.Context, in *QueryCategoriesRequest, opts ...grpc.CallOption) (*QueryCategoriesResponse, error) QueryCategoriesByKind(ctx context.Context, in *QueryCategoriesByKindRequest, opts ...grpc.CallOption) (*QueryCategoriesByKindResponse, error) QueryCategoriesByKinds(ctx context.Context, in *QueryCategoriesByKindsRequest, opts ...grpc.CallOption) (*QueryCategoriesByKindsResponse, error) + QueryCategory(ctx context.Context, in *QueryCategoryRequest, opts ...grpc.CallOption) (*QueryCategoryResponse, error) QueryComplexFilterType(ctx context.Context, in *QueryComplexFilterTypeRequest, opts ...grpc.CallOption) (*QueryComplexFilterTypeResponse, error) QueryFilterCategories(ctx context.Context, in *QueryFilterCategoriesRequest, opts ...grpc.CallOption) (*QueryFilterCategoriesResponse, error) QueryNestedType(ctx context.Context, in *QueryNestedTypeRequest, opts ...grpc.CallOption) (*QueryNestedTypeResponse, error) @@ -144,6 +148,7 @@ type ProductServiceClient interface { ResolveCategoryChildCategories(ctx context.Context, in *ResolveCategoryChildCategoriesRequest, opts ...grpc.CallOption) (*ResolveCategoryChildCategoriesResponse, error) ResolveCategoryMascot(ctx context.Context, in *ResolveCategoryMascotRequest, opts ...grpc.CallOption) (*ResolveCategoryMascotResponse, error) ResolveCategoryMetricsNormalizedScore(ctx context.Context, in *ResolveCategoryMetricsNormalizedScoreRequest, opts ...grpc.CallOption) (*ResolveCategoryMetricsNormalizedScoreResponse, error) + ResolveCategoryMetricsRelatedCategory(ctx context.Context, in *ResolveCategoryMetricsRelatedCategoryRequest, opts ...grpc.CallOption) (*ResolveCategoryMetricsRelatedCategoryResponse, error) ResolveCategoryOptionalCategories(ctx context.Context, in *ResolveCategoryOptionalCategoriesRequest, opts ...grpc.CallOption) (*ResolveCategoryOptionalCategoriesResponse, error) ResolveCategoryPopularityScore(ctx context.Context, in *ResolveCategoryPopularityScoreRequest, opts ...grpc.CallOption) (*ResolveCategoryPopularityScoreResponse, error) ResolveCategoryProductCount(ctx context.Context, in *ResolveCategoryProductCountRequest, opts ...grpc.CallOption) (*ResolveCategoryProductCountResponse, error) @@ -152,6 +157,7 @@ type ProductServiceClient interface { ResolveProductRecommendedCategory(ctx context.Context, in *ResolveProductRecommendedCategoryRequest, opts ...grpc.CallOption) (*ResolveProductRecommendedCategoryResponse, error) ResolveProductShippingEstimate(ctx context.Context, in *ResolveProductShippingEstimateRequest, opts ...grpc.CallOption) (*ResolveProductShippingEstimateResponse, error) ResolveProductStockStatus(ctx context.Context, in *ResolveProductStockStatusRequest, opts ...grpc.CallOption) (*ResolveProductStockStatusResponse, error) + ResolveSubcategoryFeaturedCategory(ctx context.Context, in *ResolveSubcategoryFeaturedCategoryRequest, opts ...grpc.CallOption) (*ResolveSubcategoryFeaturedCategoryResponse, error) ResolveSubcategoryItemCount(ctx context.Context, in *ResolveSubcategoryItemCountRequest, opts ...grpc.CallOption) (*ResolveSubcategoryItemCountResponse, error) ResolveTestContainerDetails(ctx context.Context, in *ResolveTestContainerDetailsRequest, opts ...grpc.CallOption) (*ResolveTestContainerDetailsResponse, error) } @@ -474,6 +480,16 @@ func (c *productServiceClient) QueryCategoriesByKinds(ctx context.Context, in *Q return out, nil } +func (c *productServiceClient) QueryCategory(ctx context.Context, in *QueryCategoryRequest, opts ...grpc.CallOption) (*QueryCategoryResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(QueryCategoryResponse) + err := c.cc.Invoke(ctx, ProductService_QueryCategory_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *productServiceClient) QueryComplexFilterType(ctx context.Context, in *QueryComplexFilterTypeRequest, opts ...grpc.CallOption) (*QueryComplexFilterTypeResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryComplexFilterTypeResponse) @@ -684,6 +700,16 @@ func (c *productServiceClient) ResolveCategoryMetricsNormalizedScore(ctx context return out, nil } +func (c *productServiceClient) ResolveCategoryMetricsRelatedCategory(ctx context.Context, in *ResolveCategoryMetricsRelatedCategoryRequest, opts ...grpc.CallOption) (*ResolveCategoryMetricsRelatedCategoryResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ResolveCategoryMetricsRelatedCategoryResponse) + err := c.cc.Invoke(ctx, ProductService_ResolveCategoryMetricsRelatedCategory_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *productServiceClient) ResolveCategoryOptionalCategories(ctx context.Context, in *ResolveCategoryOptionalCategoriesRequest, opts ...grpc.CallOption) (*ResolveCategoryOptionalCategoriesResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ResolveCategoryOptionalCategoriesResponse) @@ -764,6 +790,16 @@ func (c *productServiceClient) ResolveProductStockStatus(ctx context.Context, in return out, nil } +func (c *productServiceClient) ResolveSubcategoryFeaturedCategory(ctx context.Context, in *ResolveSubcategoryFeaturedCategoryRequest, opts ...grpc.CallOption) (*ResolveSubcategoryFeaturedCategoryResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ResolveSubcategoryFeaturedCategoryResponse) + err := c.cc.Invoke(ctx, ProductService_ResolveSubcategoryFeaturedCategory_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *productServiceClient) ResolveSubcategoryItemCount(ctx context.Context, in *ResolveSubcategoryItemCountRequest, opts ...grpc.CallOption) (*ResolveSubcategoryItemCountResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ResolveSubcategoryItemCountResponse) @@ -824,6 +860,7 @@ type ProductServiceServer interface { QueryCategories(context.Context, *QueryCategoriesRequest) (*QueryCategoriesResponse, error) QueryCategoriesByKind(context.Context, *QueryCategoriesByKindRequest) (*QueryCategoriesByKindResponse, error) QueryCategoriesByKinds(context.Context, *QueryCategoriesByKindsRequest) (*QueryCategoriesByKindsResponse, error) + QueryCategory(context.Context, *QueryCategoryRequest) (*QueryCategoryResponse, error) QueryComplexFilterType(context.Context, *QueryComplexFilterTypeRequest) (*QueryComplexFilterTypeResponse, error) QueryFilterCategories(context.Context, *QueryFilterCategoriesRequest) (*QueryFilterCategoriesResponse, error) QueryNestedType(context.Context, *QueryNestedTypeRequest) (*QueryNestedTypeResponse, error) @@ -845,6 +882,7 @@ type ProductServiceServer interface { ResolveCategoryChildCategories(context.Context, *ResolveCategoryChildCategoriesRequest) (*ResolveCategoryChildCategoriesResponse, error) ResolveCategoryMascot(context.Context, *ResolveCategoryMascotRequest) (*ResolveCategoryMascotResponse, error) ResolveCategoryMetricsNormalizedScore(context.Context, *ResolveCategoryMetricsNormalizedScoreRequest) (*ResolveCategoryMetricsNormalizedScoreResponse, error) + ResolveCategoryMetricsRelatedCategory(context.Context, *ResolveCategoryMetricsRelatedCategoryRequest) (*ResolveCategoryMetricsRelatedCategoryResponse, error) ResolveCategoryOptionalCategories(context.Context, *ResolveCategoryOptionalCategoriesRequest) (*ResolveCategoryOptionalCategoriesResponse, error) ResolveCategoryPopularityScore(context.Context, *ResolveCategoryPopularityScoreRequest) (*ResolveCategoryPopularityScoreResponse, error) ResolveCategoryProductCount(context.Context, *ResolveCategoryProductCountRequest) (*ResolveCategoryProductCountResponse, error) @@ -853,6 +891,7 @@ type ProductServiceServer interface { ResolveProductRecommendedCategory(context.Context, *ResolveProductRecommendedCategoryRequest) (*ResolveProductRecommendedCategoryResponse, error) ResolveProductShippingEstimate(context.Context, *ResolveProductShippingEstimateRequest) (*ResolveProductShippingEstimateResponse, error) ResolveProductStockStatus(context.Context, *ResolveProductStockStatusRequest) (*ResolveProductStockStatusResponse, error) + ResolveSubcategoryFeaturedCategory(context.Context, *ResolveSubcategoryFeaturedCategoryRequest) (*ResolveSubcategoryFeaturedCategoryResponse, error) ResolveSubcategoryItemCount(context.Context, *ResolveSubcategoryItemCountRequest) (*ResolveSubcategoryItemCountResponse, error) ResolveTestContainerDetails(context.Context, *ResolveTestContainerDetailsRequest) (*ResolveTestContainerDetailsResponse, error) mustEmbedUnimplementedProductServiceServer() @@ -958,6 +997,9 @@ func (UnimplementedProductServiceServer) QueryCategoriesByKind(context.Context, func (UnimplementedProductServiceServer) QueryCategoriesByKinds(context.Context, *QueryCategoriesByKindsRequest) (*QueryCategoriesByKindsResponse, error) { return nil, status.Error(codes.Unimplemented, "method QueryCategoriesByKinds not implemented") } +func (UnimplementedProductServiceServer) QueryCategory(context.Context, *QueryCategoryRequest) (*QueryCategoryResponse, error) { + return nil, status.Error(codes.Unimplemented, "method QueryCategory not implemented") +} func (UnimplementedProductServiceServer) QueryComplexFilterType(context.Context, *QueryComplexFilterTypeRequest) (*QueryComplexFilterTypeResponse, error) { return nil, status.Error(codes.Unimplemented, "method QueryComplexFilterType not implemented") } @@ -1021,6 +1063,9 @@ func (UnimplementedProductServiceServer) ResolveCategoryMascot(context.Context, func (UnimplementedProductServiceServer) ResolveCategoryMetricsNormalizedScore(context.Context, *ResolveCategoryMetricsNormalizedScoreRequest) (*ResolveCategoryMetricsNormalizedScoreResponse, error) { return nil, status.Error(codes.Unimplemented, "method ResolveCategoryMetricsNormalizedScore not implemented") } +func (UnimplementedProductServiceServer) ResolveCategoryMetricsRelatedCategory(context.Context, *ResolveCategoryMetricsRelatedCategoryRequest) (*ResolveCategoryMetricsRelatedCategoryResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ResolveCategoryMetricsRelatedCategory not implemented") +} func (UnimplementedProductServiceServer) ResolveCategoryOptionalCategories(context.Context, *ResolveCategoryOptionalCategoriesRequest) (*ResolveCategoryOptionalCategoriesResponse, error) { return nil, status.Error(codes.Unimplemented, "method ResolveCategoryOptionalCategories not implemented") } @@ -1045,6 +1090,9 @@ func (UnimplementedProductServiceServer) ResolveProductShippingEstimate(context. func (UnimplementedProductServiceServer) ResolveProductStockStatus(context.Context, *ResolveProductStockStatusRequest) (*ResolveProductStockStatusResponse, error) { return nil, status.Error(codes.Unimplemented, "method ResolveProductStockStatus not implemented") } +func (UnimplementedProductServiceServer) ResolveSubcategoryFeaturedCategory(context.Context, *ResolveSubcategoryFeaturedCategoryRequest) (*ResolveSubcategoryFeaturedCategoryResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ResolveSubcategoryFeaturedCategory not implemented") +} func (UnimplementedProductServiceServer) ResolveSubcategoryItemCount(context.Context, *ResolveSubcategoryItemCountRequest) (*ResolveSubcategoryItemCountResponse, error) { return nil, status.Error(codes.Unimplemented, "method ResolveSubcategoryItemCount not implemented") } @@ -1630,6 +1678,24 @@ func _ProductService_QueryCategoriesByKinds_Handler(srv interface{}, ctx context return interceptor(ctx, in, info, handler) } +func _ProductService_QueryCategory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCategoryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServiceServer).QueryCategory(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ProductService_QueryCategory_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServiceServer).QueryCategory(ctx, req.(*QueryCategoryRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ProductService_QueryComplexFilterType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryComplexFilterTypeRequest) if err := dec(in); err != nil { @@ -2008,6 +2074,24 @@ func _ProductService_ResolveCategoryMetricsNormalizedScore_Handler(srv interface return interceptor(ctx, in, info, handler) } +func _ProductService_ResolveCategoryMetricsRelatedCategory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResolveCategoryMetricsRelatedCategoryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServiceServer).ResolveCategoryMetricsRelatedCategory(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ProductService_ResolveCategoryMetricsRelatedCategory_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServiceServer).ResolveCategoryMetricsRelatedCategory(ctx, req.(*ResolveCategoryMetricsRelatedCategoryRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ProductService_ResolveCategoryOptionalCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ResolveCategoryOptionalCategoriesRequest) if err := dec(in); err != nil { @@ -2152,6 +2236,24 @@ func _ProductService_ResolveProductStockStatus_Handler(srv interface{}, ctx cont return interceptor(ctx, in, info, handler) } +func _ProductService_ResolveSubcategoryFeaturedCategory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResolveSubcategoryFeaturedCategoryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServiceServer).ResolveSubcategoryFeaturedCategory(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ProductService_ResolveSubcategoryFeaturedCategory_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServiceServer).ResolveSubcategoryFeaturedCategory(ctx, req.(*ResolveSubcategoryFeaturedCategoryRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ProductService_ResolveSubcategoryItemCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ResolveSubcategoryItemCountRequest) if err := dec(in); err != nil { @@ -2319,6 +2421,10 @@ var ProductService_ServiceDesc = grpc.ServiceDesc{ MethodName: "QueryCategoriesByKinds", Handler: _ProductService_QueryCategoriesByKinds_Handler, }, + { + MethodName: "QueryCategory", + Handler: _ProductService_QueryCategory_Handler, + }, { MethodName: "QueryComplexFilterType", Handler: _ProductService_QueryComplexFilterType_Handler, @@ -2403,6 +2509,10 @@ var ProductService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ResolveCategoryMetricsNormalizedScore", Handler: _ProductService_ResolveCategoryMetricsNormalizedScore_Handler, }, + { + MethodName: "ResolveCategoryMetricsRelatedCategory", + Handler: _ProductService_ResolveCategoryMetricsRelatedCategory_Handler, + }, { MethodName: "ResolveCategoryOptionalCategories", Handler: _ProductService_ResolveCategoryOptionalCategories_Handler, @@ -2435,6 +2545,10 @@ var ProductService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ResolveProductStockStatus", Handler: _ProductService_ResolveProductStockStatus_Handler, }, + { + MethodName: "ResolveSubcategoryFeaturedCategory", + Handler: _ProductService_ResolveSubcategoryFeaturedCategory_Handler, + }, { MethodName: "ResolveSubcategoryItemCount", Handler: _ProductService_ResolveSubcategoryItemCount_Handler, diff --git a/v2/pkg/grpctest/testdata/products.graphqls b/v2/pkg/grpctest/testdata/products.graphqls index 531d431168..6b0d26e172 100644 --- a/v2/pkg/grpctest/testdata/products.graphqls +++ b/v2/pkg/grpctest/testdata/products.graphqls @@ -132,6 +132,8 @@ type Category { categoryStatus(checkHealth: Boolean!): ActionResult! @connect__fieldResolver(context: "id name") childCategories(include: Boolean): [Category!]! @connect__fieldResolver(context: "id name") optionalCategories(include: Boolean): [Category!] @connect__fieldResolver(context: "id name") + # The nullMetrics field is used to test that nested field resolvers are not invoked when the parent result is null. + nullMetrics: CategoryMetrics } type Subcategory { @@ -140,6 +142,7 @@ type Subcategory { description: String isActive: Boolean! itemCount(filters: SubcategoryItemFilter): Int! @connect__fieldResolver(context: "id") + featuredCategory(includeChildren: Boolean!): Category @connect__fieldResolver(context: "id") } type CategoryMetrics { @@ -149,8 +152,7 @@ type CategoryMetrics { timestamp: String! categoryId: ID! normalizedScore(baseline: Float!): Float! @connect__fieldResolver(context: "id value metricType") - # This will currently not generate a resolver as it is missing arguments. - relatedCategory: Category @connect__fieldResolver(context: "categoryId") + relatedCategory(include: Boolean): Category @connect__fieldResolver(context: "categoryId") } enum CategoryKind { @@ -188,6 +190,7 @@ type Owner { id: ID! name: String! contact: ContactInfo! + pet: Animal! } type ContactInfo { @@ -455,6 +458,7 @@ type Query { ): [TypeWithComplexFilterInput!]! calculateTotals(orders: [OrderInput!]!): [Order!]! categories: [Category!]! + category(id: ID!): Category categoriesByKind(kind: CategoryKind!): [Category!]! categoriesByKinds(kinds: [CategoryKind!]!): [Category!]! filterCategories(filter: CategoryFilter!): [Category!]!