Skip to content

Commit

Permalink
feat: add create utility function to message defintions (#760)
Browse files Browse the repository at this point in the history
Similar to `fromPartial` except it allows an empty argument:

 - create() -> {object}
 - create({partial object}) -> {object}

Calls fromPartial internally.

Callers of the library can now use create() instead of fromPartial({}) which,
while functionally equivalent, is much more readable.

Signed-off-by: Christian Stewart <christian@paral.in>

Signed-off-by: Christian Stewart <christian@paral.in>
  • Loading branch information
paralin authored Jan 10, 2023
1 parent ed4266b commit 44fc7b2
Show file tree
Hide file tree
Showing 135 changed files with 1,892 additions and 6 deletions.
12 changes: 8 additions & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ Along with `encode`/`decode` factory methods:

```typescript
export const Simple = {
create(baseObject?: DeepPartial<Simple>): Simple {
...
},
encode(message: Simple, writer: Writer = Writer.create()): Writer {
...
},
Expand Down Expand Up @@ -332,7 +336,7 @@ Generated code will be placed in the Gradle build directory.

So, between typo-prevention, reader inconsistency, and proper initialization, ts-proto recommends using `useOptionals=none` as the "most safe" option.

All that said, this approach does require writers/creators to set every field (although `fromPartial` is meant to address this), so if you still want to have optional fields, you can set `useOptionals=messages` or `useOptionals=all`.
All that said, this approach does require writers/creators to set every field (although `fromPartial` and `create` are meant to address this), so if you still want to have optional fields, you can set `useOptionals=messages` or `useOptionals=all`.

(See [this issue](https://github.com/stephenh/ts-proto/issues/120#issuecomment-678375833) and [this issue](https://github.com/stephenh/ts-proto/issues/397#issuecomment-977259118) for discussions on `useOptional`.)

Expand Down Expand Up @@ -368,7 +372,7 @@ Generated code will be placed in the Gradle build directory.

This is also useful if you want "only types".

- With `--ts_proto_opt=outputPartialMethods=false`, the `Message.fromPartial` methods for accepting partially-formed objects/object literals will not be output.
- With `--ts_proto_opt=outputPartialMethods=false`, the `Message.fromPartial` and `Message.create` methods for accepting partially-formed objects/object literals will not be output.

- With `--ts_proto_opt=stringEnums=true`, the generated enum types will be string-based instead of int-based.

Expand Down Expand Up @@ -433,9 +437,9 @@ Generated code will be placed in the Gradle build directory.

- With `--ts_proto_opt=enumsAsLiterals=true`, the generated enum types will be enum-ish object with `as const`.

- With `--ts_proto_opt=useExactTypes=false`, the generated `fromPartial` method will not use Exact types.
- With `--ts_proto_opt=useExactTypes=false`, the generated `fromPartial` and `create` methods will not use Exact types.

The default behavior is `useExactTypes=true`, which makes `fromPartial` use Exact type for its argument to make TypeScript reject any unknown properties.
The default behavior is `useExactTypes=true`, which makes `fromPartial` and `create` use Exact type for its argument to make TypeScript reject any unknown properties.

- With `--ts_proto_opt=unknownFields=true`, all unknown fields will be parsed and output as arrays of buffers.

Expand Down
4 changes: 4 additions & 0 deletions integration/angular/simple-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export const SimpleMessage = {
return obj;
},

create<I extends Exact<DeepPartial<SimpleMessage>, I>>(base?: I): SimpleMessage {
return SimpleMessage.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<SimpleMessage>, I>>(object: I): SimpleMessage {
const message = createBaseSimpleMessage();
message.numberField = object.numberField ?? 0;
Expand Down
4 changes: 4 additions & 0 deletions integration/async-iterable-services-abort-signal/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export const EchoMsg = {
return obj;
},

create<I extends Exact<DeepPartial<EchoMsg>, I>>(base?: I): EchoMsg {
return EchoMsg.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<EchoMsg>, I>>(object: I): EchoMsg {
const message = createBaseEchoMsg();
message.body = object.body ?? "";
Expand Down
4 changes: 4 additions & 0 deletions integration/async-iterable-services/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export const EchoMsg = {
return obj;
},

create<I extends Exact<DeepPartial<EchoMsg>, I>>(base?: I): EchoMsg {
return EchoMsg.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<EchoMsg>, I>>(object: I): EchoMsg {
const message = createBaseEchoMsg();
message.body = object.body ?? "";
Expand Down
16 changes: 16 additions & 0 deletions integration/avoid-import-conflicts/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ export const Simple = {
return obj;
},

create<I extends Exact<DeepPartial<Simple>, I>>(base?: I): Simple {
return Simple.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Simple>, I>>(object: I): Simple {
const message = createBaseSimple();
message.name = object.name ?? "";
Expand Down Expand Up @@ -180,6 +184,10 @@ export const SimpleEnums = {
return obj;
},

create<I extends Exact<DeepPartial<SimpleEnums>, I>>(base?: I): SimpleEnums {
return SimpleEnums.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<SimpleEnums>, I>>(object: I): SimpleEnums {
const message = createBaseSimpleEnums();
message.localEnum = object.localEnum ?? 0;
Expand Down Expand Up @@ -228,6 +236,10 @@ export const FooServiceCreateRequest = {
return obj;
},

create<I extends Exact<DeepPartial<FooServiceCreateRequest>, I>>(base?: I): FooServiceCreateRequest {
return FooServiceCreateRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<FooServiceCreateRequest>, I>>(object: I): FooServiceCreateRequest {
const message = createBaseFooServiceCreateRequest();
message.kind = object.kind ?? 0;
Expand Down Expand Up @@ -275,6 +287,10 @@ export const FooServiceCreateResponse = {
return obj;
},

create<I extends Exact<DeepPartial<FooServiceCreateResponse>, I>>(base?: I): FooServiceCreateResponse {
return FooServiceCreateResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<FooServiceCreateResponse>, I>>(object: I): FooServiceCreateResponse {
const message = createBaseFooServiceCreateResponse();
message.kind = object.kind ?? 0;
Expand Down
4 changes: 4 additions & 0 deletions integration/avoid-import-conflicts/simple2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ export const Simple = {
return obj;
},

create<I extends Exact<DeepPartial<Simple>, I>>(base?: I): Simple {
return Simple.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Simple>, I>>(object: I): Simple {
const message = createBaseSimple();
message.name = object.name ?? "";
Expand Down
4 changes: 4 additions & 0 deletions integration/barrel-imports/bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export const Bar = {
return obj;
},

create<I extends Exact<DeepPartial<Bar>, I>>(base?: I): Bar {
return Bar.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Bar>, I>>(object: I): Bar {
const message = createBaseBar();
message.name = object.name ?? "";
Expand Down
4 changes: 4 additions & 0 deletions integration/barrel-imports/foo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export const Foo = {
return obj;
},

create<I extends Exact<DeepPartial<Foo>, I>>(base?: I): Foo {
return Foo.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Foo>, I>>(object: I): Foo {
const message = createBaseFoo();
message.name = object.name ?? "";
Expand Down
42 changes: 42 additions & 0 deletions integration/batching-with-context/batching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ export const BatchQueryRequest = {
return obj;
},

create<I extends Exact<DeepPartial<BatchQueryRequest>, I>>(base?: I): BatchQueryRequest {
return BatchQueryRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchQueryRequest>, I>>(object: I): BatchQueryRequest {
const message = createBaseBatchQueryRequest();
message.ids = object.ids?.map((e) => e) || [];
Expand Down Expand Up @@ -141,6 +145,10 @@ export const BatchQueryResponse = {
return obj;
},

create<I extends Exact<DeepPartial<BatchQueryResponse>, I>>(base?: I): BatchQueryResponse {
return BatchQueryResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchQueryResponse>, I>>(object: I): BatchQueryResponse {
const message = createBaseBatchQueryResponse();
message.entities = object.entities?.map((e) => Entity.fromPartial(e)) || [];
Expand Down Expand Up @@ -192,6 +200,10 @@ export const BatchMapQueryRequest = {
return obj;
},

create<I extends Exact<DeepPartial<BatchMapQueryRequest>, I>>(base?: I): BatchMapQueryRequest {
return BatchMapQueryRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchMapQueryRequest>, I>>(object: I): BatchMapQueryRequest {
const message = createBaseBatchMapQueryRequest();
message.ids = object.ids?.map((e) => e) || [];
Expand Down Expand Up @@ -254,6 +266,10 @@ export const BatchMapQueryResponse = {
return obj;
},

create<I extends Exact<DeepPartial<BatchMapQueryResponse>, I>>(base?: I): BatchMapQueryResponse {
return BatchMapQueryResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchMapQueryResponse>, I>>(object: I): BatchMapQueryResponse {
const message = createBaseBatchMapQueryResponse();
message.entities = Object.entries(object.entities ?? {}).reduce<{ [key: string]: Entity }>((acc, [key, value]) => {
Expand Down Expand Up @@ -316,6 +332,12 @@ export const BatchMapQueryResponse_EntitiesEntry = {
return obj;
},

create<I extends Exact<DeepPartial<BatchMapQueryResponse_EntitiesEntry>, I>>(
base?: I,
): BatchMapQueryResponse_EntitiesEntry {
return BatchMapQueryResponse_EntitiesEntry.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchMapQueryResponse_EntitiesEntry>, I>>(
object: I,
): BatchMapQueryResponse_EntitiesEntry {
Expand Down Expand Up @@ -368,6 +390,10 @@ export const GetOnlyMethodRequest = {
return obj;
},

create<I extends Exact<DeepPartial<GetOnlyMethodRequest>, I>>(base?: I): GetOnlyMethodRequest {
return GetOnlyMethodRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<GetOnlyMethodRequest>, I>>(object: I): GetOnlyMethodRequest {
const message = createBaseGetOnlyMethodRequest();
message.id = object.id ?? "";
Expand Down Expand Up @@ -415,6 +441,10 @@ export const GetOnlyMethodResponse = {
return obj;
},

create<I extends Exact<DeepPartial<GetOnlyMethodResponse>, I>>(base?: I): GetOnlyMethodResponse {
return GetOnlyMethodResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<GetOnlyMethodResponse>, I>>(object: I): GetOnlyMethodResponse {
const message = createBaseGetOnlyMethodResponse();
message.entity = (object.entity !== undefined && object.entity !== null)
Expand Down Expand Up @@ -464,6 +494,10 @@ export const WriteMethodRequest = {
return obj;
},

create<I extends Exact<DeepPartial<WriteMethodRequest>, I>>(base?: I): WriteMethodRequest {
return WriteMethodRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<WriteMethodRequest>, I>>(object: I): WriteMethodRequest {
const message = createBaseWriteMethodRequest();
message.id = object.id ?? "";
Expand Down Expand Up @@ -504,6 +538,10 @@ export const WriteMethodResponse = {
return obj;
},

create<I extends Exact<DeepPartial<WriteMethodResponse>, I>>(base?: I): WriteMethodResponse {
return WriteMethodResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<WriteMethodResponse>, I>>(_: I): WriteMethodResponse {
const message = createBaseWriteMethodResponse();
return message;
Expand Down Expand Up @@ -557,6 +595,10 @@ export const Entity = {
return obj;
},

create<I extends Exact<DeepPartial<Entity>, I>>(base?: I): Entity {
return Entity.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Entity>, I>>(object: I): Entity {
const message = createBaseEntity();
message.id = object.id ?? "";
Expand Down
42 changes: 42 additions & 0 deletions integration/batching/batching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export const BatchQueryRequest = {
return obj;
},

create<I extends Exact<DeepPartial<BatchQueryRequest>, I>>(base?: I): BatchQueryRequest {
return BatchQueryRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchQueryRequest>, I>>(object: I): BatchQueryRequest {
const message = createBaseBatchQueryRequest();
message.ids = object.ids?.map((e) => e) || [];
Expand Down Expand Up @@ -139,6 +143,10 @@ export const BatchQueryResponse = {
return obj;
},

create<I extends Exact<DeepPartial<BatchQueryResponse>, I>>(base?: I): BatchQueryResponse {
return BatchQueryResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchQueryResponse>, I>>(object: I): BatchQueryResponse {
const message = createBaseBatchQueryResponse();
message.entities = object.entities?.map((e) => Entity.fromPartial(e)) || [];
Expand Down Expand Up @@ -190,6 +198,10 @@ export const BatchMapQueryRequest = {
return obj;
},

create<I extends Exact<DeepPartial<BatchMapQueryRequest>, I>>(base?: I): BatchMapQueryRequest {
return BatchMapQueryRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchMapQueryRequest>, I>>(object: I): BatchMapQueryRequest {
const message = createBaseBatchMapQueryRequest();
message.ids = object.ids?.map((e) => e) || [];
Expand Down Expand Up @@ -252,6 +264,10 @@ export const BatchMapQueryResponse = {
return obj;
},

create<I extends Exact<DeepPartial<BatchMapQueryResponse>, I>>(base?: I): BatchMapQueryResponse {
return BatchMapQueryResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchMapQueryResponse>, I>>(object: I): BatchMapQueryResponse {
const message = createBaseBatchMapQueryResponse();
message.entities = Object.entries(object.entities ?? {}).reduce<{ [key: string]: Entity }>((acc, [key, value]) => {
Expand Down Expand Up @@ -314,6 +330,12 @@ export const BatchMapQueryResponse_EntitiesEntry = {
return obj;
},

create<I extends Exact<DeepPartial<BatchMapQueryResponse_EntitiesEntry>, I>>(
base?: I,
): BatchMapQueryResponse_EntitiesEntry {
return BatchMapQueryResponse_EntitiesEntry.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<BatchMapQueryResponse_EntitiesEntry>, I>>(
object: I,
): BatchMapQueryResponse_EntitiesEntry {
Expand Down Expand Up @@ -366,6 +388,10 @@ export const GetOnlyMethodRequest = {
return obj;
},

create<I extends Exact<DeepPartial<GetOnlyMethodRequest>, I>>(base?: I): GetOnlyMethodRequest {
return GetOnlyMethodRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<GetOnlyMethodRequest>, I>>(object: I): GetOnlyMethodRequest {
const message = createBaseGetOnlyMethodRequest();
message.id = object.id ?? "";
Expand Down Expand Up @@ -413,6 +439,10 @@ export const GetOnlyMethodResponse = {
return obj;
},

create<I extends Exact<DeepPartial<GetOnlyMethodResponse>, I>>(base?: I): GetOnlyMethodResponse {
return GetOnlyMethodResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<GetOnlyMethodResponse>, I>>(object: I): GetOnlyMethodResponse {
const message = createBaseGetOnlyMethodResponse();
message.entity = (object.entity !== undefined && object.entity !== null)
Expand Down Expand Up @@ -462,6 +492,10 @@ export const WriteMethodRequest = {
return obj;
},

create<I extends Exact<DeepPartial<WriteMethodRequest>, I>>(base?: I): WriteMethodRequest {
return WriteMethodRequest.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<WriteMethodRequest>, I>>(object: I): WriteMethodRequest {
const message = createBaseWriteMethodRequest();
message.id = object.id ?? "";
Expand Down Expand Up @@ -502,6 +536,10 @@ export const WriteMethodResponse = {
return obj;
},

create<I extends Exact<DeepPartial<WriteMethodResponse>, I>>(base?: I): WriteMethodResponse {
return WriteMethodResponse.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<WriteMethodResponse>, I>>(_: I): WriteMethodResponse {
const message = createBaseWriteMethodResponse();
return message;
Expand Down Expand Up @@ -555,6 +593,10 @@ export const Entity = {
return obj;
},

create<I extends Exact<DeepPartial<Entity>, I>>(base?: I): Entity {
return Entity.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Entity>, I>>(object: I): Entity {
const message = createBaseEntity();
message.id = object.id ?? "";
Expand Down
4 changes: 4 additions & 0 deletions integration/bytes-as-base64/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const Message = {
return obj;
},

create<I extends Exact<DeepPartial<Message>, I>>(base?: I): Message {
return Message.fromPartial(base ?? {});
},

fromPartial<I extends Exact<DeepPartial<Message>, I>>(object: I): Message {
const message = createBaseMessage();
message.data = object.data ?? new Uint8Array();
Expand Down
Loading

0 comments on commit 44fc7b2

Please sign in to comment.