diff --git a/packages/@proto-graphql/codegen-core/package.json b/packages/@proto-graphql/codegen-core/package.json index f40de95b..4f0a959a 100644 --- a/packages/@proto-graphql/codegen-core/package.json +++ b/packages/@proto-graphql/codegen-core/package.json @@ -2,13 +2,7 @@ "name": "@proto-graphql/codegen-core", "version": "0.5.2", "description": "", - "keywords": [ - "graphql", - "grpc", - "nexus", - "protobuf", - "typescript" - ], + "keywords": ["graphql", "grpc", "nexus", "protobuf", "typescript"], "repository": "git@github.com:proto-graphql/proto-graphql-js.git", "author": "izumin5210 ", "license": "MIT", @@ -28,12 +22,7 @@ } } }, - "files": [ - "src/", - "dist/", - "!src/**/*.test.ts", - "!src/**/__tests__/" - ], + "files": ["src/", "dist/", "!src/**/*.test.ts", "!src/**/__tests__/"], "sideEffects": false, "private": false, "publishConfig": { diff --git a/packages/@proto-graphql/protoc-plugin-helpers/package.json b/packages/@proto-graphql/protoc-plugin-helpers/package.json index 3237826c..6911c647 100644 --- a/packages/@proto-graphql/protoc-plugin-helpers/package.json +++ b/packages/@proto-graphql/protoc-plugin-helpers/package.json @@ -2,13 +2,7 @@ "name": "@proto-graphql/protoc-plugin-helpers", "version": "0.4.2", "description": "", - "keywords": [ - "graphql", - "grpc", - "nexus", - "protobuf", - "typescript" - ], + "keywords": ["graphql", "grpc", "nexus", "protobuf", "typescript"], "repository": "git@github.com:proto-graphql/proto-graphql-js.git", "author": "izumin5210 ", "license": "MIT", @@ -28,12 +22,7 @@ } } }, - "files": [ - "src/", - "dist/", - "!src/**/*.test.ts", - "!src/**/__tests__/" - ], + "files": ["src/", "dist/", "!src/**/*.test.ts", "!src/**/__tests__/"], "sideEffects": false, "private": false, "publishConfig": { diff --git a/packages/@proto-graphql/scalars-protobuf-es/package.json b/packages/@proto-graphql/scalars-protobuf-es/package.json index 4fde49a1..a337811b 100644 --- a/packages/@proto-graphql/scalars-protobuf-es/package.json +++ b/packages/@proto-graphql/scalars-protobuf-es/package.json @@ -2,12 +2,7 @@ "name": "@proto-graphql/scalars-protobuf-es", "version": "0.4.2", "description": "", - "keywords": [ - "graphql", - "grpc", - "protobuf", - "typescript" - ], + "keywords": ["graphql", "grpc", "protobuf", "typescript"], "repository": "git@github.com:proto-graphql/proto-graphql-js.git", "author": "izumin5210 ", "license": "MIT", @@ -27,12 +22,7 @@ } } }, - "files": [ - "src/", - "dist/", - "!src/**/*.test.ts", - "!src/**/__tests__/" - ], + "files": ["src/", "dist/", "!src/**/*.test.ts", "!src/**/__tests__/"], "sideEffects": false, "private": false, "publishConfig": { diff --git a/packages/@proto-nexus/proto-fields-plugin/package.json b/packages/@proto-nexus/proto-fields-plugin/package.json index b0b8d2a3..67af43d0 100644 --- a/packages/@proto-nexus/proto-fields-plugin/package.json +++ b/packages/@proto-nexus/proto-fields-plugin/package.json @@ -2,13 +2,7 @@ "name": "@proto-nexus/proto-fields-plugin", "version": "0.5.6", "description": "Nexus plugin for building subset types from proto-nexus's artifacts", - "keywords": [ - "graphql", - "grpc", - "nexus", - "protobuf", - "typescript" - ], + "keywords": ["graphql", "grpc", "nexus", "protobuf", "typescript"], "repository": "git@github.com:proto-graphql/proto-graphql-js.git", "author": "izumin5210 ", "license": "MIT", @@ -30,12 +24,7 @@ "engines": { "node": ">= 14.0.0" }, - "files": [ - "src/", - "dist/", - "!src/**/*.test.ts", - "!src/**/__tests__/" - ], + "files": ["src/", "dist/", "!src/**/*.test.ts", "!src/**/__tests__/"], "peerDependencies": { "nexus": "^1.0.0" }, diff --git a/packages/protoc-gen-nexus/package.json b/packages/protoc-gen-nexus/package.json index 09a8bdec..e0355e98 100644 --- a/packages/protoc-gen-nexus/package.json +++ b/packages/protoc-gen-nexus/package.json @@ -2,13 +2,7 @@ "name": "protoc-gen-nexus", "version": "0.8.2", "description": "Generate DSL for GraphQL Nexus from Protocol Buffers IDL", - "keywords": [ - "graphql", - "grpc", - "nexus", - "protobuf", - "typescript" - ], + "keywords": ["graphql", "grpc", "nexus", "protobuf", "typescript"], "bin": { "protoc-gen-nexus": "./bin/protoc-gen-nexus.cjs" }, @@ -31,13 +25,7 @@ } } }, - "files": [ - "bin/", - "src/", - "dist/", - "!src/**/*.test.ts", - "!src/**/__tests__/" - ], + "files": ["bin/", "src/", "dist/", "!src/**/*.test.ts", "!src/**/__tests__/"], "sideEffects": false, "private": false, "publishConfig": { diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/enumType.test.ts.snap b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/enumType.test.ts.snap new file mode 100644 index 00000000..629de3ad --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/enumType.test.ts.snap @@ -0,0 +1,157 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createEnumTypeCode > google-protobuf > 'generates code for a simple enum' 1`] = ` +"import { enumType } from "nexus"; + +export const MyEnum = enumType({ + "name": "MyEnum", + "members": [{ "name": "FOO", "value": 1, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_FOO" } } }, { + "name": "BAR", + "value": 2, + "description": "This is Bar.", + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAR" } }, + }, { "name": "BAZ", "value": 3, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAZ" } } }], + "extensions": { + "protobufEnum": { "name": "MyEnum", "fullName": "testapi.enums.MyEnum", "package": "testapi.enums" }, + }, +}); +" +`; + +exports[`createEnumTypeCode > google-protobuf > 'generates code for an enum without un…' 1`] = ` +"import { enumType } from "nexus"; + +export const MyEnumWithoutUnspecified = enumType({ + "name": "MyEnumWithoutUnspecified", + "members": [{ + "name": "FOO", + "value": 0, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_FOO" } }, + }, { + "name": "BAR", + "value": 1, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAR" } }, + }, { + "name": "BAZ", + "value": 2, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAZ" } }, + }], + "extensions": { + "protobufEnum": { + "name": "MyEnumWithoutUnspecified", + "fullName": "testapi.enums.MyEnumWithoutUnspecified", + "package": "testapi.enums", + }, + }, +}); +" +`; + +exports[`createEnumTypeCode > google-protobuf > 'generates code for enum with extensio…' 1`] = ` +"import { enumType } from "nexus"; + +export const TestPrefixPrefixedEnum = enumType({ + "name": "TestPrefixPrefixedEnum", + "members": [ + { "name": "PREFIXED_FOO", "value": 1, "extensions": { "protobufEnumValue": { "name": "PREFIXED_FOO" } } }, + { "name": "PREFIXED_BAR", "value": 2, "extensions": { "protobufEnumValue": { "name": "PREFIXED_BAR" } } }, + ], + "extensions": { + "protobufEnum": { + "name": "PrefixedEnum", + "fullName": "testapis.extensions.PrefixedEnum", + "package": "testapis.extensions", + }, + }, +}); +" +`; + +exports[`createEnumTypeCode > google-protobuf > 'generates code for nested enum' 1`] = ` +"import { enumType } from "nexus"; + +export const ParentMessageNestedEnum = enumType({ + "name": "ParentMessageNestedEnum", + "members": [{ "name": "FOO", "value": 1, "extensions": { "protobufEnumValue": { "name": "FOO" } } }, { + "name": "BAR", + "value": 2, + "extensions": { "protobufEnumValue": { "name": "BAR" } }, + }], + "extensions": { + "protobufEnum": { + "name": "NestedEnum", + "fullName": "testapis.nested.ParentMessage.NestedEnum", + "package": "testapis.nested", + }, + }, +}); +" +`; + +exports[`createEnumTypeCode > protobufjs > 'generates code for a simple enum' 1`] = ` +"import { enumType } from "nexus"; + +export const MyEnum = enumType({ + "name": "MyEnum", + "members": [{ "name": "FOO", "value": 1, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_FOO" } } }, { + "name": "BAR", + "value": 2, + "description": "This is Bar.", + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAR" } }, + }, { "name": "BAZ", "value": 3, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAZ" } } }], + "extensions": { + "protobufEnum": { "name": "MyEnum", "fullName": "testapi.enums.MyEnum", "package": "testapi.enums" }, + }, +}); +" +`; + +exports[`createEnumTypeCode > protobufjs > 'generates code for an enum without un…' 1`] = ` +"import { enumType } from "nexus"; + +export const MyEnumWithoutUnspecified = enumType({ + "name": "MyEnumWithoutUnspecified", + "members": [{ + "name": "FOO", + "value": 0, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_FOO" } }, + }, { + "name": "BAR", + "value": 1, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAR" } }, + }, { + "name": "BAZ", + "value": 2, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAZ" } }, + }], + "extensions": { + "protobufEnum": { + "name": "MyEnumWithoutUnspecified", + "fullName": "testapi.enums.MyEnumWithoutUnspecified", + "package": "testapi.enums", + }, + }, +}); +" +`; + +exports[`createEnumTypeCode > protobufjs > 'generates code for nested enum' 1`] = ` +"import { enumType } from "nexus"; + +export const ParentMessageNestedEnum = enumType({ + "name": "ParentMessageNestedEnum", + "members": [{ "name": "FOO", "value": 1, "extensions": { "protobufEnumValue": { "name": "FOO" } } }, { + "name": "BAR", + "value": 2, + "extensions": { "protobufEnumValue": { "name": "BAR" } }, + }], + "extensions": { + "protobufEnum": { + "name": "NestedEnum", + "fullName": "testapis.nested.ParentMessage.NestedEnum", + "package": "testapis.nested", + }, + }, +}); +" +`; diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/inputObjectType.test.ts.snap b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/inputObjectType.test.ts.snap new file mode 100644 index 00000000..b392988c --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/inputObjectType.test.ts.snap @@ -0,0 +1,1216 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createInputObjectTypeCode > google-protobuf > 'generates code for a simple input obj…' 1`] = ` +"import { Primitives } from "@testapis/google-protobuf/testapis/primitives/primitives_pb"; +import { inputObjectType, list, nonNull } from "nexus"; +import { stringToNumber } from "proto-nexus"; + +export const PrimitivesInput = Object.assign( + inputObjectType({ + "name": "PrimitivesInput", + "definition": (t) => { + t.field("requiredDoubleValue", { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }); + t.field("requiredFloatValue", { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }); + t.field("requiredInt32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValue", { + "type": nonNull("Boolean"), + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }); + t.field("requiredStringValue", { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }); + t.field("requiredBytesValue", { + "type": nonNull("Byte"), + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }); + t.field("requiredDoubleValues", { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }); + t.field("requiredFloatValues", { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }); + t.field("requiredInt32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValues", { + "type": nonNull(list(nonNull("Boolean"))), + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }); + t.field("requiredStringValues", { + "type": nonNull(list(nonNull("String"))), + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }); + t.field("requiredBytesValues", { + "type": nonNull(list(nonNull("Byte"))), + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["PrimitivesInput"]): Primitives => { + const output = new Primitives(); + output.setRequiredDoubleValue(input.requiredDoubleValue); + output.setRequiredFloatValue(input.requiredFloatValue); + output.setRequiredInt32Value(input.requiredInt32Value); + output.setRequiredInt64Value(stringToNumber(input.requiredInt64Value)); + output.setRequiredUint32Value(input.requiredUint32Value); + output.setRequiredUint64Value(stringToNumber(input.requiredUint64Value)); + output.setRequiredSint32Value(input.requiredSint32Value); + output.setRequiredSint64Value(stringToNumber(input.requiredSint64Value)); + output.setRequiredFixed32Value(input.requiredFixed32Value); + output.setRequiredFixed64Value(stringToNumber(input.requiredFixed64Value)); + output.setRequiredSfixed32Value(input.requiredSfixed32Value); + output.setRequiredSfixed64Value(stringToNumber(input.requiredSfixed64Value)); + output.setRequiredBoolValue(input.requiredBoolValue); + output.setRequiredStringValue(input.requiredStringValue); + output.setRequiredBytesValue(input.requiredBytesValue); + output.setRequiredDoubleValuesList(input.requiredDoubleValues.map((v) => v)); + output.setRequiredFloatValuesList(input.requiredFloatValues.map((v) => v)); + output.setRequiredInt32ValuesList(input.requiredInt32Values.map((v) => v)); + output.setRequiredInt64ValuesList(input.requiredInt64Values.map((v) => stringToNumber(v))); + output.setRequiredUint32ValuesList(input.requiredUint32Values.map((v) => v)); + output.setRequiredUint64ValuesList(input.requiredUint64Values.map((v) => stringToNumber(v))); + output.setRequiredSint32ValuesList(input.requiredSint32Values.map((v) => v)); + output.setRequiredSint64ValuesList(input.requiredSint64Values.map((v) => stringToNumber(v))); + output.setRequiredFixed32ValuesList(input.requiredFixed32Values.map((v) => v)); + output.setRequiredFixed64ValuesList(input.requiredFixed64Values.map((v) => stringToNumber(v))); + output.setRequiredSfixed32ValuesList(input.requiredSfixed32Values.map((v) => v)); + output.setRequiredSfixed64ValuesList(input.requiredSfixed64Values.map((v) => stringToNumber(v))); + output.setRequiredBoolValuesList(input.requiredBoolValues.map((v) => v)); + output.setRequiredStringValuesList(input.requiredStringValues.map((v) => v)); + output.setRequiredBytesValuesList(input.requiredBytesValues.map((v) => v)); + return output; + }, + _protoNexus: { + fields: { + requiredDoubleValue: { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }, + requiredFloatValue: { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }, + requiredInt32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }, + requiredInt64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }, + requiredUint32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }, + requiredUint64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }, + requiredSint32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }, + requiredSint64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }, + requiredFixed32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }, + requiredFixed64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }, + requiredSfixed32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }, + requiredSfixed64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }, + requiredBoolValue: { + "type": nonNull("Boolean"), + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }, + requiredStringValue: { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }, + requiredBytesValue: { + "type": nonNull("Byte"), + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }, + requiredDoubleValues: { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }, + requiredFloatValues: { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }, + requiredInt32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }, + requiredInt64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }, + requiredUint32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }, + requiredUint64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }, + requiredSint32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }, + requiredSint64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }, + requiredFixed32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }, + requiredFixed64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }, + requiredSfixed32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }, + requiredSfixed64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }, + requiredBoolValues: { + "type": nonNull(list(nonNull("Boolean"))), + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }, + requiredStringValues: { + "type": nonNull(list(nonNull("String"))), + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }, + requiredBytesValues: { + "type": nonNull(list(nonNull("Byte"))), + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > google-protobuf > 'generates code for an input object wi…' 1`] = ` +"import { Message } from "@testapis/google-protobuf/testapis/primitives/primitives_pb"; +import { inputObjectType, list, nonNull, nullable } from "nexus"; + +export const MessageInput = Object.assign( + inputObjectType({ + "name": "MessageInput", + "definition": (t) => { + t.field("requiredPrimitives", { + "type": nonNull("PrimitivesInput"), + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitives", { + "type": nullable("PrimitivesInput"), + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("requiredPrimitivesList", { + "type": nonNull(list(nonNull("PrimitivesInput"))), + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitivesList", { + "type": nullable(list(nonNull("PrimitivesInput"))), + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["MessageInput"]): Message => { + const output = new Message(); + output.setRequiredPrimitives(PrimitivesInput.toProto(input.requiredPrimitives)); + if (input.optionalPrimitives != null) { + output.setOptionalPrimitives(PrimitivesInput.toProto(input.optionalPrimitives)); + } + output.setRequiredPrimitivesListList(input.requiredPrimitivesList.map((v) => PrimitivesInput.toProto(v))); + if (input.optionalPrimitivesList != null) { + output.setOptionalPrimitivesListList(input.optionalPrimitivesList.map((v) => PrimitivesInput.toProto(v))); + } + return output; + }, + _protoNexus: { + fields: { + requiredPrimitives: { + "type": nonNull("PrimitivesInput"), + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + optionalPrimitives: { + "type": nullable("PrimitivesInput"), + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + requiredPrimitivesList: { + "type": nonNull(list(nonNull("PrimitivesInput"))), + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + optionalPrimitivesList: { + "type": nullable(list(nonNull("PrimitivesInput"))), + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > google-protobuf > 'generates code for an input object wi…' 2`] = ` +"import { OneofParent } from "@testapis/google-protobuf/testapis/oneof/oneof_pb"; +import { inputObjectType, nonNull, nullable } from "nexus"; + +export const OneofParentInput = Object.assign( + inputObjectType({ + "name": "OneofParentInput", + "definition": (t) => { + t.field("normalField", { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }); + t.field("requiredMessage1", { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "required_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }); + t.field("requiredMessage2", { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "required_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }); + t.field("optoinalMessage1", { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "optoinal_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }); + t.field("optoinalMessage2", { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "optoinal_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.oneof.OneofParent", + "name": "OneofParent", + "package": "testapis.oneof", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["OneofParentInput"]): OneofParent => { + const output = new OneofParent(); + output.setNormalField(input.normalField); + if (input.requiredMessage1 != null) { + output.setRequiredMessage1(OneofMemberMessage1Input.toProto(input.requiredMessage1)); + } + if (input.requiredMessage2 != null) { + output.setRequiredMessage2(OneofMemberMessage2Input.toProto(input.requiredMessage2)); + } + if (input.optoinalMessage1 != null) { + output.setOptoinalMessage1(OneofMemberMessage1Input.toProto(input.optoinalMessage1)); + } + if (input.optoinalMessage2 != null) { + output.setOptoinalMessage2(OneofMemberMessage2Input.toProto(input.optoinalMessage2)); + } + return output; + }, + _protoNexus: { + fields: { + normalField: { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }, + requiredMessage1: { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "required_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }, + requiredMessage2: { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "required_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }, + optoinalMessage1: { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "optoinal_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }, + optoinalMessage2: { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "optoinal_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > google-protobuf > 'generates code for empty input object' 1`] = ` +"import { EmptyMessage } from "@testapis/google-protobuf/testapis/empty_types/empty_pb"; +import { inputObjectType } from "nexus"; + +export const EmptyMessageInput = Object.assign( + inputObjectType({ + "name": "EmptyMessageInput", + "definition": (t) => { + t.field("_", { type: "Boolean", description: "noop field" }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.empty_types.EmptyMessage", + "name": "EmptyMessage", + "package": "testapis.empty_types", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["EmptyMessageInput"]): EmptyMessage => { + const output = new EmptyMessage(); + + return output; + }, + _protoNexus: { fields: {} }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > google-protobuf > 'generates code for nested input types' 1`] = ` +"import { ParentMessage } from "@testapis/google-protobuf/testapis/nested/nested_pb"; +import { inputObjectType, nonNull, nullable } from "nexus"; + +export const ParentMessageInput = Object.assign( + inputObjectType({ + "name": "ParentMessageInput", + "definition": (t) => { + t.field("body", { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "body", "typeFullName": "string" } }, + }); + t.field("nested", { + "type": nullable("ParentMessageNestedMessageInput"), + "extensions": { + "protobufField": { "name": "nested", "typeFullName": "testapis.nested.ParentMessage.NestedMessage" }, + }, + }); + t.field("nestedEnum", { + "type": nullable("ParentMessageNestedEnum"), + "extensions": { + "protobufField": { "name": "nested_enum", "typeFullName": "testapis.nested.ParentMessage.NestedEnum" }, + }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.nested.ParentMessage", + "name": "ParentMessage", + "package": "testapis.nested", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["ParentMessageInput"]): ParentMessage => { + const output = new ParentMessage(); + output.setBody(input.body); + if (input.nested != null) { + output.setNested(ParentMessageNestedMessageInput.toProto(input.nested)); + } + if (input.nestedEnum != null) { + output.setNestedEnum(input.nestedEnum); + } + return output; + }, + _protoNexus: { + fields: { + body: { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "body", "typeFullName": "string" } }, + }, + nested: { + "type": nullable("ParentMessageNestedMessageInput"), + "extensions": { + "protobufField": { "name": "nested", "typeFullName": "testapis.nested.ParentMessage.NestedMessage" }, + }, + }, + nestedEnum: { + "type": nullable("ParentMessageNestedEnum"), + "extensions": { + "protobufField": { "name": "nested_enum", "typeFullName": "testapis.nested.ParentMessage.NestedEnum" }, + }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > protobufjs > 'generates code for a simple input obj…' 1`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/primitives"; +import { inputObjectType, list, nonNull } from "nexus"; +import { stringToNumber } from "proto-nexus"; + +export const PrimitivesInput = Object.assign( + inputObjectType({ + "name": "PrimitivesInput", + "definition": (t) => { + t.field("requiredDoubleValue", { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }); + t.field("requiredFloatValue", { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }); + t.field("requiredInt32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Value", { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Value", { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValue", { + "type": nonNull("Boolean"), + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }); + t.field("requiredStringValue", { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }); + t.field("requiredBytesValue", { + "type": nonNull("Byte"), + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }); + t.field("requiredDoubleValues", { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }); + t.field("requiredFloatValues", { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }); + t.field("requiredInt32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValues", { + "type": nonNull(list(nonNull("Boolean"))), + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }); + t.field("requiredStringValues", { + "type": nonNull(list(nonNull("String"))), + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }); + t.field("requiredBytesValues", { + "type": nonNull(list(nonNull("Byte"))), + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["PrimitivesInput"]): testapis.primitives.Primitives => { + const output = new testapis.primitives.Primitives(); + output.requiredDoubleValue = input.requiredDoubleValue; + output.requiredFloatValue = input.requiredFloatValue; + output.requiredInt32Value = input.requiredInt32Value; + output.requiredInt64Value = stringToNumber(input.requiredInt64Value); + output.requiredUint32Value = input.requiredUint32Value; + output.requiredUint64Value = stringToNumber(input.requiredUint64Value); + output.requiredSint32Value = input.requiredSint32Value; + output.requiredSint64Value = stringToNumber(input.requiredSint64Value); + output.requiredFixed32Value = input.requiredFixed32Value; + output.requiredFixed64Value = stringToNumber(input.requiredFixed64Value); + output.requiredSfixed32Value = input.requiredSfixed32Value; + output.requiredSfixed64Value = stringToNumber(input.requiredSfixed64Value); + output.requiredBoolValue = input.requiredBoolValue; + output.requiredStringValue = input.requiredStringValue; + output.requiredBytesValue = input.requiredBytesValue; + output.requiredDoubleValues = input.requiredDoubleValues.map((v) => v); + output.requiredFloatValues = input.requiredFloatValues.map((v) => v); + output.requiredInt32Values = input.requiredInt32Values.map((v) => v); + output.requiredInt64Values = input.requiredInt64Values.map((v) => stringToNumber(v)); + output.requiredUint32Values = input.requiredUint32Values.map((v) => v); + output.requiredUint64Values = input.requiredUint64Values.map((v) => stringToNumber(v)); + output.requiredSint32Values = input.requiredSint32Values.map((v) => v); + output.requiredSint64Values = input.requiredSint64Values.map((v) => stringToNumber(v)); + output.requiredFixed32Values = input.requiredFixed32Values.map((v) => v); + output.requiredFixed64Values = input.requiredFixed64Values.map((v) => stringToNumber(v)); + output.requiredSfixed32Values = input.requiredSfixed32Values.map((v) => v); + output.requiredSfixed64Values = input.requiredSfixed64Values.map((v) => stringToNumber(v)); + output.requiredBoolValues = input.requiredBoolValues.map((v) => v); + output.requiredStringValues = input.requiredStringValues.map((v) => v); + output.requiredBytesValues = input.requiredBytesValues.map((v) => v); + return output; + }, + _protoNexus: { + fields: { + requiredDoubleValue: { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }, + requiredFloatValue: { + "type": nonNull("Float"), + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }, + requiredInt32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }, + requiredInt64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }, + requiredUint32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }, + requiredUint64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }, + requiredSint32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }, + requiredSint64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }, + requiredFixed32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }, + requiredFixed64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }, + requiredSfixed32Value: { + "type": nonNull("Int"), + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }, + requiredSfixed64Value: { + "type": nonNull("Int64"), + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }, + requiredBoolValue: { + "type": nonNull("Boolean"), + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }, + requiredStringValue: { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }, + requiredBytesValue: { + "type": nonNull("Byte"), + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }, + requiredDoubleValues: { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }, + requiredFloatValues: { + "type": nonNull(list(nonNull("Float"))), + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }, + requiredInt32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }, + requiredInt64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }, + requiredUint32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }, + requiredUint64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }, + requiredSint32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }, + requiredSint64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }, + requiredFixed32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }, + requiredFixed64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }, + requiredSfixed32Values: { + "type": nonNull(list(nonNull("Int"))), + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }, + requiredSfixed64Values: { + "type": nonNull(list(nonNull("Int64"))), + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }, + requiredBoolValues: { + "type": nonNull(list(nonNull("Boolean"))), + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }, + requiredStringValues: { + "type": nonNull(list(nonNull("String"))), + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }, + requiredBytesValues: { + "type": nonNull(list(nonNull("Byte"))), + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > protobufjs > 'generates code for an input object wi…' 1`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/primitives"; +import { inputObjectType, list, nonNull, nullable } from "nexus"; + +export const MessageInput = Object.assign( + inputObjectType({ + "name": "MessageInput", + "definition": (t) => { + t.field("requiredPrimitives", { + "type": nonNull("PrimitivesInput"), + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitives", { + "type": nullable("PrimitivesInput"), + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("requiredPrimitivesList", { + "type": nonNull(list(nonNull("PrimitivesInput"))), + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitivesList", { + "type": nullable(list(nonNull("PrimitivesInput"))), + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["MessageInput"]): testapis.primitives.Message => { + const output = new testapis.primitives.Message(); + output.requiredPrimitives = PrimitivesInput.toProto(input.requiredPrimitives); + if (input.optionalPrimitives != null) { + output.optionalPrimitives = PrimitivesInput.toProto(input.optionalPrimitives); + } + output.requiredPrimitivesList = input.requiredPrimitivesList.map((v) => PrimitivesInput.toProto(v)); + if (input.optionalPrimitivesList != null) { + output.optionalPrimitivesList = input.optionalPrimitivesList.map((v) => PrimitivesInput.toProto(v)); + } + return output; + }, + _protoNexus: { + fields: { + requiredPrimitives: { + "type": nonNull("PrimitivesInput"), + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + optionalPrimitives: { + "type": nullable("PrimitivesInput"), + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + requiredPrimitivesList: { + "type": nonNull(list(nonNull("PrimitivesInput"))), + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + optionalPrimitivesList: { + "type": nullable(list(nonNull("PrimitivesInput"))), + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > protobufjs > 'generates code for an input object wi…' 2`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/oneof"; +import { inputObjectType, nonNull, nullable } from "nexus"; + +export const OneofParentInput = Object.assign( + inputObjectType({ + "name": "OneofParentInput", + "definition": (t) => { + t.field("normalField", { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }); + t.field("requiredMessage1", { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "required_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }); + t.field("requiredMessage2", { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "required_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }); + t.field("optoinalMessage1", { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "optoinal_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }); + t.field("optoinalMessage2", { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "optoinal_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.oneof.OneofParent", + "name": "OneofParent", + "package": "testapis.oneof", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["OneofParentInput"]): testapis.oneof.OneofParent => { + const output = new testapis.oneof.OneofParent(); + output.normalField = input.normalField; + if (input.requiredMessage1 != null) { + output.requiredMessage1 = OneofMemberMessage1Input.toProto(input.requiredMessage1); + } + if (input.requiredMessage2 != null) { + output.requiredMessage2 = OneofMemberMessage2Input.toProto(input.requiredMessage2); + } + if (input.optoinalMessage1 != null) { + output.optoinalMessage1 = OneofMemberMessage1Input.toProto(input.optoinalMessage1); + } + if (input.optoinalMessage2 != null) { + output.optoinalMessage2 = OneofMemberMessage2Input.toProto(input.optoinalMessage2); + } + return output; + }, + _protoNexus: { + fields: { + normalField: { + "type": nonNull("String"), + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }, + requiredMessage1: { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "required_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }, + requiredMessage2: { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "required_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }, + optoinalMessage1: { + "type": nullable("OneofMemberMessage1Input"), + "extensions": { + "protobufField": { "name": "optoinal_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }, + optoinalMessage2: { + "type": nullable("OneofMemberMessage2Input"), + "extensions": { + "protobufField": { "name": "optoinal_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }, + }, + }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > protobufjs > 'generates code for empty input object' 1`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/empty_types"; +import { inputObjectType } from "nexus"; + +export const EmptyMessageInput = Object.assign( + inputObjectType({ + "name": "EmptyMessageInput", + "definition": (t) => { + t.field("_", { type: "Boolean", description: "noop field" }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.empty_types.EmptyMessage", + "name": "EmptyMessage", + "package": "testapis.empty_types", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["EmptyMessageInput"]): testapis.empty_types.EmptyMessage => { + const output = new testapis.empty_types.EmptyMessage(); + + return output; + }, + _protoNexus: { fields: {} }, + }, +); +" +`; + +exports[`createInputObjectTypeCode > with partial inputs > 'generates code for partial input types' 1`] = ` +"import { Message } from "@testapis/google-protobuf/testapis/primitives/primitives_pb"; +import { inputObjectType, list, nonNull, nullable } from "nexus"; + +export const MessagePartialInput = Object.assign( + inputObjectType({ + "name": "MessagePartialInput", + "definition": (t) => { + t.field("requiredPrimitives", { + "type": nullable("PrimitivesPartialInput"), + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitives", { + "type": nullable("PrimitivesPartialInput"), + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("requiredPrimitivesList", { + "type": nullable(list(nonNull("PrimitivesPartialInput"))), + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitivesList", { + "type": nullable(list(nonNull("PrimitivesPartialInput"))), + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, + }), + { + toProto: (input: NexusGen["inputTypes"]["MessagePartialInput"]): Message => { + const output = new Message(); + if (input.requiredPrimitives != null) { + output.setRequiredPrimitives(PrimitivesPartialInput.toProto(input.requiredPrimitives)); + } + if (input.optionalPrimitives != null) { + output.setOptionalPrimitives(PrimitivesPartialInput.toProto(input.optionalPrimitives)); + } + if (input.requiredPrimitivesList != null) { + output.setRequiredPrimitivesListList( + input.requiredPrimitivesList.map((v) => PrimitivesPartialInput.toProto(v)), + ); + } + if (input.optionalPrimitivesList != null) { + output.setOptionalPrimitivesListList( + input.optionalPrimitivesList.map((v) => PrimitivesPartialInput.toProto(v)), + ); + } + return output; + }, + _protoNexus: { + fields: { + requiredPrimitives: { + "type": nullable("PrimitivesPartialInput"), + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + optionalPrimitives: { + "type": nullable("PrimitivesPartialInput"), + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + requiredPrimitivesList: { + "type": nullable(list(nonNull("PrimitivesPartialInput"))), + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + optionalPrimitivesList: { + "type": nullable(list(nonNull("PrimitivesPartialInput"))), + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }, + }, + }, + }, +); +" +`; diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/objectType.test.ts.snap b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/objectType.test.ts.snap new file mode 100644 index 00000000..dbfcb752 --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/objectType.test.ts.snap @@ -0,0 +1,1022 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createObjectTypeCode > google-protobuf > 'generates code for a message with nes…' 1`] = ` +"import { Message as Message1 } from "@testapis/google-protobuf/testapis/primitives/primitives_pb"; +import { list, nonNull, nullable, objectType } from "nexus"; + +export type testapis$primitives$Message = Message1; +export const Message = objectType({ + "name": "Message", + "definition": (t) => { + t.field("requiredPrimitives", { + "type": nonNull("Primitives"), + "description": "Required.", + "resolve": (source) => { + const value = source.getRequiredPrimitives(); + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitives", { + "type": nullable("Primitives"), + "description": "Optional.", + "resolve": (source) => { + const value = source.getOptionalPrimitives(); + if (value == null) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("requiredPrimitivesList", { + "type": nonNull(list(nonNull("Primitives"))), + "description": "Required.", + "resolve": (source) => { + return source.getRequiredPrimitivesListList().map((value) => { + return value; + }); + }, + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitivesList", { + "type": nullable(list(nonNull("Primitives"))), + "description": "Optional.", + "resolve": (source) => { + return source.getOptionalPrimitivesListList().map((value) => { + return value; + }); + }, + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + }, + "isTypeOf": (data: unknown) => { + return data instanceof Message1; + }, + "sourceType": { "module": __filename, "export": "testapis$primitives$Message" }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > google-protobuf > 'generates code for a simple message' 1`] = ` +"import { Primitives as Primitives1 } from "@testapis/google-protobuf/testapis/primitives/primitives_pb"; +import { list, nonNull, objectType } from "nexus"; + +export type testapis$primitives$Primitives = Primitives1; +export const Primitives = objectType({ + "name": "Primitives", + "definition": (t) => { + t.field("requiredDoubleValue", { + "type": nonNull("Float"), + "resolve": (source) => { + const value = source.getRequiredDoubleValue(); + return value; + }, + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }); + t.field("requiredFloatValue", { + "type": nonNull("Float"), + "resolve": (source) => { + const value = source.getRequiredFloatValue(); + return value; + }, + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }); + t.field("requiredInt32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.getRequiredInt32Value(); + return value; + }, + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.getRequiredInt64Value(); + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.getRequiredUint32Value(); + return value; + }, + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.getRequiredUint64Value(); + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.getRequiredSint32Value(); + return value; + }, + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.getRequiredSint64Value(); + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.getRequiredFixed32Value(); + return value; + }, + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.getRequiredFixed64Value(); + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.getRequiredSfixed32Value(); + return value; + }, + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.getRequiredSfixed64Value(); + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValue", { + "type": nonNull("Boolean"), + "resolve": (source) => { + const value = source.getRequiredBoolValue(); + return value; + }, + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }); + t.field("requiredStringValue", { + "type": nonNull("String"), + "resolve": (source) => { + const value = source.getRequiredStringValue(); + return value; + }, + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }); + t.field("requiredBytesValue", { + "type": nonNull("Byte"), + "resolve": (source) => { + const value = source.getRequiredBytesValue(); + return value; + }, + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }); + t.field("requiredDoubleValues", { + "type": nonNull(list(nonNull("Float"))), + "resolve": (source) => { + return source.getRequiredDoubleValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }); + t.field("requiredFloatValues", { + "type": nonNull(list(nonNull("Float"))), + "resolve": (source) => { + return source.getRequiredFloatValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }); + t.field("requiredInt32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.getRequiredInt32ValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.getRequiredInt64ValuesList().map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.getRequiredUint32ValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.getRequiredUint64ValuesList().map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.getRequiredSint32ValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.getRequiredSint64ValuesList().map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.getRequiredFixed32ValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.getRequiredFixed64ValuesList().map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.getRequiredSfixed32ValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.getRequiredSfixed64ValuesList().map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValues", { + "type": nonNull(list(nonNull("Boolean"))), + "resolve": (source) => { + return source.getRequiredBoolValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }); + t.field("requiredStringValues", { + "type": nonNull(list(nonNull("String"))), + "resolve": (source) => { + return source.getRequiredStringValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }); + t.field("requiredBytesValues", { + "type": nonNull(list(nonNull("Byte"))), + "resolve": (source) => { + return source.getRequiredBytesValuesList().map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }); + }, + "isTypeOf": (data: unknown) => { + return data instanceof Primitives1; + }, + "sourceType": { "module": __filename, "export": "testapis$primitives$Primitives" }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > protobufjs > 'generates code for a message with nes…' 1`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/primitives"; +import { list, nonNull, nullable, objectType } from "nexus"; + +export type testapis$primitives$Message = testapis.primitives.Message; +export const Message = objectType({ + "name": "Message", + "definition": (t) => { + t.field("requiredPrimitives", { + "type": nonNull("Primitives"), + "description": "Required.", + "resolve": (source) => { + const value = source.requiredPrimitives; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitives", { + "type": nullable("Primitives"), + "description": "Optional.", + "resolve": (source) => { + const value = source.optionalPrimitives; + if (value == null) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("requiredPrimitivesList", { + "type": nonNull(list(nonNull("Primitives"))), + "description": "Required.", + "resolve": (source) => { + return source.requiredPrimitivesList.map((value) => { + return value; + }); + }, + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + t.field("optionalPrimitivesList", { + "type": nullable(list(nonNull("Primitives"))), + "description": "Optional.", + "resolve": (source) => { + return source.optionalPrimitivesList.map((value) => { + return value; + }); + }, + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }); + }, + "isTypeOf": (data: unknown) => { + return data instanceof testapis.primitives.Message; + }, + "sourceType": { "module": __filename, "export": "testapis$primitives$Message" }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > protobufjs > 'generates code for a message with one…' 1`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/oneof"; +import { nonNull, nullable, objectType } from "nexus"; + +export type testapis$oneof$OneofParent = testapis.oneof.OneofParent; +export const OneofParent = objectType({ + "name": "OneofParent", + "definition": (t) => { + t.field("normalField", { + "type": nonNull("String"), + "resolve": (source) => { + const value = source.normalField; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }); + t.field("requiredOneofMembers", { + "type": nonNull("OneofParentRequiredOneofMembers"), + "description": "Required. disallow not_set.", + "resolve": (source) => { + const value = source; + if (value.requiredMessage1 != null) { + return value.requiredMessage1; + } + if (value.requiredMessage2 != null) { + return value.requiredMessage2; + } + throw new Error("One of the following fields must be non-null: required_message1, required_message2"); + }, + "extensions": { "protobufField": { "name": "required_oneof_members" } }, + }); + t.field("optionalOneofMembers", { + "type": nullable("OneofParentOptionalOneofMembers"), + "resolve": (source) => { + const value = source; + if (value.optoinalMessage1 != null) { + return value.optoinalMessage1; + } + if (value.optoinalMessage2 != null) { + return value.optoinalMessage2; + } + return null; + }, + "extensions": { "protobufField": { "name": "optional_oneof_members" } }, + }); + }, + "isTypeOf": (data: unknown) => { + return data instanceof testapis.oneof.OneofParent; + }, + "sourceType": { "module": __filename, "export": "testapis$oneof$OneofParent" }, + "extensions": { + "protobufMessage": { "fullName": "testapis.oneof.OneofParent", "name": "OneofParent", "package": "testapis.oneof" }, + }, +}); +" +`; + +exports[`createObjectTypeCode > protobufjs > 'generates code for a simple message' 1`] = ` +"import { testapis } from "@testapis/protobufjs/testapis/primitives"; +import { list, nonNull, objectType } from "nexus"; + +export type testapis$primitives$Primitives = testapis.primitives.Primitives; +export const Primitives = objectType({ + "name": "Primitives", + "definition": (t) => { + t.field("requiredDoubleValue", { + "type": nonNull("Float"), + "resolve": (source) => { + const value = source.requiredDoubleValue; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }); + t.field("requiredFloatValue", { + "type": nonNull("Float"), + "resolve": (source) => { + const value = source.requiredFloatValue; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }); + t.field("requiredInt32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.requiredInt32Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.requiredInt64Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.requiredUint32Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.requiredUint64Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.requiredSint32Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.requiredSint64Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.requiredFixed32Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.requiredFixed64Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Value", { + "type": nonNull("Int"), + "resolve": (source) => { + const value = source.requiredSfixed32Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Value", { + "type": nonNull("Int64"), + "resolve": (source) => { + const value = source.requiredSfixed64Value; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value.toString(); + }, + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValue", { + "type": nonNull("Boolean"), + "resolve": (source) => { + const value = source.requiredBoolValue; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }); + t.field("requiredStringValue", { + "type": nonNull("String"), + "resolve": (source) => { + const value = source.requiredStringValue; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }); + t.field("requiredBytesValue", { + "type": nonNull("Byte"), + "resolve": (source) => { + const value = source.requiredBytesValue; + if (value == null) { + throw new Error("Cannot return null for non-nullable field"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }); + t.field("requiredDoubleValues", { + "type": nonNull(list(nonNull("Float"))), + "resolve": (source) => { + return source.requiredDoubleValues.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }); + t.field("requiredFloatValues", { + "type": nonNull(list(nonNull("Float"))), + "resolve": (source) => { + return source.requiredFloatValues.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }); + t.field("requiredInt32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.requiredInt32Values.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }); + t.field("requiredInt64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.requiredInt64Values.map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }); + t.field("requiredUint32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.requiredUint32Values.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }); + t.field("requiredUint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.requiredUint64Values.map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }); + t.field("requiredSint32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.requiredSint32Values.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }); + t.field("requiredSint64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.requiredSint64Values.map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }); + t.field("requiredFixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.requiredFixed32Values.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }); + t.field("requiredFixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.requiredFixed64Values.map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }); + t.field("requiredSfixed32Values", { + "type": nonNull(list(nonNull("Int"))), + "resolve": (source) => { + return source.requiredSfixed32Values.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }); + t.field("requiredSfixed64Values", { + "type": nonNull(list(nonNull("Int64"))), + "resolve": (source) => { + return source.requiredSfixed64Values.map((value) => { + return value.toString(); + }); + }, + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }); + t.field("requiredBoolValues", { + "type": nonNull(list(nonNull("Boolean"))), + "resolve": (source) => { + return source.requiredBoolValues.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }); + t.field("requiredStringValues", { + "type": nonNull(list(nonNull("String"))), + "resolve": (source) => { + return source.requiredStringValues.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }); + t.field("requiredBytesValues", { + "type": nonNull(list(nonNull("Byte"))), + "resolve": (source) => { + return source.requiredBytesValues.map((value) => { + return value; + }); + }, + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }); + }, + "isTypeOf": (data: unknown) => { + return data instanceof testapis.primitives.Primitives; + }, + "sourceType": { "module": __filename, "export": "testapis$primitives$Primitives" }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > with extensions > 'generates code for message with field…' 1`] = ` +"import { + EnumWillRename, + PrefixedEnum, + PrefixedMessage, +} from "@testapis/google-protobuf/testapis/extensions/extensions_pb"; +import { list, nonNull, nullable, objectType } from "nexus"; + +export type testapis$extensions$PrefixedMessage = PrefixedMessage; +export const TestPrefixPrefixedMessage = objectType({ + "name": "TestPrefixPrefixedMessage", + "definition": (t) => { + t.field("id", { + "type": nonNull("Int64"), + "description": "Output only.", + "resolve": (source) => { + const value = source.getId(); + return value.toString(); + }, + "extensions": { "protobufField": { "name": "id", "typeFullName": "uint64" } }, + }); + t.field("body", { + "type": nonNull("String"), + "resolve": (source) => { + const value = source.getBody(); + return value; + }, + "extensions": { "protobufField": { "name": "body", "typeFullName": "string" } }, + }); + t.field("prefixedEnum", { + "type": nullable("TestPrefixPrefixedEnum"), + "resolve": (source) => { + const value = source.getPrefixedEnum(); + if (value == null) { + return null; + } + if (value === PrefixedEnum.PREFIXED_ENUM_UNSPECIFIED) { + return null; + } + if (value === PrefixedEnum.PREFIXED_IGNORED) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { "name": "prefixed_enum", "typeFullName": "testapis.extensions.PrefixedEnum" }, + }, + }); + t.field("notIgnoredMessage", { + "type": nullable("TestPrefixIgnoredMessageNotIgnored"), + "resolve": (source) => { + const value = source.getNotIgnoredMessage(); + if (value == null) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { + "name": "not_ignored_message", + "typeFullName": "testapis.extensions.IgnoredMessage.NotIgnored", + }, + }, + }); + t.field("squashedMessage", { + "type": nullable("TestPrefixPrefixedMessageSquashedMessage"), + "resolve": (source) => { + const value = source.getSquashedMessage(); + if (value == null) { + return null; + } + switch (value.getSquashedMessageCase()) { + case PrefixedMessage.SquashedMessage.SquashedMessageCase.ONEOF_FIELD: { + return value.getOneofField()!; + } + + case PrefixedMessage.SquashedMessage.SquashedMessageCase.ONEOF_FIELD_2: { + return value.getOneofField2()!; + } + + default: { + return null; + } + } + }, + "extensions": { + "protobufField": { + "name": "squashed_message", + "typeFullName": "testapis.extensions.PrefixedMessage.SquashedMessage", + }, + }, + }); + t.field("thisFieldWasRenamed", { + "type": nonNull("String"), + "resolve": (source) => { + const value = source.getThisFieldWillBeRenamed(); + return value; + }, + "extensions": { + "protobufField": { + "name": "this_field_will_be_renamed", + "typeFullName": "string", + "options": { "[graphql.field]": { "name": "thisFieldWasRenamed" } }, + }, + }, + }); + t.field("skipResolver", { + "type": nonNull("String"), + "resolve": (source) => { + throw new Error("not implemented"); + }, + "extensions": { + "protobufField": { + "name": "skip_resolver", + "typeFullName": "string", + "options": { "[graphql.field]": { "skipResolver": true } }, + }, + }, + }); + t.field("squashedMessages", { + "type": nullable(list(nonNull("TestPrefixPrefixedMessageSquashedMessage"))), + "resolve": (source) => { + return source.getSquashedMessagesList().map((value) => { + switch (value.getSquashedMessageCase()) { + case PrefixedMessage.SquashedMessage.SquashedMessageCase.ONEOF_FIELD: { + return value.getOneofField()!; + } + + case PrefixedMessage.SquashedMessage.SquashedMessageCase.ONEOF_FIELD_2: { + return value.getOneofField2()!; + } + + default: { + throw new Error("One of the following fields must be non-null: oneof_field, oneof_field_2"); + } + } + }); + }, + "extensions": { + "protobufField": { + "name": "squashed_messages", + "typeFullName": "testapis.extensions.PrefixedMessage.SquashedMessage", + }, + }, + }); + t.field("renamedMessage", { + "type": nullable("TestPrefixRenamedMessage"), + "resolve": (source) => { + const value = source.getRenamedMessage(); + if (value == null) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { "name": "renamed_message", "typeFullName": "testapis.extensions.MessageWillRename" }, + }, + }); + t.field("renamedEnum", { + "type": nullable("TestPrefixRenamedEnum"), + "resolve": (source) => { + const value = source.getRenamedEnum(); + if (value == null) { + return null; + } + if (value === EnumWillRename.ENUM_WILL_RENAME_UNSPECIFIED) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { "name": "renamed_enum", "typeFullName": "testapis.extensions.EnumWillRename" }, + }, + }); + t.field("partialIgnoreOneof", { + "type": nullable("TestPrefixPrefixedMessagePartialIgnoreOneof"), + "resolve": (source) => { + const value = source; + switch (value.getPartialIgnoreOneofCase()) { + case PrefixedMessage.PartialIgnoreOneofCase.ONEOF_NOT_IGNORED_FIELD: { + return value.getOneofNotIgnoredField()!; + } + + default: { + return null; + } + } + }, + "extensions": { "protobufField": { "name": "partial_ignore_oneof" } }, + }); + }, + "isTypeOf": (data: unknown) => { + return data instanceof PrefixedMessage; + }, + "sourceType": { "module": __filename, "export": "testapis$extensions$PrefixedMessage" }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.extensions.PrefixedMessage", + "name": "PrefixedMessage", + "package": "testapis.extensions", + }, + }, +}); +" +`; diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/oneofUnionType.test.ts.snap b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/oneofUnionType.test.ts.snap new file mode 100644 index 00000000..b8f1b63e --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/__snapshots__/oneofUnionType.test.ts.snap @@ -0,0 +1,147 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createOneofUnionTypeCode > google-protobuf > 'generates code for a simple oneof uni…' 1`] = ` +"import { unionType } from "nexus"; + +export const OneofParentRequiredOneofMembers = unionType({ + "name": "OneofParentRequiredOneofMembers", + "description": "Required. disallow not_set.", + "definition": (t) => { + t.members(OneofMemberMessage1, OneofMemberMessage2); + }, + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.required_oneof_members", + "name": "required_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "required_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "required_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > google-protobuf > 'generates code for import squashed un…' 1`] = ` +"import { unionType } from "nexus"; + +export const SquashedOneof = unionType({ + "name": "SquashedOneof", + "definition": (t) => { + t.members(OneofMessage1); + }, + "extensions": { + "protobufOneof": { + "fullName": "testapis.edgecases.import_squashed_union.pkg1.SquashedOneof", + "name": "SquashedOneof", + "package": "testapis.edgecases.import_squashed_union.pkg1", + "fields": [{ + "name": "msg1", + "type": "testapis.edgecases.import_squashed_union.pkg1.OneofMessage1", + "options": { "[graphql.object_type]": { "squashUnion": true } }, + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > google-protobuf > 'generates code for optional oneof uni…' 1`] = ` +"import { unionType } from "nexus"; + +export const OneofParentOptionalOneofMembers = unionType({ + "name": "OneofParentOptionalOneofMembers", + "definition": (t) => { + t.members(OneofMemberMessage1, OneofMemberMessage2); + }, + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.optional_oneof_members", + "name": "optional_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "optoinal_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "optoinal_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > protobufjs > 'generates code for a simple oneof uni…' 1`] = ` +"import { unionType } from "nexus"; + +export const OneofParentRequiredOneofMembers = unionType({ + "name": "OneofParentRequiredOneofMembers", + "description": "Required. disallow not_set.", + "definition": (t) => { + t.members(OneofMemberMessage1, OneofMemberMessage2); + }, + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.required_oneof_members", + "name": "required_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "required_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "required_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > protobufjs > 'generates code for import squashed un…' 1`] = ` +"import { unionType } from "nexus"; + +export const SquashedOneof = unionType({ + "name": "SquashedOneof", + "definition": (t) => { + t.members(OneofMessage1); + }, + "extensions": { + "protobufOneof": { + "fullName": "testapis.edgecases.import_squashed_union.pkg1.SquashedOneof", + "name": "SquashedOneof", + "package": "testapis.edgecases.import_squashed_union.pkg1", + "fields": [{ + "name": "msg1", + "type": "testapis.edgecases.import_squashed_union.pkg1.OneofMessage1", + "options": { "[graphql.object_type]": { "squashUnion": true } }, + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > protobufjs > 'generates code for optional oneof uni…' 1`] = ` +"import { unionType } from "nexus"; + +export const OneofParentOptionalOneofMembers = unionType({ + "name": "OneofParentOptionalOneofMembers", + "definition": (t) => { + t.members(OneofMemberMessage1, OneofMemberMessage2); + }, + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.optional_oneof_members", + "name": "optional_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "optoinal_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "optoinal_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/enumType.test.ts b/packages/protoc-gen-nexus/src/dslgen/printers/enumType.test.ts new file mode 100644 index 00000000..c0b1bd48 --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/enumType.test.ts @@ -0,0 +1,136 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + EnumType, + type TypeOptions, + defaultScalarMapping, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createEnumTypeCode } from "./enumType.js"; + +function generateEnumTypeCode( + packageName: TestapisPackage, + enumTypeNameInProto: string, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + + // The actual proto package might differ from the TestapisPackage key + // For example: "testapis.enums" key but "testapi.enums" proto package + let descEnum = registry.getEnum(`${packageName}.${enumTypeNameInProto}`); + + if (descEnum === undefined && packageName === "testapis.enums") { + // Try with the actual proto package name + descEnum = registry.getEnum(`testapi.enums.${enumTypeNameInProto}`); + } + + if (descEnum === undefined) { + throw new Error( + `Enum ${enumTypeNameInProto} not found in package ${packageName}`, + ); + } + + const enumType = new EnumType(descEnum, typeOptions); + + const code = createEnumTypeCode(enumType, registry); + + return code.toString(); +} + +type TestCase = { + test: string; + args: { + packageName: TestapisPackage; + enumTypeNameInProto: string; + }; +}; + +type TestSuite = { + suite: string; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "google-protobuf", + cases: [ + { + test: "generates code for a simple enum", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnum", + }, + }, + { + test: "generates code for an enum without unspecified", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnumWithoutUnspecified", + }, + }, + { + test: "generates code for nested enum", + args: { + packageName: "testapis.nested", + enumTypeNameInProto: "ParentMessage.NestedEnum", + }, + }, + { + test: "generates code for enum with extensions", + args: { + packageName: "testapis.extensions", + enumTypeNameInProto: "PrefixedEnum", + }, + }, + ], + }, + { + suite: "protobufjs", + cases: [ + { + test: "generates code for a simple enum", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnum", + }, + }, + { + test: "generates code for an enum without unspecified", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnumWithoutUnspecified", + }, + }, + { + test: "generates code for nested enum", + args: { + packageName: "testapis.nested", + enumTypeNameInProto: "ParentMessage.NestedEnum", + }, + }, + ], + }, +]; + +describe("createEnumTypeCode", () => { + for (const { suite, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + const code = generateEnumTypeCode( + args.packageName, + args.enumTypeNameInProto, + ); + expect(code).toMatchSnapshot(); + }); + }); + } +}); diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/inputObjectType.test.ts b/packages/protoc-gen-nexus/src/dslgen/printers/inputObjectType.test.ts new file mode 100644 index 00000000..ead080d1 --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/inputObjectType.test.ts @@ -0,0 +1,189 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + InputObjectType, + type TypeOptions, + defaultScalarMapping, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createInputObjectTypeCode } from "./inputObjectType.js"; +import type { NexusPrinterOptions } from "./util.js"; + +function generateInputObjectTypeCode( + packageName: TestapisPackage, + typeNameInProto: string, + options: NexusPrinterOptions, + partialInputs = false, +): string { + const typeOptions: TypeOptions = { + partialInputs, + scalarMapping: defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${typeNameInProto}`); + if (descMsg === undefined) { + throw new Error( + `Message ${typeNameInProto} not found in package ${packageName}`, + ); + } + + const inputType = new InputObjectType(descMsg, typeOptions); + + const code = createInputObjectTypeCode( + partialInputs ? inputType.toPartialInput() : inputType, + registry, + options, + ); + + return code.toString(); +} + +type TestCase = { + test: string; + args: { + packageName: TestapisPackage; + typeNameInProto: string; + partialInputs?: boolean; + }; +}; + +type TestSuite = { + suite: string; + options: NexusPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "google-protobuf", + options: { + dsl: "nexus", + protobuf: "google-protobuf" as const, + importPrefix: "@testapis/google-protobuf", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for a simple input object", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Primitives", + }, + }, + { + test: "generates code for an input object with nested fields", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Message", + }, + }, + { + test: "generates code for an input object with oneof fields", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + }, + }, + { + test: "generates code for empty input object", + args: { + packageName: "testapis.empty_types", + typeNameInProto: "EmptyMessage", + }, + }, + { + test: "generates code for nested input types", + args: { + packageName: "testapis.nested", + typeNameInProto: "ParentMessage", + }, + }, + ], + }, + { + suite: "protobufjs", + options: { + dsl: "nexus", + protobuf: "protobufjs" as const, + importPrefix: "@testapis/protobufjs", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for a simple input object", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Primitives", + }, + }, + { + test: "generates code for an input object with nested fields", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Message", + }, + }, + { + test: "generates code for an input object with oneof fields", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + }, + }, + { + test: "generates code for empty input object", + args: { + packageName: "testapis.empty_types", + typeNameInProto: "EmptyMessage", + }, + }, + ], + }, + { + suite: "with partial inputs", + options: { + dsl: "nexus", + protobuf: "google-protobuf" as const, + importPrefix: "@testapis/google-protobuf", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for partial input types", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Message", + partialInputs: true, + }, + }, + ], + }, +]; + +describe("createInputObjectTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + const code = generateInputObjectTypeCode( + args.packageName, + args.typeNameInProto, + options, + args.partialInputs ?? false, + ); + expect(code).toMatchSnapshot(); + }); + }); + } +}); diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/objectType.test.ts b/packages/protoc-gen-nexus/src/dslgen/printers/objectType.test.ts new file mode 100644 index 00000000..3c8bfb45 --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/objectType.test.ts @@ -0,0 +1,153 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + ObjectType, + type TypeOptions, + defaultScalarMapping, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createObjectTypeCode } from "./objectType.js"; +import type { NexusPrinterOptions } from "./util.js"; + +function generateObjectTypeCode( + packageName: TestapisPackage, + messageTypeName: string, + options: NexusPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${messageTypeName}`); + if (descMsg === undefined) { + throw new Error( + `Message ${messageTypeName} not found in package ${packageName}`, + ); + } + + const objType = new ObjectType(descMsg, typeOptions); + + const code = createObjectTypeCode(objType, registry, options); + + return code.toString(); +} + +type TestCase = { + test: string; + args: { + packageName: TestapisPackage; + messageTypeName: string; + }; +}; + +type TestSuite = { + suite: string; + options: NexusPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "google-protobuf", + options: { + dsl: "nexus", + protobuf: "google-protobuf" as const, + importPrefix: "@testapis/google-protobuf", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for a simple message", + args: { + packageName: "testapis.primitives", + messageTypeName: "Primitives", + }, + }, + { + test: "generates code for a message with nested fields", + args: { + packageName: "testapis.primitives", + messageTypeName: "Message", + }, + }, + ], + }, + { + suite: "protobufjs", + options: { + dsl: "nexus", + protobuf: "protobufjs" as const, + importPrefix: "@testapis/protobufjs", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for a simple message", + args: { + packageName: "testapis.primitives", + messageTypeName: "Primitives", + }, + }, + { + test: "generates code for a message with nested fields", + args: { + packageName: "testapis.primitives", + messageTypeName: "Message", + }, + }, + { + test: "generates code for a message with oneofs", + args: { + packageName: "testapis.oneof", + messageTypeName: "OneofParent", + }, + }, + ], + }, + { + suite: "with extensions", + options: { + dsl: "nexus", + protobuf: "google-protobuf" as const, + importPrefix: "@testapis/google-protobuf", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for message with field extensions", + args: { + packageName: "testapis.extensions", + messageTypeName: "PrefixedMessage", + }, + }, + ], + }, +]; + +describe("createObjectTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + const code = generateObjectTypeCode( + args.packageName, + args.messageTypeName, + options, + ); + expect(code).toMatchSnapshot(); + }); + }); + } +}); diff --git a/packages/protoc-gen-nexus/src/dslgen/printers/oneofUnionType.test.ts b/packages/protoc-gen-nexus/src/dslgen/printers/oneofUnionType.test.ts new file mode 100644 index 00000000..dc43c16f --- /dev/null +++ b/packages/protoc-gen-nexus/src/dslgen/printers/oneofUnionType.test.ts @@ -0,0 +1,209 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + OneofUnionType, + SquashedOneofUnionType, + type TypeOptions, + defaultScalarMapping, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createOneofUnionTypeCode } from "./oneofUnionType.js"; +import type { NexusPrinterOptions } from "./util.js"; + +function generateOneofUnionTypeCode( + packageName: TestapisPackage, + typeNameInProto: string, + oneofFieldName: string, + options: NexusPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${typeNameInProto}`); + if (descMsg === undefined) { + throw new Error( + `Message ${typeNameInProto} not found in package ${packageName}`, + ); + } + + const descOneof = descMsg.oneofs.find((d) => d.name === oneofFieldName); + if (descOneof === undefined) { + throw new Error( + `Oneof field ${oneofFieldName} not found in message ${typeNameInProto} in package ${packageName}`, + ); + } + + const oneofType = new OneofUnionType(descOneof, typeOptions); + + const code = createOneofUnionTypeCode( + oneofType, + registry, + options, + ).toString(); + + return code.toString(); +} + +function generateSquashedOneofUnionTypeCode( + packageName: TestapisPackage, + typeNameInProto: string, + options: NexusPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${typeNameInProto}`); + if (descMsg === undefined) { + throw new Error( + `Message ${typeNameInProto} not found in package ${packageName}`, + ); + } + + const oneofType = new SquashedOneofUnionType(descMsg, typeOptions); + + const code = createOneofUnionTypeCode( + oneofType, + registry, + options, + ).toString(); + + return code.toString(); +} + +type OneofTestCase = { + test: string; + args: { + packageName: TestapisPackage; + typeNameInProto: string; + oneofFieldName: string; + }; +}; + +type SquashedTestCase = { + test: string; + args: { + packageName: TestapisPackage; + typeNameInProto: string; + }; +}; + +type TestCase = OneofTestCase | SquashedTestCase; + +type TestSuite = { + suite: string; + options: NexusPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "google-protobuf", + options: { + dsl: "nexus", + protobuf: "google-protobuf" as const, + importPrefix: "@testapis/google-protobuf", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for a simple oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "required_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for optional oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "optional_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for import squashed union", + args: { + packageName: "testapis.edgecases.import_squashed_union.pkg1", + typeNameInProto: "SquashedOneof", + }, + } as SquashedTestCase, + ], + }, + { + suite: "protobufjs", + options: { + dsl: "nexus", + protobuf: "protobufjs" as const, + importPrefix: "@testapis/protobufjs", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".nexus", + }, + cases: [ + { + test: "generates code for a simple oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "required_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for optional oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "optional_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for import squashed union", + args: { + packageName: "testapis.edgecases.import_squashed_union.pkg1", + typeNameInProto: "SquashedOneof", + }, + } as SquashedTestCase, + ], + }, +]; + +describe("createOneofUnionTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + if ("oneofFieldName" in args) { + const code = generateOneofUnionTypeCode( + args.packageName, + args.typeNameInProto, + args.oneofFieldName, + options, + ); + expect(code).toMatchSnapshot(); + } else { + const code = generateSquashedOneofUnionTypeCode( + args.packageName, + args.typeNameInProto, + options, + ); + expect(code).toMatchSnapshot(); + } + }); + }); + } +}); diff --git a/packages/protoc-gen-pothos/package.json b/packages/protoc-gen-pothos/package.json index c4598f93..f393653a 100644 --- a/packages/protoc-gen-pothos/package.json +++ b/packages/protoc-gen-pothos/package.json @@ -2,13 +2,7 @@ "name": "protoc-gen-pothos", "version": "0.6.2", "description": "Generate DSL for Pothos GraphQL from Protocol Buffers IDL", - "keywords": [ - "graphql", - "grpc", - "pothos", - "protobuf", - "typescript" - ], + "keywords": ["graphql", "grpc", "pothos", "protobuf", "typescript"], "bin": { "protoc-gen-pothos": "./bin/protoc-gen-pothos.cjs" }, @@ -31,13 +25,7 @@ } } }, - "files": [ - "bin/", - "src/", - "dist/", - "!src/**/*.test.ts", - "!src/**/__tests__/" - ], + "files": ["bin/", "src/", "dist/", "!src/**/*.test.ts", "!src/**/__tests__/"], "sideEffects": false, "private": false, "publishConfig": { diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/enumType.test.ts.snap b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/enumType.test.ts.snap new file mode 100644 index 00000000..6ce346ba --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/enumType.test.ts.snap @@ -0,0 +1,159 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createEnumTypeCode > protobuf-es > 'generates code for a simple enum' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { MyEnum } from "@testapis/protobuf-es/testapis/enums/enums_pb"; +import { builder } from "../../../../builder"; + +export const MyEnum$Ref: EnumRef = builder.enumType("MyEnum", { + "values": { + FOO: { "value": 1, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_FOO" } } }, + BAR: { + "description": "This is Bar.", + "value": 2, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAR" } }, + }, + BAZ: { "value": 3, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAZ" } } }, + } as const, + "extensions": { + "protobufEnum": { "name": "MyEnum", "fullName": "testapi.enums.MyEnum", "package": "testapi.enums" }, + }, +}); +" +`; + +exports[`createEnumTypeCode > protobuf-es > 'generates code for an enum without un…' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { MyEnumWithoutUnspecified } from "@testapis/protobuf-es/testapis/enums/enums_pb"; +import { builder } from "../../../../builder"; + +export const MyEnumWithoutUnspecified$Ref: EnumRef = builder + .enumType("MyEnumWithoutUnspecified", { + "values": { + FOO: { "value": 0, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_FOO" } } }, + BAR: { "value": 1, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAR" } } }, + BAZ: { "value": 2, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAZ" } } }, + } as const, + "extensions": { + "protobufEnum": { + "name": "MyEnumWithoutUnspecified", + "fullName": "testapi.enums.MyEnumWithoutUnspecified", + "package": "testapi.enums", + }, + }, + }); +" +`; + +exports[`createEnumTypeCode > protobuf-es > 'generates code for nested enum' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { ParentMessage_NestedEnum } from "@testapis/protobuf-es/testapis/nested/nested_pb"; +import { builder } from "../../../../builder"; + +export const ParentMessageNestedEnum$Ref: EnumRef = builder + .enumType("ParentMessageNestedEnum", { + "values": { + FOO: { "value": 1, "extensions": { "protobufEnumValue": { "name": "FOO" } } }, + BAR: { "value": 2, "extensions": { "protobufEnumValue": { "name": "BAR" } } }, + } as const, + "extensions": { + "protobufEnum": { + "name": "NestedEnum", + "fullName": "testapis.nested.ParentMessage.NestedEnum", + "package": "testapis.nested", + }, + }, + }); +" +`; + +exports[`createEnumTypeCode > ts-proto > 'generates code for a simple enum' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { MyEnum } from "@testapis/ts-proto/testapis/enums/enums"; +import { builder } from "../../../../builder"; + +export const MyEnum$Ref: EnumRef = builder.enumType("MyEnum", { + "values": { + FOO: { "value": 1, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_FOO" } } }, + BAR: { + "description": "This is Bar.", + "value": 2, + "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAR" } }, + }, + BAZ: { "value": 3, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_BAZ" } } }, + } as const, + "extensions": { + "protobufEnum": { "name": "MyEnum", "fullName": "testapi.enums.MyEnum", "package": "testapi.enums" }, + }, +}); +" +`; + +exports[`createEnumTypeCode > ts-proto > 'generates code for an enum without un…' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { MyEnumWithoutUnspecified } from "@testapis/ts-proto/testapis/enums/enums"; +import { builder } from "../../../../builder"; + +export const MyEnumWithoutUnspecified$Ref: EnumRef = builder + .enumType("MyEnumWithoutUnspecified", { + "values": { + FOO: { "value": 0, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_FOO" } } }, + BAR: { "value": 1, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAR" } } }, + BAZ: { "value": 2, "extensions": { "protobufEnumValue": { "name": "MY_ENUM_WITHOUT_UNSPECIFIED_BAZ" } } }, + } as const, + "extensions": { + "protobufEnum": { + "name": "MyEnumWithoutUnspecified", + "fullName": "testapi.enums.MyEnumWithoutUnspecified", + "package": "testapi.enums", + }, + }, + }); +" +`; + +exports[`createEnumTypeCode > ts-proto > 'generates code for enum with extensio…' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { PrefixedEnum } from "@testapis/ts-proto/testapis/extensions/extensions"; +import { builder } from "../../../../builder"; + +export const TestPrefixPrefixedEnum$Ref: EnumRef = builder.enumType( + "TestPrefixPrefixedEnum", + { + "values": { + PREFIXED_FOO: { "value": 1, "extensions": { "protobufEnumValue": { "name": "PREFIXED_FOO" } } }, + PREFIXED_BAR: { "value": 2, "extensions": { "protobufEnumValue": { "name": "PREFIXED_BAR" } } }, + } as const, + "extensions": { + "protobufEnum": { + "name": "PrefixedEnum", + "fullName": "testapis.extensions.PrefixedEnum", + "package": "testapis.extensions", + }, + }, + }, +); +" +`; + +exports[`createEnumTypeCode > ts-proto > 'generates code for nested enum' 1`] = ` +"import { EnumRef } from "@pothos/core"; +import { ParentMessage_NestedEnum } from "@testapis/ts-proto/testapis/nested/nested"; +import { builder } from "../../../../builder"; + +export const ParentMessageNestedEnum$Ref: EnumRef = builder + .enumType("ParentMessageNestedEnum", { + "values": { + FOO: { "value": 1, "extensions": { "protobufEnumValue": { "name": "FOO" } } }, + BAR: { "value": 2, "extensions": { "protobufEnumValue": { "name": "BAR" } } }, + } as const, + "extensions": { + "protobufEnum": { + "name": "NestedEnum", + "fullName": "testapis.nested.ParentMessage.NestedEnum", + "package": "testapis.nested", + }, + }, + }); +" +`; diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/inputObjectType.test.ts.snap b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/inputObjectType.test.ts.snap new file mode 100644 index 00000000..eb8fadbf --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/inputObjectType.test.ts.snap @@ -0,0 +1,854 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createInputObjectTypeCode > protobuf-es > 'generates code for a simple input obj…' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { Primitives } from "@testapis/protobuf-es/testapis/primitives/primitives_pb"; +import { builder } from "../../../../builder"; + +export type PrimitivesInput$Shape = { + requiredDoubleValue: Primitives["requiredDoubleValue"]; + requiredFloatValue: Primitives["requiredFloatValue"]; + requiredInt32Value: Primitives["requiredInt32Value"]; + requiredInt64Value: Primitives["requiredInt64Value"]; + requiredUint32Value: Primitives["requiredUint32Value"]; + requiredUint64Value: Primitives["requiredUint64Value"]; + requiredSint32Value: Primitives["requiredSint32Value"]; + requiredSint64Value: Primitives["requiredSint64Value"]; + requiredFixed32Value: Primitives["requiredFixed32Value"]; + requiredFixed64Value: Primitives["requiredFixed64Value"]; + requiredSfixed32Value: Primitives["requiredSfixed32Value"]; + requiredSfixed64Value: Primitives["requiredSfixed64Value"]; + requiredBoolValue: Primitives["requiredBoolValue"]; + requiredStringValue: Primitives["requiredStringValue"]; + requiredBytesValue: Primitives["requiredBytesValue"]; + requiredDoubleValues: Primitives["requiredDoubleValues"]; + requiredFloatValues: Primitives["requiredFloatValues"]; + requiredInt32Values: Primitives["requiredInt32Values"]; + requiredInt64Values: Primitives["requiredInt64Values"]; + requiredUint32Values: Primitives["requiredUint32Values"]; + requiredUint64Values: Primitives["requiredUint64Values"]; + requiredSint32Values: Primitives["requiredSint32Values"]; + requiredSint64Values: Primitives["requiredSint64Values"]; + requiredFixed32Values: Primitives["requiredFixed32Values"]; + requiredFixed64Values: Primitives["requiredFixed64Values"]; + requiredSfixed32Values: Primitives["requiredSfixed32Values"]; + requiredSfixed64Values: Primitives["requiredSfixed64Values"]; + requiredBoolValues: Primitives["requiredBoolValues"]; + requiredStringValues: Primitives["requiredStringValues"]; + requiredBytesValues: Primitives["requiredBytesValues"]; +}; + +export const PrimitivesInput$Ref: InputObjectRef = builder.inputRef( + "PrimitivesInput", +).implement({ + "fields": (t) => ({ + requiredDoubleValue: t.field({ + "type": "Float", + "required": true, + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }), + requiredFloatValue: t.field({ + "type": "Float", + "required": true, + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }), + requiredInt32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }), + requiredInt64Value: t.field({ + "type": "Int64", + "required": true, + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }), + requiredUint32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }), + requiredUint64Value: t.field({ + "type": "Int64", + "required": true, + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }), + requiredSint32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }), + requiredSint64Value: t.field({ + "type": "Int64", + "required": true, + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }), + requiredFixed32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }), + requiredFixed64Value: t.field({ + "type": "Int64", + "required": true, + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Value: t.field({ + "type": "Int64", + "required": true, + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }), + requiredBoolValue: t.field({ + "type": "Boolean", + "required": true, + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }), + requiredStringValue: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }), + requiredBytesValue: t.field({ + "type": "Byte", + "required": true, + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }), + requiredDoubleValues: t.field({ + "type": ["Float"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }), + requiredFloatValues: t.field({ + "type": ["Float"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }), + requiredInt32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }), + requiredInt64Values: t.field({ + "type": ["Int64"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }), + requiredUint32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }), + requiredUint64Values: t.field({ + "type": ["Int64"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }), + requiredSint32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }), + requiredSint64Values: t.field({ + "type": ["Int64"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }), + requiredFixed32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }), + requiredFixed64Values: t.field({ + "type": ["Int64"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Values: t.field({ + "type": ["Int64"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }), + requiredBoolValues: t.field({ + "type": ["Boolean"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }), + requiredStringValues: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }), + requiredBytesValues: t.field({ + "type": ["Byte"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }), + }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, +}); + +export function PrimitivesInput$toProto(input: PrimitivesInput$Shape | null | undefined): Primitives { + return new Primitives({ + requiredDoubleValue: input?.requiredDoubleValue ?? undefined, + requiredFloatValue: input?.requiredFloatValue ?? undefined, + requiredInt32Value: input?.requiredInt32Value ?? undefined, + requiredInt64Value: input?.requiredInt64Value ?? undefined, + requiredUint32Value: input?.requiredUint32Value ?? undefined, + requiredUint64Value: input?.requiredUint64Value ?? undefined, + requiredSint32Value: input?.requiredSint32Value ?? undefined, + requiredSint64Value: input?.requiredSint64Value ?? undefined, + requiredFixed32Value: input?.requiredFixed32Value ?? undefined, + requiredFixed64Value: input?.requiredFixed64Value ?? undefined, + requiredSfixed32Value: input?.requiredSfixed32Value ?? undefined, + requiredSfixed64Value: input?.requiredSfixed64Value ?? undefined, + requiredBoolValue: input?.requiredBoolValue ?? undefined, + requiredStringValue: input?.requiredStringValue ?? undefined, + requiredBytesValue: input?.requiredBytesValue ?? undefined, + requiredDoubleValues: input?.requiredDoubleValues ?? undefined, + requiredFloatValues: input?.requiredFloatValues ?? undefined, + requiredInt32Values: input?.requiredInt32Values ?? undefined, + requiredInt64Values: input?.requiredInt64Values ?? undefined, + requiredUint32Values: input?.requiredUint32Values ?? undefined, + requiredUint64Values: input?.requiredUint64Values ?? undefined, + requiredSint32Values: input?.requiredSint32Values ?? undefined, + requiredSint64Values: input?.requiredSint64Values ?? undefined, + requiredFixed32Values: input?.requiredFixed32Values ?? undefined, + requiredFixed64Values: input?.requiredFixed64Values ?? undefined, + requiredSfixed32Values: input?.requiredSfixed32Values ?? undefined, + requiredSfixed64Values: input?.requiredSfixed64Values ?? undefined, + requiredBoolValues: input?.requiredBoolValues ?? undefined, + requiredStringValues: input?.requiredStringValues ?? undefined, + requiredBytesValues: input?.requiredBytesValues ?? undefined, + }); +} +" +`; + +exports[`createInputObjectTypeCode > protobuf-es > 'generates code for an input object wi…' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { Message } from "@testapis/protobuf-es/testapis/primitives/primitives_pb"; +import { builder } from "../../../../builder"; + +export type MessageInput$Shape = { + requiredPrimitives: PrimitivesInput$Shape; + optionalPrimitives?: PrimitivesInput$Shape | null; + requiredPrimitivesList: Array; + optionalPrimitivesList?: Array | null; +}; + +export const MessageInput$Ref: InputObjectRef = builder.inputRef("MessageInput") + .implement({ + "fields": (t) => ({ + requiredPrimitives: t.field({ + "type": PrimitivesInput$Ref, + "required": true, + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitives: t.field({ + "type": PrimitivesInput$Ref, + "required": false, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + requiredPrimitivesList: t.field({ + "type": [PrimitivesInput$Ref], + "required": { "list": true, "items": true }, + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitivesList: t.field({ + "type": [PrimitivesInput$Ref], + "required": { "list": false, "items": true }, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, + }); + +export function MessageInput$toProto(input: MessageInput$Shape | null | undefined): Message { + return new Message({ + requiredPrimitives: input?.requiredPrimitives ? PrimitivesInput$toProto(input.requiredPrimitives) : undefined, + optionalPrimitives: input?.optionalPrimitives ? PrimitivesInput$toProto(input.optionalPrimitives) : undefined, + requiredPrimitivesList: input?.requiredPrimitivesList?.map((v) => PrimitivesInput$toProto(v)), + optionalPrimitivesList: input?.optionalPrimitivesList?.map((v) => PrimitivesInput$toProto(v)), + }); +} +" +`; + +exports[`createInputObjectTypeCode > protobuf-es > 'generates code for an input object wi…' 2`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { OneofParent } from "@testapis/protobuf-es/testapis/oneof/oneof_pb"; +import { builder } from "../../../../builder"; + +export type OneofParentInput$Shape = { + normalField: OneofParent["normalField"]; + requiredMessage1?: OneofMemberMessage1Input$Shape | null; + requiredMessage2?: OneofMemberMessage2Input$Shape | null; + optoinalMessage1?: OneofMemberMessage1Input$Shape | null; + optoinalMessage2?: OneofMemberMessage2Input$Shape | null; +}; + +export const OneofParentInput$Ref: InputObjectRef = builder.inputRef( + "OneofParentInput", +).implement({ + "fields": (t) => ({ + normalField: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }), + requiredMessage1: t.field({ + "type": OneofMemberMessage1Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "required_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }), + requiredMessage2: t.field({ + "type": OneofMemberMessage2Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "required_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }), + optoinalMessage1: t.field({ + "type": OneofMemberMessage1Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "optoinal_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }), + optoinalMessage2: t.field({ + "type": OneofMemberMessage2Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "optoinal_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }), + }), + "extensions": { + "protobufMessage": { "fullName": "testapis.oneof.OneofParent", "name": "OneofParent", "package": "testapis.oneof" }, + }, +}); + +export function OneofParentInput$toProto(input: OneofParentInput$Shape | null | undefined): OneofParent { + return new OneofParent({ + normalField: input?.normalField ?? undefined, + requiredOneofMembers: input?.requiredMessage1 + ? { case: "requiredMessage1", value: OneofMemberMessage1Input$toProto(input.requiredMessage1) } + : input?.requiredMessage2 + ? { case: "requiredMessage2", value: OneofMemberMessage2Input$toProto(input.requiredMessage2) } + : undefined, + optionalOneofMembers: input?.optoinalMessage1 + ? { case: "optoinalMessage1", value: OneofMemberMessage1Input$toProto(input.optoinalMessage1) } + : input?.optoinalMessage2 + ? { case: "optoinalMessage2", value: OneofMemberMessage2Input$toProto(input.optoinalMessage2) } + : undefined, + }); +} +" +`; + +exports[`createInputObjectTypeCode > protobuf-es > 'generates code for empty input object' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { EmptyMessage } from "@testapis/protobuf-es/testapis/empty_types/empty_pb"; +import { builder } from "../../../../builder"; + +export type EmptyMessageInput$Shape = {}; + +export const EmptyMessageInput$Ref: InputObjectRef = builder.inputRef( + "EmptyMessageInput", +).implement({ + "fields": (t) => ({ _: t.field({ type: "Boolean", required: false, description: "noop field" }) }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.empty_types.EmptyMessage", + "name": "EmptyMessage", + "package": "testapis.empty_types", + }, + }, +}); + +export function EmptyMessageInput$toProto(input: EmptyMessageInput$Shape | null | undefined): EmptyMessage { + return new EmptyMessage({}); +} +" +`; + +exports[`createInputObjectTypeCode > ts-proto > 'generates code for a simple input obj…' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { Primitives } from "@testapis/ts-proto/testapis/primitives/primitives"; +import { builder } from "../../../../builder"; + +export type PrimitivesInput$Shape = { + requiredDoubleValue: Primitives["requiredDoubleValue"]; + requiredFloatValue: Primitives["requiredFloatValue"]; + requiredInt32Value: Primitives["requiredInt32Value"]; + requiredInt64Value: Primitives["requiredInt64Value"]; + requiredUint32Value: Primitives["requiredUint32Value"]; + requiredUint64Value: Primitives["requiredUint64Value"]; + requiredSint32Value: Primitives["requiredSint32Value"]; + requiredSint64Value: Primitives["requiredSint64Value"]; + requiredFixed32Value: Primitives["requiredFixed32Value"]; + requiredFixed64Value: Primitives["requiredFixed64Value"]; + requiredSfixed32Value: Primitives["requiredSfixed32Value"]; + requiredSfixed64Value: Primitives["requiredSfixed64Value"]; + requiredBoolValue: Primitives["requiredBoolValue"]; + requiredStringValue: Primitives["requiredStringValue"]; + requiredBytesValue: Primitives["requiredBytesValue"]; + requiredDoubleValues: Primitives["requiredDoubleValues"]; + requiredFloatValues: Primitives["requiredFloatValues"]; + requiredInt32Values: Primitives["requiredInt32Values"]; + requiredInt64Values: Primitives["requiredInt64Values"]; + requiredUint32Values: Primitives["requiredUint32Values"]; + requiredUint64Values: Primitives["requiredUint64Values"]; + requiredSint32Values: Primitives["requiredSint32Values"]; + requiredSint64Values: Primitives["requiredSint64Values"]; + requiredFixed32Values: Primitives["requiredFixed32Values"]; + requiredFixed64Values: Primitives["requiredFixed64Values"]; + requiredSfixed32Values: Primitives["requiredSfixed32Values"]; + requiredSfixed64Values: Primitives["requiredSfixed64Values"]; + requiredBoolValues: Primitives["requiredBoolValues"]; + requiredStringValues: Primitives["requiredStringValues"]; + requiredBytesValues: Primitives["requiredBytesValues"]; +}; + +export const PrimitivesInput$Ref: InputObjectRef = builder.inputRef( + "PrimitivesInput", +).implement({ + "fields": (t) => ({ + requiredDoubleValue: t.field({ + "type": "Float", + "required": true, + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }), + requiredFloatValue: t.field({ + "type": "Float", + "required": true, + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }), + requiredInt32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }), + requiredInt64Value: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }), + requiredUint32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }), + requiredUint64Value: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }), + requiredSint32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }), + requiredSint64Value: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }), + requiredFixed32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }), + requiredFixed64Value: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Value: t.field({ + "type": "Int", + "required": true, + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Value: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }), + requiredBoolValue: t.field({ + "type": "Boolean", + "required": true, + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }), + requiredStringValue: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }), + requiredBytesValue: t.field({ + "type": "Byte", + "required": true, + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }), + requiredDoubleValues: t.field({ + "type": ["Float"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }), + requiredFloatValues: t.field({ + "type": ["Float"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }), + requiredInt32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }), + requiredInt64Values: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }), + requiredUint32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }), + requiredUint64Values: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }), + requiredSint32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }), + requiredSint64Values: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }), + requiredFixed32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }), + requiredFixed64Values: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Values: t.field({ + "type": ["Int"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Values: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }), + requiredBoolValues: t.field({ + "type": ["Boolean"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }), + requiredStringValues: t.field({ + "type": ["String"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }), + requiredBytesValues: t.field({ + "type": ["Byte"], + "required": { "list": true, "items": true }, + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }), + }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createInputObjectTypeCode > ts-proto > 'generates code for an input object wi…' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { builder } from "../../../../builder"; + +export type MessageInput$Shape = { + requiredPrimitives: PrimitivesInput$Shape; + optionalPrimitives?: PrimitivesInput$Shape | null; + requiredPrimitivesList: Array; + optionalPrimitivesList?: Array | null; +}; + +export const MessageInput$Ref: InputObjectRef = builder.inputRef("MessageInput") + .implement({ + "fields": (t) => ({ + requiredPrimitives: t.field({ + "type": PrimitivesInput$Ref, + "required": true, + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitives: t.field({ + "type": PrimitivesInput$Ref, + "required": false, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + requiredPrimitivesList: t.field({ + "type": [PrimitivesInput$Ref], + "required": { "list": true, "items": true }, + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitivesList: t.field({ + "type": [PrimitivesInput$Ref], + "required": { "list": false, "items": true }, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, + }); +" +`; + +exports[`createInputObjectTypeCode > ts-proto > 'generates code for an input object wi…' 2`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { OneofParent } from "@testapis/ts-proto/testapis/oneof/oneof"; +import { builder } from "../../../../builder"; + +export type OneofParentInput$Shape = { + normalField: OneofParent["normalField"]; + requiredMessage1?: OneofMemberMessage1Input$Shape | null; + requiredMessage2?: OneofMemberMessage2Input$Shape | null; + optoinalMessage1?: OneofMemberMessage1Input$Shape | null; + optoinalMessage2?: OneofMemberMessage2Input$Shape | null; +}; + +export const OneofParentInput$Ref: InputObjectRef = builder.inputRef( + "OneofParentInput", +).implement({ + "fields": (t) => ({ + normalField: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }), + requiredMessage1: t.field({ + "type": OneofMemberMessage1Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "required_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }), + requiredMessage2: t.field({ + "type": OneofMemberMessage2Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "required_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }), + optoinalMessage1: t.field({ + "type": OneofMemberMessage1Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "optoinal_message1", "typeFullName": "testapis.oneof.OneofMemberMessage1" }, + }, + }), + optoinalMessage2: t.field({ + "type": OneofMemberMessage2Input$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "optoinal_message2", "typeFullName": "testapis.oneof.OneofMemberMessage2" }, + }, + }), + }), + "extensions": { + "protobufMessage": { "fullName": "testapis.oneof.OneofParent", "name": "OneofParent", "package": "testapis.oneof" }, + }, +}); +" +`; + +exports[`createInputObjectTypeCode > ts-proto > 'generates code for empty input object' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { builder } from "../../../../builder"; + +export type EmptyMessageInput$Shape = {}; + +export const EmptyMessageInput$Ref: InputObjectRef = builder.inputRef( + "EmptyMessageInput", +).implement({ + "fields": (t) => ({ _: t.field({ type: "Boolean", required: false, description: "noop field" }) }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.empty_types.EmptyMessage", + "name": "EmptyMessage", + "package": "testapis.empty_types", + }, + }, +}); +" +`; + +exports[`createInputObjectTypeCode > ts-proto > 'generates code for nested input types' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { ParentMessage } from "@testapis/ts-proto/testapis/nested/nested"; +import { builder } from "../../../../builder"; + +export type ParentMessageInput$Shape = { + body: ParentMessage["body"]; + nested?: ParentMessageNestedMessageInput$Shape | null; + nestedEnum?: ParentMessage["nestedEnum"] | null; +}; + +export const ParentMessageInput$Ref: InputObjectRef = builder.inputRef< + ParentMessageInput$Shape +>("ParentMessageInput").implement({ + "fields": (t) => ({ + body: t.field({ + "type": "String", + "required": true, + "extensions": { "protobufField": { "name": "body", "typeFullName": "string" } }, + }), + nested: t.field({ + "type": ParentMessageNestedMessageInput$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "nested", "typeFullName": "testapis.nested.ParentMessage.NestedMessage" }, + }, + }), + nestedEnum: t.field({ + "type": ParentMessageNestedEnum$Ref, + "required": false, + "extensions": { + "protobufField": { "name": "nested_enum", "typeFullName": "testapis.nested.ParentMessage.NestedEnum" }, + }, + }), + }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.nested.ParentMessage", + "name": "ParentMessage", + "package": "testapis.nested", + }, + }, +}); +" +`; + +exports[`createInputObjectTypeCode > with partial inputs > 'generates code for partial input types' 1`] = ` +"import { InputObjectRef } from "@pothos/core"; +import { builder } from "../../../../builder"; + +export type MessagePartialInput$Shape = { + requiredPrimitives?: PrimitivesPartialInput$Shape | null; + optionalPrimitives?: PrimitivesPartialInput$Shape | null; + requiredPrimitivesList?: Array | null; + optionalPrimitivesList?: Array | null; +}; + +export const MessagePartialInput$Ref: InputObjectRef = builder.inputRef< + MessagePartialInput$Shape +>("MessagePartialInput").implement({ + "fields": (t) => ({ + requiredPrimitives: t.field({ + "type": PrimitivesPartialInput$Ref, + "required": false, + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitives: t.field({ + "type": PrimitivesPartialInput$Ref, + "required": false, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + requiredPrimitivesList: t.field({ + "type": [PrimitivesPartialInput$Ref], + "required": { "list": false, "items": true }, + "description": "Required.", + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitivesList: t.field({ + "type": [PrimitivesPartialInput$Ref], + "required": { "list": false, "items": true }, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + }), + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, +}); +" +`; diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/objectType.test.ts.snap b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/objectType.test.ts.snap new file mode 100644 index 00000000..fe291141 --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/objectType.test.ts.snap @@ -0,0 +1,801 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createObjectTypeCode > protobuf-es > 'generates code for a message with nes…' 1`] = ` +"import { Message } from "@testapis/protobuf-es/testapis/primitives/primitives_pb"; +import { builder } from "../../../../builder"; + +export const Message$Ref = builder.objectRef("Message"); +builder.objectType(Message$Ref, { + "name": "Message", + "fields": (t) => ({ + requiredPrimitives: t.field({ + "type": Primitives$Ref, + "nullable": false, + "description": "Required.", + "resolve": (source) => { + return source.requiredPrimitives!; + }, + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitives: t.expose("optionalPrimitives", { + "type": Primitives$Ref, + "nullable": true, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + requiredPrimitivesList: t.field({ + "type": [Primitives$Ref], + "nullable": { "list": false, "items": false }, + "description": "Required.", + "resolve": (source) => { + return source.requiredPrimitivesList!; + }, + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitivesList: t.expose("optionalPrimitivesList", { + "type": [Primitives$Ref], + "nullable": { "list": true, "items": false }, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + }), + "isTypeOf": (source) => { + return source instanceof Message; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > protobuf-es > 'generates code for a message with one…' 1`] = ` +"import { OneofParent } from "@testapis/protobuf-es/testapis/oneof/oneof_pb"; +import { builder } from "../../../../builder"; + +export const OneofParent$Ref = builder.objectRef("OneofParent"); +builder.objectType(OneofParent$Ref, { + "name": "OneofParent", + "fields": (t) => ({ + normalField: t.expose("normalField", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }), + requiredOneofMembers: t.field({ + "type": OneofParentRequiredOneofMembers$Ref, + "nullable": false, + "description": "Required. disallow not_set.", + "resolve": (source) => { + const value = source.requiredOneofMembers.value; + if (value == null) { + throw new Error("requiredOneofMembers should not be null"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_oneof_members" } }, + }), + optionalOneofMembers: t.field({ + "type": OneofParentOptionalOneofMembers$Ref, + "nullable": true, + "resolve": (source) => { + return source.optionalOneofMembers.value; + }, + "extensions": { "protobufField": { "name": "optional_oneof_members" } }, + }), + }), + "isTypeOf": (source) => { + return source instanceof OneofParent; + }, + "extensions": { + "protobufMessage": { "fullName": "testapis.oneof.OneofParent", "name": "OneofParent", "package": "testapis.oneof" }, + }, +}); +" +`; + +exports[`createObjectTypeCode > protobuf-es > 'generates code for a simple message' 1`] = ` +"import { Primitives } from "@testapis/protobuf-es/testapis/primitives/primitives_pb"; +import { builder } from "../../../../builder"; + +export const Primitives$Ref = builder.objectRef("Primitives"); +builder.objectType(Primitives$Ref, { + "name": "Primitives", + "fields": (t) => ({ + requiredDoubleValue: t.expose("requiredDoubleValue", { + "type": "Float", + "nullable": false, + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }), + requiredFloatValue: t.expose("requiredFloatValue", { + "type": "Float", + "nullable": false, + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }), + requiredInt32Value: t.expose("requiredInt32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }), + requiredInt64Value: t.expose("requiredInt64Value", { + "type": "Int64", + "nullable": false, + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }), + requiredUint32Value: t.expose("requiredUint32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }), + requiredUint64Value: t.expose("requiredUint64Value", { + "type": "Int64", + "nullable": false, + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }), + requiredSint32Value: t.expose("requiredSint32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }), + requiredSint64Value: t.expose("requiredSint64Value", { + "type": "Int64", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }), + requiredFixed32Value: t.expose("requiredFixed32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }), + requiredFixed64Value: t.expose("requiredFixed64Value", { + "type": "Int64", + "nullable": false, + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Value: t.expose("requiredSfixed32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Value: t.expose("requiredSfixed64Value", { + "type": "Int64", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }), + requiredBoolValue: t.expose("requiredBoolValue", { + "type": "Boolean", + "nullable": false, + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }), + requiredStringValue: t.expose("requiredStringValue", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }), + requiredBytesValue: t.field({ + "type": "Byte", + "nullable": false, + "resolve": (source) => { + return Buffer.from(source.requiredBytesValue); + }, + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }), + requiredDoubleValues: t.expose("requiredDoubleValues", { + "type": ["Float"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }), + requiredFloatValues: t.expose("requiredFloatValues", { + "type": ["Float"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }), + requiredInt32Values: t.expose("requiredInt32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }), + requiredInt64Values: t.expose("requiredInt64Values", { + "type": ["Int64"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }), + requiredUint32Values: t.expose("requiredUint32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }), + requiredUint64Values: t.expose("requiredUint64Values", { + "type": ["Int64"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }), + requiredSint32Values: t.expose("requiredSint32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }), + requiredSint64Values: t.expose("requiredSint64Values", { + "type": ["Int64"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }), + requiredFixed32Values: t.expose("requiredFixed32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }), + requiredFixed64Values: t.expose("requiredFixed64Values", { + "type": ["Int64"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Values: t.expose("requiredSfixed32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Values: t.expose("requiredSfixed64Values", { + "type": ["Int64"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }), + requiredBoolValues: t.expose("requiredBoolValues", { + "type": ["Boolean"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }), + requiredStringValues: t.expose("requiredStringValues", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }), + requiredBytesValues: t.field({ + "type": ["Byte"], + "nullable": { "list": false, "items": false }, + "resolve": (source) => { + return source.requiredBytesValues.map((v) => Buffer.from(v)); + }, + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }), + }), + "isTypeOf": (source) => { + return source instanceof Primitives; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > ts-proto > 'generates code for a message with nes…' 1`] = ` +"import { Message } from "@testapis/ts-proto/testapis/primitives/primitives"; +import { builder } from "../../../../builder"; + +export const Message$Ref = builder.objectRef("Message"); +builder.objectType(Message$Ref, { + "name": "Message", + "fields": (t) => ({ + requiredPrimitives: t.field({ + "type": Primitives$Ref, + "nullable": false, + "description": "Required.", + "resolve": (source) => { + return source.requiredPrimitives!; + }, + "extensions": { + "protobufField": { "name": "required_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitives: t.expose("optionalPrimitives", { + "type": Primitives$Ref, + "nullable": true, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + requiredPrimitivesList: t.field({ + "type": [Primitives$Ref], + "nullable": { "list": false, "items": false }, + "description": "Required.", + "resolve": (source) => { + return source.requiredPrimitivesList!; + }, + "extensions": { + "protobufField": { "name": "required_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + optionalPrimitivesList: t.expose("optionalPrimitivesList", { + "type": [Primitives$Ref], + "nullable": { "list": true, "items": false }, + "description": "Optional.", + "extensions": { + "protobufField": { "name": "optional_primitives_list", "typeFullName": "testapis.primitives.Primitives" }, + }, + }), + }), + "isTypeOf": (source) => { + return (source as Message | { $type: string & {} }).$type === "testapis.primitives.Message"; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Message", + "name": "Message", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > ts-proto > 'generates code for a message with one…' 1`] = ` +"import { OneofParent } from "@testapis/ts-proto/testapis/oneof/oneof"; +import { builder } from "../../../../builder"; + +export const OneofParent$Ref = builder.objectRef("OneofParent"); +builder.objectType(OneofParent$Ref, { + "name": "OneofParent", + "fields": (t) => ({ + normalField: t.expose("normalField", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "normal_field", "typeFullName": "string" } }, + }), + requiredOneofMembers: t.field({ + "type": OneofParentRequiredOneofMembers$Ref, + "nullable": false, + "description": "Required. disallow not_set.", + "resolve": (source) => { + const value = source.requiredMessage1 ?? source.requiredMessage2; + if (value == null) { + throw new Error("requiredOneofMembers should not be null"); + } + return value; + }, + "extensions": { "protobufField": { "name": "required_oneof_members" } }, + }), + optionalOneofMembers: t.field({ + "type": OneofParentOptionalOneofMembers$Ref, + "nullable": true, + "resolve": (source) => { + const value = source.optoinalMessage1 ?? source.optoinalMessage2; + if (value == null) { + return null; + } + return value; + }, + "extensions": { "protobufField": { "name": "optional_oneof_members" } }, + }), + }), + "isTypeOf": (source) => { + return (source as OneofParent | { $type: string & {} }).$type === "testapis.oneof.OneofParent"; + }, + "extensions": { + "protobufMessage": { "fullName": "testapis.oneof.OneofParent", "name": "OneofParent", "package": "testapis.oneof" }, + }, +}); +" +`; + +exports[`createObjectTypeCode > ts-proto > 'generates code for a simple message' 1`] = ` +"import { Primitives } from "@testapis/ts-proto/testapis/primitives/primitives"; +import { builder } from "../../../../builder"; + +export const Primitives$Ref = builder.objectRef("Primitives"); +builder.objectType(Primitives$Ref, { + "name": "Primitives", + "fields": (t) => ({ + requiredDoubleValue: t.expose("requiredDoubleValue", { + "type": "Float", + "nullable": false, + "extensions": { "protobufField": { "name": "required_double_value", "typeFullName": "double" } }, + }), + requiredFloatValue: t.expose("requiredFloatValue", { + "type": "Float", + "nullable": false, + "extensions": { "protobufField": { "name": "required_float_value", "typeFullName": "float" } }, + }), + requiredInt32Value: t.expose("requiredInt32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_int32_value", "typeFullName": "int32" } }, + }), + requiredInt64Value: t.expose("requiredInt64Value", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_int64_value", "typeFullName": "int64" } }, + }), + requiredUint32Value: t.expose("requiredUint32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_uint32_value", "typeFullName": "uint32" } }, + }), + requiredUint64Value: t.expose("requiredUint64Value", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_uint64_value", "typeFullName": "uint64" } }, + }), + requiredSint32Value: t.expose("requiredSint32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sint32_value", "typeFullName": "sint32" } }, + }), + requiredSint64Value: t.expose("requiredSint64Value", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sint64_value", "typeFullName": "sint64" } }, + }), + requiredFixed32Value: t.expose("requiredFixed32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_fixed32_value", "typeFullName": "fixed32" } }, + }), + requiredFixed64Value: t.expose("requiredFixed64Value", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_fixed64_value", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Value: t.expose("requiredSfixed32Value", { + "type": "Int", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sfixed32_value", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Value: t.expose("requiredSfixed64Value", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_sfixed64_value", "typeFullName": "sfixed64" } }, + }), + requiredBoolValue: t.expose("requiredBoolValue", { + "type": "Boolean", + "nullable": false, + "extensions": { "protobufField": { "name": "required_bool_value", "typeFullName": "bool" } }, + }), + requiredStringValue: t.expose("requiredStringValue", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "required_string_value", "typeFullName": "string" } }, + }), + requiredBytesValue: t.field({ + "type": "Byte", + "nullable": false, + "resolve": (source) => { + return Buffer.from(source.requiredBytesValue); + }, + "extensions": { "protobufField": { "name": "required_bytes_value", "typeFullName": "bytes" } }, + }), + requiredDoubleValues: t.expose("requiredDoubleValues", { + "type": ["Float"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_double_values", "typeFullName": "double" } }, + }), + requiredFloatValues: t.expose("requiredFloatValues", { + "type": ["Float"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_float_values", "typeFullName": "float" } }, + }), + requiredInt32Values: t.expose("requiredInt32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_int32_values", "typeFullName": "int32" } }, + }), + requiredInt64Values: t.expose("requiredInt64Values", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_int64_values", "typeFullName": "int64" } }, + }), + requiredUint32Values: t.expose("requiredUint32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_uint32_values", "typeFullName": "uint32" } }, + }), + requiredUint64Values: t.expose("requiredUint64Values", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_uint64_values", "typeFullName": "uint64" } }, + }), + requiredSint32Values: t.expose("requiredSint32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sint32_values", "typeFullName": "sint32" } }, + }), + requiredSint64Values: t.expose("requiredSint64Values", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sint64_values", "typeFullName": "sint64" } }, + }), + requiredFixed32Values: t.expose("requiredFixed32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_fixed32_values", "typeFullName": "fixed32" } }, + }), + requiredFixed64Values: t.expose("requiredFixed64Values", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_fixed64_values", "typeFullName": "fixed64" } }, + }), + requiredSfixed32Values: t.expose("requiredSfixed32Values", { + "type": ["Int"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sfixed32_values", "typeFullName": "sfixed32" } }, + }), + requiredSfixed64Values: t.expose("requiredSfixed64Values", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_sfixed64_values", "typeFullName": "sfixed64" } }, + }), + requiredBoolValues: t.expose("requiredBoolValues", { + "type": ["Boolean"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_bool_values", "typeFullName": "bool" } }, + }), + requiredStringValues: t.expose("requiredStringValues", { + "type": ["String"], + "nullable": { "list": false, "items": false }, + "extensions": { "protobufField": { "name": "required_string_values", "typeFullName": "string" } }, + }), + requiredBytesValues: t.field({ + "type": ["Byte"], + "nullable": { "list": false, "items": false }, + "resolve": (source) => { + return source.requiredBytesValues.map((v) => Buffer.from(v)); + }, + "extensions": { "protobufField": { "name": "required_bytes_values", "typeFullName": "bytes" } }, + }), + }), + "isTypeOf": (source) => { + return (source as Primitives | { $type: string & {} }).$type === "testapis.primitives.Primitives"; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.primitives.Primitives", + "name": "Primitives", + "package": "testapis.primitives", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > ts-proto > 'generates code for empty message' 1`] = ` +"import { EmptyMessage } from "@testapis/ts-proto/testapis/empty_types/empty"; +import { builder } from "../../../../builder"; + +export const EmptyMessage$Ref = builder.objectRef("EmptyMessage"); +builder.objectType(EmptyMessage$Ref, { + "name": "EmptyMessage", + "fields": (t) => ({ + _: t.field({ type: "Boolean", nullable: true, description: "noop field", resolve: () => true }), + }), + "isTypeOf": (source) => { + return (source as EmptyMessage | { $type: string & {} }).$type === "testapis.empty_types.EmptyMessage"; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.empty_types.EmptyMessage", + "name": "EmptyMessage", + "package": "testapis.empty_types", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > ts-proto > 'generates code for nested types' 1`] = ` +"import { ParentMessage, ParentMessage_NestedEnum } from "@testapis/ts-proto/testapis/nested/nested"; +import { builder } from "../../../../builder"; + +export const ParentMessage$Ref = builder.objectRef("ParentMessage"); +builder.objectType(ParentMessage$Ref, { + "name": "ParentMessage", + "fields": (t) => ({ + body: t.expose("body", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "body", "typeFullName": "string" } }, + }), + nested: t.expose("nested", { + "type": ParentMessageNestedMessage$Ref, + "nullable": true, + "extensions": { + "protobufField": { "name": "nested", "typeFullName": "testapis.nested.ParentMessage.NestedMessage" }, + }, + }), + nestedEnum: t.field({ + "type": ParentMessageNestedEnum$Ref, + "nullable": true, + "resolve": (source) => { + if (source.nestedEnum === ParentMessage_NestedEnum.NESTED_ENUM_UNSPECIFIED) { + return null; + } + + return source.nestedEnum; + }, + "extensions": { + "protobufField": { "name": "nested_enum", "typeFullName": "testapis.nested.ParentMessage.NestedEnum" }, + }, + }), + }), + "isTypeOf": (source) => { + return (source as ParentMessage | { $type: string & {} }).$type === "testapis.nested.ParentMessage"; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.nested.ParentMessage", + "name": "ParentMessage", + "package": "testapis.nested", + }, + }, +}); +" +`; + +exports[`createObjectTypeCode > with extensions > 'generates code for message with field…' 1`] = ` +"import { EnumWillRename, PrefixedEnum, PrefixedMessage } from "@testapis/ts-proto/testapis/extensions/extensions"; +import { builder } from "../../../../builder"; + +export const TestPrefixPrefixedMessage$Ref = builder.objectRef("TestPrefixPrefixedMessage"); +builder.objectType(TestPrefixPrefixedMessage$Ref, { + "name": "TestPrefixPrefixedMessage", + "fields": (t) => ({ + id: t.expose("id", { + "type": "String", + "nullable": false, + "description": "Output only.", + "extensions": { "protobufField": { "name": "id", "typeFullName": "uint64" } }, + }), + body: t.expose("body", { + "type": "String", + "nullable": false, + "extensions": { "protobufField": { "name": "body", "typeFullName": "string" } }, + }), + prefixedEnum: t.field({ + "type": TestPrefixPrefixedEnum$Ref, + "nullable": true, + "resolve": (source) => { + if (source.prefixedEnum === PrefixedEnum.PREFIXED_ENUM_UNSPECIFIED) { + return null; + } + + if (source.prefixedEnum === PrefixedEnum.PREFIXED_IGNORED) { + throw new Error("PREFIXED_IGNORED is ignored in GraphQL schema"); + } + + return source.prefixedEnum; + }, + "extensions": { + "protobufField": { "name": "prefixed_enum", "typeFullName": "testapis.extensions.PrefixedEnum" }, + }, + }), + notIgnoredMessage: t.expose("notIgnoredMessage", { + "type": TestPrefixIgnoredMessageNotIgnored$Ref, + "nullable": true, + "extensions": { + "protobufField": { + "name": "not_ignored_message", + "typeFullName": "testapis.extensions.IgnoredMessage.NotIgnored", + }, + }, + }), + squashedMessage: t.field({ + "type": TestPrefixPrefixedMessageSquashedMessage$Ref, + "nullable": true, + "resolve": (source) => { + const value = source.squashedMessage?.oneofField ?? source.squashedMessage?.oneofField2; + if (value == null) { + return null; + } + return value; + }, + "extensions": { + "protobufField": { + "name": "squashed_message", + "typeFullName": "testapis.extensions.PrefixedMessage.SquashedMessage", + }, + }, + }), + thisFieldWasRenamed: t.expose("thisFieldWillBeRenamed", { + "type": "String", + "nullable": false, + "extensions": { + "protobufField": { + "name": "this_field_will_be_renamed", + "typeFullName": "string", + "options": { "[graphql.field]": { "name": "thisFieldWasRenamed" } }, + }, + }, + }), + skipResolver: t.expose("skipResolver", { + "type": "String", + "nullable": false, + "extensions": { + "protobufField": { + "name": "skip_resolver", + "typeFullName": "string", + "options": { "[graphql.field]": { "skipResolver": true } }, + }, + }, + }), + squashedMessages: t.field({ + "type": [TestPrefixPrefixedMessageSquashedMessage$Ref], + "nullable": { "list": true, "items": false }, + "resolve": (source) => { + return source.squashedMessages.map((item) => { + const value = item?.oneofField ?? item?.oneofField2; + if (value == null) { + throw new Error("squashedMessages should not be null"); + } + return value; + }); + }, + "extensions": { + "protobufField": { + "name": "squashed_messages", + "typeFullName": "testapis.extensions.PrefixedMessage.SquashedMessage", + }, + }, + }), + renamedMessage: t.expose("renamedMessage", { + "type": TestPrefixRenamedMessage$Ref, + "nullable": true, + "extensions": { + "protobufField": { "name": "renamed_message", "typeFullName": "testapis.extensions.MessageWillRename" }, + }, + }), + renamedEnum: t.field({ + "type": TestPrefixRenamedEnum$Ref, + "nullable": true, + "resolve": (source) => { + if (source.renamedEnum === EnumWillRename.ENUM_WILL_RENAME_UNSPECIFIED) { + return null; + } + + return source.renamedEnum; + }, + "extensions": { + "protobufField": { "name": "renamed_enum", "typeFullName": "testapis.extensions.EnumWillRename" }, + }, + }), + partialIgnoreOneof: t.field({ + "type": TestPrefixPrefixedMessagePartialIgnoreOneof$Ref, + "nullable": true, + "resolve": (source) => { + const value = source.oneofNotIgnoredField; + if (value == null) { + return null; + } + return value; + }, + "extensions": { "protobufField": { "name": "partial_ignore_oneof" } }, + }), + }), + "isTypeOf": (source) => { + return (source as PrefixedMessage | { $type: string & {} }).$type === "testapis.extensions.PrefixedMessage"; + }, + "extensions": { + "protobufMessage": { + "fullName": "testapis.extensions.PrefixedMessage", + "name": "PrefixedMessage", + "package": "testapis.extensions", + }, + }, +}); +" +`; diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/oneofUnionType.test.ts.snap b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/oneofUnionType.test.ts.snap new file mode 100644 index 00000000..ea9b6280 --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/__snapshots__/oneofUnionType.test.ts.snap @@ -0,0 +1,189 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createOneofUnionTypeCode > protobuf-es > 'generates code for a required oneof u…' 1`] = ` +"import { builder } from "../../../../builder"; + +export const OneofParentRequiredOneofMembers$Ref = builder.unionType("OneofParentRequiredOneofMembers", { + "types": [OneofMemberMessage1$Ref, OneofMemberMessage2$Ref], + "description": "Required. disallow not_set.", + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.required_oneof_members", + "name": "required_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "required_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "required_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > protobuf-es > 'generates code for a squashed oneof u…' 1`] = ` +"import { builder } from "../../../../builder"; + +export const TestPrefixPrefixedMessageSquashedMessage$Ref = builder.unionType( + "TestPrefixPrefixedMessageSquashedMessage", + { + "types": [TestPrefixPrefixedMessageInnerMessage$Ref, TestPrefixPrefixedMessageInnerMessage2$Ref], + "extensions": { + "protobufOneof": { + "fullName": "testapis.extensions.PrefixedMessage.SquashedMessage", + "name": "SquashedMessage", + "package": "testapis.extensions", + "fields": [{ + "name": "oneof_field", + "type": "testapis.extensions.PrefixedMessage.InnerMessage", + "options": { "[graphql.object_type]": { "squashUnion": true } }, + }, { + "name": "oneof_field_2", + "type": "testapis.extensions.PrefixedMessage.InnerMessage2", + "options": { "[graphql.object_type]": { "squashUnion": true } }, + }], + }, + }, + }, +); +" +`; + +exports[`createOneofUnionTypeCode > protobuf-es > 'generates code for an optional oneof …' 1`] = ` +"import { builder } from "../../../../builder"; + +export const OneofParentOptionalOneofMembers$Ref = builder.unionType("OneofParentOptionalOneofMembers", { + "types": [OneofMemberMessage1$Ref, OneofMemberMessage2$Ref], + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.optional_oneof_members", + "name": "optional_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "optoinal_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "optoinal_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > ts-proto > 'generates code for a required oneof u…' 1`] = ` +"import { builder } from "../../../../builder"; + +export const OneofParentRequiredOneofMembers$Ref = builder.unionType("OneofParentRequiredOneofMembers", { + "types": [OneofMemberMessage1$Ref, OneofMemberMessage2$Ref], + "description": "Required. disallow not_set.", + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.required_oneof_members", + "name": "required_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "required_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "required_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > ts-proto > 'generates code for a squashed oneof u…' 1`] = ` +"import { builder } from "../../../../builder"; + +export const TestPrefixPrefixedMessageSquashedMessage$Ref = builder.unionType( + "TestPrefixPrefixedMessageSquashedMessage", + { + "types": [TestPrefixPrefixedMessageInnerMessage$Ref, TestPrefixPrefixedMessageInnerMessage2$Ref], + "extensions": { + "protobufOneof": { + "fullName": "testapis.extensions.PrefixedMessage.SquashedMessage", + "name": "SquashedMessage", + "package": "testapis.extensions", + "fields": [{ + "name": "oneof_field", + "type": "testapis.extensions.PrefixedMessage.InnerMessage", + "options": { "[graphql.object_type]": { "squashUnion": true } }, + }, { + "name": "oneof_field_2", + "type": "testapis.extensions.PrefixedMessage.InnerMessage2", + "options": { "[graphql.object_type]": { "squashUnion": true } }, + }], + }, + }, + }, +); +" +`; + +exports[`createOneofUnionTypeCode > ts-proto > 'generates code for an optional oneof …' 1`] = ` +"import { builder } from "../../../../builder"; + +export const OneofParentOptionalOneofMembers$Ref = builder.unionType("OneofParentOptionalOneofMembers", { + "types": [OneofMemberMessage1$Ref, OneofMemberMessage2$Ref], + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.optional_oneof_members", + "name": "optional_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "optoinal_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "optoinal_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > ts-proto > 'generates code for imported oneof mem…' 1`] = ` +"import { builder } from "../../../../../builder"; +import { OneofMember1$Ref, OneofMember2$Ref } from "./member.pothos"; + +export const OneofParentOneofField$Ref = builder.unionType("OneofParentOneofField", { + "types": [OneofMember1$Ref, OneofMember2$Ref], + "extensions": { + "protobufOneof": { + "fullName": "testapis.edgecases.import_oneof_member_from_other_file.OneofParent.oneof_field", + "name": "oneof_field", + "messageName": "OneofParent", + "package": "testapis.edgecases.import_oneof_member_from_other_file", + "fields": [{ "name": "member1", "type": "testapis.edgecases.import_oneof_member_from_other_file.OneofMember1" }, { + "name": "member2", + "type": "testapis.edgecases.import_oneof_member_from_other_file.OneofMember2", + }], + }, + }, +}); +" +`; + +exports[`createOneofUnionTypeCode > with file layout graphql_type > 'generates code with correct imports f…' 1`] = ` +"import { builder } from "../../../../builder"; +import { OneofMemberMessage1$Ref } from "./OneofMemberMessage1.pothos"; +import { OneofMemberMessage2$Ref } from "./OneofMemberMessage2.pothos"; + +export const OneofParentRequiredOneofMembers$Ref = builder.unionType("OneofParentRequiredOneofMembers", { + "types": [OneofMemberMessage1$Ref, OneofMemberMessage2$Ref], + "description": "Required. disallow not_set.", + "extensions": { + "protobufOneof": { + "fullName": "testapis.oneof.OneofParent.required_oneof_members", + "name": "required_oneof_members", + "messageName": "OneofParent", + "package": "testapis.oneof", + "fields": [{ "name": "required_message1", "type": "testapis.oneof.OneofMemberMessage1" }, { + "name": "required_message2", + "type": "testapis.oneof.OneofMemberMessage2", + }], + }, + }, +}); +" +`; diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/enumType.test.ts b/packages/protoc-gen-pothos/src/dslgen/printers/enumType.test.ts new file mode 100644 index 00000000..2aba6df2 --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/enumType.test.ts @@ -0,0 +1,166 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + EnumType, + type TypeOptions, + defaultScalarMapping, + defaultScalarMappingForTsProto, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createEnumTypeCode } from "./enumType.js"; +import type { PothosPrinterOptions } from "./util.js"; + +function generateEnumTypeCode( + packageName: TestapisPackage, + enumTypeNameInProto: string, + options: PothosPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: + options.protobuf === "ts-proto" + ? defaultScalarMappingForTsProto + : defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + + // The actual proto package might differ from the TestapisPackage key + // For example: "testapis.enums" key but "testapi.enums" proto package + let descEnum = registry.getEnum(`${packageName}.${enumTypeNameInProto}`); + + if (descEnum === undefined && packageName === "testapis.enums") { + // Try with the actual proto package name + descEnum = registry.getEnum(`testapi.enums.${enumTypeNameInProto}`); + } + + if (descEnum === undefined) { + throw new Error( + `Enum ${enumTypeNameInProto} not found in package ${packageName}`, + ); + } + + const enumType = new EnumType(descEnum, typeOptions); + + const code = createEnumTypeCode(enumType, registry, options); + + return code.toString(); +} + +type TestCase = { + test: string; + args: { + packageName: TestapisPackage; + enumTypeNameInProto: string; + }; +}; + +type TestSuite = { + suite: string; + options: PothosPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "ts-proto", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a simple enum", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnum", + }, + }, + { + test: "generates code for an enum without unspecified", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnumWithoutUnspecified", + }, + }, + { + test: "generates code for nested enum", + args: { + packageName: "testapis.nested", + enumTypeNameInProto: "ParentMessage.NestedEnum", + }, + }, + { + test: "generates code for enum with extensions", + args: { + packageName: "testapis.extensions", + enumTypeNameInProto: "PrefixedEnum", + }, + }, + ], + }, + { + suite: "protobuf-es", + options: { + dsl: "pothos", + protobuf: "protobuf-es" as const, + importPrefix: "@testapis/protobuf-es", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a simple enum", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnum", + }, + }, + { + test: "generates code for an enum without unspecified", + args: { + packageName: "testapis.enums", + enumTypeNameInProto: "MyEnumWithoutUnspecified", + }, + }, + { + test: "generates code for nested enum", + args: { + packageName: "testapis.nested", + enumTypeNameInProto: "ParentMessage.NestedEnum", + }, + }, + ], + }, +]; + +describe("createEnumTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + const code = generateEnumTypeCode( + args.packageName, + args.enumTypeNameInProto, + options, + ); + expect(code).toMatchSnapshot(); + }); + }); + } +}); diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/inputObjectType.test.ts b/packages/protoc-gen-pothos/src/dslgen/printers/inputObjectType.test.ts new file mode 100644 index 00000000..cff721e4 --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/inputObjectType.test.ts @@ -0,0 +1,202 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + InputObjectType, + type TypeOptions, + defaultScalarMapping, + defaultScalarMappingForTsProto, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createInputObjectTypeCode } from "./inputObjectType.js"; +import type { PothosPrinterOptions } from "./util.js"; + +function generateInputObjectTypeCode( + packageName: TestapisPackage, + typeNameInProto: string, + options: PothosPrinterOptions, + partialInputs = false, +): string { + const typeOptions: TypeOptions = { + partialInputs, + scalarMapping: + options.protobuf === "ts-proto" + ? defaultScalarMappingForTsProto + : defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${typeNameInProto}`); + if (descMsg === undefined) { + throw new Error( + `Message ${typeNameInProto} not found in package ${packageName}`, + ); + } + + const inputType = new InputObjectType(descMsg, typeOptions); + + const code = createInputObjectTypeCode( + partialInputs ? inputType.toPartialInput() : inputType, + registry, + options, + ); + + return code.toString(); +} + +type TestCase = { + test: string; + args: { + packageName: TestapisPackage; + typeNameInProto: string; + partialInputs?: boolean; + }; +}; + +type TestSuite = { + suite: string; + options: PothosPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "ts-proto", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a simple input object", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Primitives", + }, + }, + { + test: "generates code for an input object with nested fields", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Message", + }, + }, + { + test: "generates code for an input object with oneof fields", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + }, + }, + { + test: "generates code for empty input object", + args: { + packageName: "testapis.empty_types", + typeNameInProto: "EmptyMessage", + }, + }, + { + test: "generates code for nested input types", + args: { + packageName: "testapis.nested", + typeNameInProto: "ParentMessage", + }, + }, + ], + }, + { + suite: "protobuf-es", + options: { + dsl: "pothos", + protobuf: "protobuf-es" as const, + importPrefix: "@testapis/protobuf-es", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a simple input object", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Primitives", + }, + }, + { + test: "generates code for an input object with nested fields", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Message", + }, + }, + { + test: "generates code for an input object with oneof fields", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + }, + }, + { + test: "generates code for empty input object", + args: { + packageName: "testapis.empty_types", + typeNameInProto: "EmptyMessage", + }, + }, + ], + }, + { + suite: "with partial inputs", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for partial input types", + args: { + packageName: "testapis.primitives", + typeNameInProto: "Message", + partialInputs: true, + }, + }, + ], + }, +]; + +describe("createInputObjectTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + const code = generateInputObjectTypeCode( + args.packageName, + args.typeNameInProto, + options, + args.partialInputs ?? false, + ); + expect(code).toMatchSnapshot(); + }); + }); + } +}); diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/objectType.test.ts b/packages/protoc-gen-pothos/src/dslgen/printers/objectType.test.ts new file mode 100644 index 00000000..bd6ce02a --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/objectType.test.ts @@ -0,0 +1,187 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + ObjectType, + type TypeOptions, + defaultScalarMapping, + defaultScalarMappingForTsProto, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createObjectTypeCode } from "./objectType.js"; +import type { PothosPrinterOptions } from "./util.js"; + +function generateObjectTypeCode( + packageName: TestapisPackage, + messageTypeName: string, + options: PothosPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: + options.protobuf === "ts-proto" + ? defaultScalarMappingForTsProto + : defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${messageTypeName}`); + if (descMsg === undefined) { + throw new Error( + `Message ${messageTypeName} not found in package ${packageName}`, + ); + } + + const objType = new ObjectType(descMsg, typeOptions); + + const code = createObjectTypeCode(objType, registry, options); + + return code.toString(); +} + +type TestCase = { + test: string; + args: { + packageName: TestapisPackage; + messageTypeName: string; + }; +}; + +type TestSuite = { + suite: string; + options: PothosPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "ts-proto", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a simple message", + args: { + packageName: "testapis.primitives", + messageTypeName: "Primitives", + }, + }, + { + test: "generates code for a message with nested fields", + args: { + packageName: "testapis.primitives", + messageTypeName: "Message", + }, + }, + { + test: "generates code for a message with oneofs", + args: { + packageName: "testapis.oneof", + messageTypeName: "OneofParent", + }, + }, + { + test: "generates code for empty message", + args: { + packageName: "testapis.empty_types", + messageTypeName: "EmptyMessage", + }, + }, + { + test: "generates code for nested types", + args: { + packageName: "testapis.nested", + messageTypeName: "ParentMessage", + }, + }, + ], + }, + { + suite: "protobuf-es", + options: { + dsl: "pothos", + protobuf: "protobuf-es" as const, + importPrefix: "@testapis/protobuf-es", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a simple message", + args: { + packageName: "testapis.primitives", + messageTypeName: "Primitives", + }, + }, + { + test: "generates code for a message with nested fields", + args: { + packageName: "testapis.primitives", + messageTypeName: "Message", + }, + }, + { + test: "generates code for a message with oneofs", + args: { + packageName: "testapis.oneof", + messageTypeName: "OneofParent", + }, + }, + ], + }, + { + suite: "with extensions", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for message with field extensions", + args: { + packageName: "testapis.extensions", + messageTypeName: "PrefixedMessage", + }, + }, + ], + }, +]; + +describe("createObjectTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + const code = generateObjectTypeCode( + args.packageName, + args.messageTypeName, + options, + ); + expect(code).toMatchSnapshot(); + }); + }); + } +}); diff --git a/packages/protoc-gen-pothos/src/dslgen/printers/oneofUnionType.test.ts b/packages/protoc-gen-pothos/src/dslgen/printers/oneofUnionType.test.ts new file mode 100644 index 00000000..18d43764 --- /dev/null +++ b/packages/protoc-gen-pothos/src/dslgen/printers/oneofUnionType.test.ts @@ -0,0 +1,254 @@ +import { createFileRegistry } from "@bufbuild/protobuf"; +import { + OneofUnionType, + SquashedOneofUnionType, + type TypeOptions, + defaultScalarMapping, + defaultScalarMappingForTsProto, +} from "@proto-graphql/codegen-core"; +import { + type TestapisPackage, + getTestapisFileDescriptorSet, +} from "@proto-graphql/testapis-proto"; +import { describe, expect, test } from "vitest"; +import { createOneofUnionTypeCode } from "./oneofUnionType.js"; +import type { PothosPrinterOptions } from "./util.js"; + +function generateOneofUnionTypeCode( + packageName: TestapisPackage, + typeNameInProto: string, + oneofFieldName: string, + options: PothosPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: + options.protobuf === "ts-proto" + ? defaultScalarMappingForTsProto + : defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${typeNameInProto}`); + if (descMsg === undefined) { + throw new Error( + `Message ${typeNameInProto} not found in package ${packageName}`, + ); + } + + const descOneof = descMsg.oneofs.find((d) => d.name === oneofFieldName); + if (descOneof === undefined) { + throw new Error( + `Oneof field ${oneofFieldName} not found in message ${typeNameInProto} in package ${packageName}`, + ); + } + + const oneofType = new OneofUnionType(descOneof, typeOptions); + + const code = createOneofUnionTypeCode( + oneofType, + registry, + options, + ).toString(); + + return code.toString(); +} + +function generateSquashedOneofUnionTypeCode( + packageName: TestapisPackage, + typeNameInProto: string, + options: PothosPrinterOptions, +): string { + const typeOptions: TypeOptions = { + partialInputs: false, + scalarMapping: + options.protobuf === "ts-proto" + ? defaultScalarMappingForTsProto + : defaultScalarMapping, + ignoreNonMessageOneofFields: false, + }; + + const descSet = getTestapisFileDescriptorSet(packageName); + const registry = createFileRegistry(descSet); + const descMsg = registry.getMessage(`${packageName}.${typeNameInProto}`); + if (descMsg === undefined) { + throw new Error( + `Message ${typeNameInProto} not found in package ${packageName}`, + ); + } + + const oneofType = new SquashedOneofUnionType(descMsg, typeOptions); + + const code = createOneofUnionTypeCode( + oneofType, + registry, + options, + ).toString(); + + return code.toString(); +} + +type OneofTestCase = { + test: string; + args: { + packageName: TestapisPackage; + typeNameInProto: string; + oneofFieldName: string; + }; +}; + +type SquashedTestCase = { + test: string; + args: { + packageName: TestapisPackage; + typeNameInProto: string; + }; +}; + +type TestCase = OneofTestCase | SquashedTestCase; + +type TestSuite = { + suite: string; + options: PothosPrinterOptions; + cases: TestCase[]; +}; + +const testSuites: TestSuite[] = [ + { + suite: "ts-proto", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a required oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "required_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for an optional oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "optional_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for a squashed oneof union", + args: { + packageName: "testapis.extensions", + typeNameInProto: "PrefixedMessage.SquashedMessage", + }, + } as SquashedTestCase, + { + test: "generates code for imported oneof member", + args: { + packageName: "testapis.edgecases.import_oneof_member_from_other_file", + typeNameInProto: "OneofParent", + oneofFieldName: "oneof_field", + }, + } as OneofTestCase, + ], + }, + { + suite: "protobuf-es", + options: { + dsl: "pothos", + protobuf: "protobuf-es" as const, + importPrefix: "@testapis/protobuf-es", + emitImportedFiles: false, + fileLayout: "proto_file", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code for a required oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "required_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for an optional oneof union", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "optional_oneof_members", + }, + } as OneofTestCase, + { + test: "generates code for a squashed oneof union", + args: { + packageName: "testapis.extensions", + typeNameInProto: "PrefixedMessage.SquashedMessage", + }, + } as SquashedTestCase, + ], + }, + { + suite: "with file layout graphql_type", + options: { + dsl: "pothos", + protobuf: "ts-proto" as const, + importPrefix: "@testapis/ts-proto", + emitImportedFiles: false, + fileLayout: "graphql_type", + filenameSuffix: ".pothos", + pothos: { + builderPath: "../../builder", + }, + }, + cases: [ + { + test: "generates code with correct imports for graphql_type layout", + args: { + packageName: "testapis.oneof", + typeNameInProto: "OneofParent", + oneofFieldName: "required_oneof_members", + }, + } as OneofTestCase, + ], + }, +]; + +describe("createOneofUnionTypeCode", () => { + for (const { suite, options, cases } of testSuites) { + describe(suite, () => { + test.each(cases)("$test", ({ args }) => { + if ("oneofFieldName" in args) { + const code = generateOneofUnionTypeCode( + args.packageName, + args.typeNameInProto, + args.oneofFieldName, + options, + ); + expect(code).toMatchSnapshot(); + } else { + const code = generateSquashedOneofUnionTypeCode( + args.packageName, + args.typeNameInProto, + options, + ); + expect(code).toMatchSnapshot(); + } + }); + }); + } +});