From 396536ff9620f72f5943bfbc7af1baae3be0b18c Mon Sep 17 00:00:00 2001 From: Q00 Date: Wed, 25 Oct 2023 17:44:11 +0900 Subject: [PATCH 1/5] feat: make nullable when proto field optional --- packages/handlers/grpc/src/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/handlers/grpc/src/index.ts b/packages/handlers/grpc/src/index.ts index f7268636bf238..65b0b4a22bde8 100644 --- a/packages/handlers/grpc/src/index.ts +++ b/packages/handlers/grpc/src/index.ts @@ -550,7 +550,7 @@ export default class GrpcHandler implements MeshHandler { description, fields: {}, }); - for (const [fieldName, { type, rule, comment, keyType }] of fieldEntries) { + for (const [fieldName, { type, rule, comment, keyType, options }] of fieldEntries) { logger.debug(`Visiting ${currentPath}.nested.fields[${fieldName}]`); const baseFieldTypePath = type.split('.'); inputTC.addFields({ @@ -566,6 +566,9 @@ export default class GrpcHandler implements MeshHandler { baseFieldTypePath, ); fieldInputTypeName = getTypeName(this.schemaComposer, fieldTypePath, true); + if (!options?.proto3_optional) { + fieldInputTypeName = fieldInputTypeName + '!'; + } } return rule === 'repeated' ? `[${fieldInputTypeName}]` : fieldInputTypeName; }, @@ -585,6 +588,9 @@ export default class GrpcHandler implements MeshHandler { baseFieldTypePath, ); fieldTypeName = getTypeName(this.schemaComposer, fieldTypePath, false); + if (!options?.proto3_optional) { + fieldTypeName = fieldTypeName + '!'; + } } return rule === 'repeated' ? `[${fieldTypeName}]` : fieldTypeName; }, From 128dfa9e34ce37447d411a07e0a50ea5faa0185a Mon Sep 17 00:00:00 2001 From: Q00 Date: Wed, 25 Oct 2023 18:14:36 +0900 Subject: [PATCH 2/5] test: update snapshot of new version --- .../test/__snapshots__/handler.spec.ts.snap | 328 +++++++++--------- 1 file changed, 164 insertions(+), 164 deletions(-) diff --git a/packages/handlers/grpc/test/__snapshots__/handler.spec.ts.snap b/packages/handlers/grpc/test/__snapshots__/handler.spec.ts.snap index 7785c138e56c8..6e8dc614a9b91 100644 --- a/packages/handlers/grpc/test/__snapshots__/handler.spec.ts.snap +++ b/packages/handlers/grpc/test/__snapshots__/handler.spec.ts.snap @@ -30,13 +30,13 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"foo\\":{\\" "Comment 5: This is a comment on one line, delimiters slash star star at beginning of the line. Trailing comment delimiter at beginning of next line after comment." type foo__SampleResponse { - sample_id: String + sample_id: String! } "Comment 7: This is a comment with slash followed by two stars at the beginning. The first comment delimiter is not at the beginning of the line." input foo__GetSampleRequest_Input { "Comment 8: This is a comment with slash star delimiter on the same line as a field definition." - sample_id: String + sample_id: String! } enum ConnectivityState { @@ -58,18 +58,18 @@ type Mutation { input foo__CreateSampleRequest_Input { "Comment 6: This is a comment with slash followed by two stars at the beginning. The first comment delimiter is at the beginning of the line. Trailing comment delimiter on same line as text." - description: String - type: String + description: String! + type: String! } input foo__UpdateSampleRequest_Input { "Comment 10: This is a comment with slash star star delimiter on the same line as a field definition." - sample_id: String + sample_id: String! } input foo__DeleteSampleRequest_Input { "Comment 12: This is a two-slash comment on the same line as a field definition." - sample_id: String + sample_id: String! } scalar ObjMap" @@ -102,23 +102,23 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"foos\\":{\\ } type foos__GetFoosResponse { - abcd: foos__Bam + abcd: foos__Bam! } type foos__Bam { - id: BigInt + id: BigInt! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." scalar BigInt input foos__GetBamRequest_Input { - id: Int - abcd: foos__Bam_Input + id: Int! + abcd: foos__Bam_Input! } input foos__Bam_Input { - id: BigInt + id: BigInt! } enum ConnectivityState { @@ -159,18 +159,18 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"foo\\":{\\" } type foo__GetFOOsResponse { - foos: [foo__FOO] + foos: [foo__FOO!] } type foo__FOO { - id: BigInt + id: BigInt! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." scalar BigInt input foo__GetFOOsRequest_Input { - id: Int + id: Int! } enum ConnectivityState { @@ -225,23 +225,23 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n "movie result message, contains list of movies" type io__xtech__MoviesResult { "list of movies" - result: [io__xtech__Movie] + result: [io__xtech__Movie!] } "movie message payload" type io__xtech__Movie { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp! + genre: io__xtech__Genre! } type google__protobuf__Timestamp { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." @@ -254,29 +254,29 @@ enum io__xtech__Genre { } input io__xtech__MovieRequest_Input { - movie: io__xtech__Movie_Input + movie: io__xtech__Movie_Input! } "movie message payload" input io__xtech__Movie_Input { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp_Input - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp_Input! + genre: io__xtech__Genre! } input google__protobuf__Timestamp_Input { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } scalar io__xtech__EmptyRequest @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") input io__xtech__SearchByCastRequest_Input { - castName: String + castName: String! } enum ConnectivityState { @@ -326,13 +326,13 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n } type io__xtech__OrganizationProto { - id: String - owner: String - name: String - description: String - image_url: String - state: io__xtech__OrganizationStateProto - default_org: Boolean + id: String! + owner: String! + name: String! + description: String! + image_url: String! + state: io__xtech__OrganizationStateProto! + default_org: Boolean! } enum io__xtech__OrganizationStateProto { @@ -384,19 +384,19 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n } type io__xtech__Result { - result: [io__xtech__Item] + result: [io__xtech__Item!] } type io__xtech__Item { - name: String + name: String! } input io__xtech__TopLevel__Nested_Input { - movie: io__xtech__Item_Input + movie: io__xtech__Item_Input! } input io__xtech__Item_Input { - name: String + name: String! } enum ConnectivityState { @@ -437,13 +437,13 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"TestMessage } type TestMessage { - input: TestMessage__Input + input: TestMessage__Input! } scalar TestMessage__Input @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") input TestMessage_Input { - input: TestMessage__Input_Input + input: TestMessage__Input_Input! } scalar TestMessage__Input_Input @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") @@ -547,23 +547,23 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n "movie result message, contains list of movies" type io__xtech__MoviesResult { "list of movies" - result: [io__xtech__Movie] + result: [io__xtech__Movie!] } "movie message payload" type io__xtech__Movie { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp! + genre: io__xtech__Genre! } type google__protobuf__Timestamp { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." @@ -576,27 +576,27 @@ enum io__xtech__Genre { } input io__xtech__MovieRequest_Input { - movie: io__xtech__Movie_Input + movie: io__xtech__Movie_Input! } "movie message payload" input io__xtech__Movie_Input { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp_Input - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp_Input! + genre: io__xtech__Genre! } input google__protobuf__Timestamp_Input { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } input io__xtech__SearchByCastRequest_Input { - castName: String + castName: String! } enum ConnectivityState { @@ -644,19 +644,19 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n } type io__xtech__Result { - result: [io__xtech__Item] + result: [io__xtech__Item!] } type io__xtech__Item { - name: String + name: String! } input io__xtech__TopLevel__Nested_Input { - movie: io__xtech__Item_Input + movie: io__xtech__Item_Input! } input io__xtech__Item_Input { - name: String + name: String! } enum ConnectivityState { @@ -697,19 +697,19 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"Item\\":{\\ } type Result { - result: [Item] + result: [Item!] } type Item { - name: String + name: String! } input TopLevel__Nested_Input { - movie: Item_Input + movie: Item_Input! } input Item_Input { - name: String + name: String! } enum ConnectivityState { @@ -763,23 +763,23 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n } type io__outside__MoviesResult { - result: [io__xtech__Movie] + result: [io__xtech__Movie!] } "movie message payload" type io__xtech__Movie { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp! + genre: io__xtech__Genre! } type google__protobuf__Timestamp { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." @@ -792,23 +792,23 @@ enum io__xtech__Genre { } input io__outside__MovieRequest_Input { - movie: io__xtech__Movie_Input + movie: io__xtech__Movie_Input! } "movie message payload" input io__xtech__Movie_Input { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp_Input - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp_Input! + genre: io__xtech__Genre! } input google__protobuf__Timestamp_Input { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } enum ConnectivityState { @@ -822,15 +822,15 @@ enum ConnectivityState { "movie result message, contains list of movies" type io__xtech__MoviesResult { "list of movies" - result: [io__xtech__Movie] + result: [io__xtech__Movie!] } input io__xtech__MovieRequest_Input { - movie: io__xtech__Movie_Input + movie: io__xtech__Movie_Input! } input io__xtech__SearchByCastRequest_Input { - castName: String + castName: String! } type Subscription { @@ -870,25 +870,25 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"Item\\":{\\ } type Result { - result: [Item] + result: [Item!] } type Item { - boolean: Boolean - bytesType: Byte - doubleNum: Float - fixedint32: Int - fixedint64: BigInt - floatNum: Float - integer32: Int - integer64: BigInt - sfixedint32: Int - sfixedint64: BigInt - sinteger32: Int - sinteger64: BigInt - str: String - uinteger32: UnsignedInt - uinteger64: BigInt + boolean: Boolean! + bytesType: Byte! + doubleNum: Float! + fixedint32: Int! + fixedint64: BigInt! + floatNum: Float! + integer32: Int! + integer64: BigInt! + sfixedint32: Int! + sfixedint64: BigInt! + sinteger32: Int! + sinteger64: BigInt! + str: String! + uinteger32: UnsignedInt! + uinteger64: BigInt! } "The \`Byte\` scalar type represents byte value as a Buffer" @@ -901,21 +901,21 @@ scalar BigInt scalar UnsignedInt input Item_Input { - boolean: Boolean - bytesType: Byte - doubleNum: Float - fixedint32: Int - fixedint64: BigInt - floatNum: Float - integer32: Int - integer64: BigInt - sfixedint32: Int - sfixedint64: BigInt - sinteger32: Int - sinteger64: BigInt - str: String - uinteger32: UnsignedInt - uinteger64: BigInt + boolean: Boolean! + bytesType: Byte! + doubleNum: Float! + fixedint32: Int! + fixedint64: BigInt! + floatNum: Float! + integer32: Int! + integer64: BigInt! + sfixedint32: Int! + sfixedint64: BigInt! + sinteger32: Int! + sinteger64: BigInt! + str: String! + uinteger32: UnsignedInt! + uinteger64: BigInt! } enum ConnectivityState { @@ -969,23 +969,23 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n "movie result message, contains list of movies" type io__xtech__MoviesResult { "list of movies" - result: [io__xtech__Movie] + result: [io__xtech__Movie!] } "movie message payload" type io__xtech__Movie { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp! + genre: io__xtech__Genre! } type google__protobuf__Timestamp { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." @@ -998,27 +998,27 @@ enum io__xtech__Genre { } input io__xtech__movie_request_Input { - movie: io__xtech__Movie_Input + movie: io__xtech__Movie_Input! } "movie message payload" input io__xtech__Movie_Input { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp_Input - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp_Input! + genre: io__xtech__Genre! } input google__protobuf__Timestamp_Input { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } input io__xtech__SearchByCastRequest_Input { - castName: String + castName: String! } enum ConnectivityState { @@ -1080,23 +1080,23 @@ type Query @grpcRootJson(name: "Root0", rootJson: "{\\"nested\\":{\\"io\\":{\\"n "movie result message, contains list of movies" type io__xtech__MoviesResult { "list of movies" - result: [io__xtech__Movie] + result: [io__xtech__Movie!] } "movie message payload" type io__xtech__Movie { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp! + genre: io__xtech__Genre! } type google__protobuf__Timestamp { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } "The \`BigInt\` scalar type represents non-fractional signed whole numeric values." @@ -1109,27 +1109,27 @@ enum io__xtech__Genre { } input io__xtech__movie_request_Input { - movie: io__xtech__Movie_Input + movie: io__xtech__Movie_Input! } "movie message payload" input io__xtech__Movie_Input { - name: String - year: Int - rating: Float + name: String! + year: Int! + rating: Float! "list of cast" - cast: [String] - time: google__protobuf__Timestamp_Input - genre: io__xtech__Genre + cast: [String!] + time: google__protobuf__Timestamp_Input! + genre: io__xtech__Genre! } input google__protobuf__Timestamp_Input { - seconds: BigInt - nanos: Int + seconds: BigInt! + nanos: Int! } input io__xtech__movie_request_by_ids_Input { - movieIds: [String] + movieIds: [String!] } enum ConnectivityState { @@ -1148,7 +1148,7 @@ type Mutation { } input io__xtech__SearchByCastRequest_Input { - castName: String + castName: String! } type Subscription { From 65d184427983b6df4fd9e03872e9801050c7bc98 Mon Sep 17 00:00:00 2001 From: Q00 Date: Wed, 25 Oct 2023 18:30:58 +0900 Subject: [PATCH 3/5] chore: add changeset --- .changeset/old-dryers-tap.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/old-dryers-tap.md diff --git a/.changeset/old-dryers-tap.md b/.changeset/old-dryers-tap.md new file mode 100644 index 0000000000000..db93d2f62a7fd --- /dev/null +++ b/.changeset/old-dryers-tap.md @@ -0,0 +1,5 @@ +--- +'@graphql-mesh/grpc': minor +--- + +make required field of graphql schema using protobuf field From 5b350eaacf9aa7ead2d2c52f5363332a72bfb32a Mon Sep 17 00:00:00 2001 From: Q00 Date: Mon, 30 Oct 2023 12:50:32 +0900 Subject: [PATCH 4/5] chore: update dependency --- packages/container/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/container/package.json b/packages/container/package.json index 3f6092ea77c44..b99ca4502c006 100644 --- a/packages/container/package.json +++ b/packages/container/package.json @@ -1,6 +1,6 @@ { - "name": "@graphql-mesh/container", - "version": "0.2.4", + "name": "@q00/container", + "version": "0.2.5", "type": "module", "repository": { "type": "git", @@ -19,7 +19,7 @@ "@graphql-mesh/cli": "0.87.15", "@graphql-mesh/config": "0.97.14", "@graphql-mesh/graphql": "0.95.7", - "@graphql-mesh/grpc": "0.96.0", + "@q00/grpc": "0.96.1", "@graphql-mesh/json-schema": "0.95.11", "@graphql-mesh/odata": "0.95.8", "@graphql-mesh/openapi": "0.95.11", From e0ac7512ab39aab451a552dbe4b563539ee495db Mon Sep 17 00:00:00 2001 From: Q00 Date: Mon, 30 Oct 2023 20:02:33 +0900 Subject: [PATCH 5/5] refactor: refactor checking optional for grpc reflection --- packages/handlers/grpc/src/index.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/handlers/grpc/src/index.ts b/packages/handlers/grpc/src/index.ts index 65b0b4a22bde8..3fa767925d875 100644 --- a/packages/handlers/grpc/src/index.ts +++ b/packages/handlers/grpc/src/index.ts @@ -539,6 +539,10 @@ export default class GrpcHandler implements MeshHandler { string, protobufjs.IField & { comment: string; keyType?: string }, ][]; + const oneofEntries = nested.oneofs ?? {} as { + [k: string]: protobufjs.IOneOf; + }; + if (fieldEntries.length) { const inputTC = this.schemaComposer.createInputTC({ name: inputTypeName, @@ -550,8 +554,9 @@ export default class GrpcHandler implements MeshHandler { description, fields: {}, }); - for (const [fieldName, { type, rule, comment, keyType, options }] of fieldEntries) { + for (const [fieldName, { type, rule, comment, keyType }] of fieldEntries) { logger.debug(`Visiting ${currentPath}.nested.fields[${fieldName}]`); + const isOptional = oneofEntries[`_${fieldName}`]?.oneof.includes(fieldName) const baseFieldTypePath = type.split('.'); inputTC.addFields({ [fieldName]: { @@ -566,7 +571,7 @@ export default class GrpcHandler implements MeshHandler { baseFieldTypePath, ); fieldInputTypeName = getTypeName(this.schemaComposer, fieldTypePath, true); - if (!options?.proto3_optional) { + if (!isOptional) { fieldInputTypeName = fieldInputTypeName + '!'; } } @@ -588,7 +593,7 @@ export default class GrpcHandler implements MeshHandler { baseFieldTypePath, ); fieldTypeName = getTypeName(this.schemaComposer, fieldTypePath, false); - if (!options?.proto3_optional) { + if (!isOptional) { fieldTypeName = fieldTypeName + '!'; } }