Skip to content

Commit

Permalink
feat: omit optional fields in base instance (#669)
Browse files Browse the repository at this point in the history
* feat: option to disable optional generation in base instance

* feat: updated test bins

* feat: option rename

* feat: fixed test

* Revert "feat: updated test bins"

This reverts commit bd96bdc.

* feat: option rename & README

* feat: added integration test

* Re-codegen.

Co-authored-by: Bence Nagygyörgy <robot9706@gmail.com>
  • Loading branch information
stephenh and robot9706 committed Sep 3, 2022
1 parent 562f73b commit 47b60aa
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,8 @@ Generated code will be placed in the Gradle build directory.

- With `--ts_proto_opt=useNumericEnumForJson=true`, the JSON converter (`toJSON`) will encode enum values as int, rather than a string literal.

- With `--ts_proto_opt=initializeFieldsAsUndefined=false`, all optional field initializers will be omited from the generated base instances.

### NestJS Support

We have a great way of working together with [nestjs](https://docs.nestjs.com/microservices/grpc). `ts-proto` generates `interfaces` and `decorators` for you controller, client. For more information see the [nestjs readme](NESTJS.markdown).
Expand Down
1 change: 1 addition & 0 deletions integration/omit-optionals/parameters.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
initializeFieldsAsUndefined=false
Binary file added integration/omit-optionals/simple.bin
Binary file not shown.
8 changes: 8 additions & 0 deletions integration/omit-optionals/simple.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
syntax = "proto3";

package omit;

message TestMessage {
bool field1 = 1;
optional bool field2 = 2;
}
82 changes: 82 additions & 0 deletions integration/omit-optionals/simple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* eslint-disable */
import * as _m0 from "protobufjs/minimal";

export const protobufPackage = "omit";

export interface TestMessage {
field1: boolean;
field2?: boolean | undefined;
}

function createBaseTestMessage(): TestMessage {
return { field1: false };
}

export const TestMessage = {
encode(message: TestMessage, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
if (message.field1 === true) {
writer.uint32(8).bool(message.field1);
}
if (message.field2 !== undefined) {
writer.uint32(16).bool(message.field2);
}
return writer;
},

decode(input: _m0.Reader | Uint8Array, length?: number): TestMessage {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseTestMessage();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.field1 = reader.bool();
break;
case 2:
message.field2 = reader.bool();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},

fromJSON(object: any): TestMessage {
return {
field1: isSet(object.field1) ? Boolean(object.field1) : false,
field2: isSet(object.field2) ? Boolean(object.field2) : undefined,
};
},

toJSON(message: TestMessage): unknown {
const obj: any = {};
message.field1 !== undefined && (obj.field1 = message.field1);
message.field2 !== undefined && (obj.field2 = message.field2);
return obj;
},

fromPartial<I extends Exact<DeepPartial<TestMessage>, I>>(object: I): TestMessage {
const message = createBaseTestMessage();
message.field1 = object.field1 ?? false;
message.field2 = object.field2 ?? undefined;
return message;
},
};

type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;

export type DeepPartial<T> = T extends Builtin ? T
: T extends Array<infer U> ? Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };

function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
5 changes: 5 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ function generateBaseInstanceFactory(
messageDesc: DescriptorProto,
fullTypeName: string
): Code {
const { options } = ctx;
const fields: Code[] = [];

// When oneof=unions, we generate a single property with an ADT per `oneof` clause.
Expand All @@ -799,6 +800,10 @@ function generateBaseInstanceFactory(
continue;
}

if (!options.initializeFieldsAsUndefined && isOptionalProperty(field, messageDesc.options, options)) {
continue;
}

const name = maybeSnakeToCamel(field.name, ctx.options);
const val = isWithinOneOf(field)
? "undefined"
Expand Down
6 changes: 6 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export type Options = {
usePrototypeForDefaults: boolean;
useJsonWireFormat: boolean;
useNumericEnumForJson: boolean;
initializeFieldsAsUndefined: boolean;
};

export function defaultOptions(): Options {
Expand Down Expand Up @@ -111,6 +112,7 @@ export function defaultOptions(): Options {
usePrototypeForDefaults: false,
useJsonWireFormat: false,
useNumericEnumForJson: false,
initializeFieldsAsUndefined: true,
};
}

Expand Down Expand Up @@ -193,6 +195,10 @@ export function optionsFromParameter(parameter: string | undefined): Options {
}
}

if (options.nestJs) {
options.initializeFieldsAsUndefined = false;
}

return options;
}

Expand Down
1 change: 1 addition & 0 deletions tests/options-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe("options", () => {
"fileSuffix": "",
"forceLong": "number",
"importSuffix": "",
"initializeFieldsAsUndefined": false,
"lowerCaseServiceMethods": true,
"metadataType": undefined,
"nestJs": true,
Expand Down

0 comments on commit 47b60aa

Please sign in to comment.