ts-proto 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.markdown CHANGED
@@ -118,7 +118,7 @@ plugins:
118
118
  path: ../node_modules/ts-proto/protoc-gen-ts_proto
119
119
  ```
120
120
 
121
- To prevent `buf push` from reading irrelevent `.proto` files, configure `buf.yaml` like so:
121
+ To prevent `buf push` from reading irrelevant `.proto` files, configure `buf.yaml` like so:
122
122
 
123
123
  ```yaml
124
124
  build:
@@ -150,7 +150,7 @@ In terms of the code that `ts-proto` generates, the general goals are:
150
150
 
151
151
  - Idiomatic TypeScript/ES6 types
152
152
  - `ts-proto` is a clean break from either the built-in Google/Java-esque JS code of `protoc` or the "make `.d.ts` files the `*.js` comments" approach of `protobufjs`
153
- - (Techically the `protobufjs/minimal` package is used for actually reading/writing bytes.)
153
+ - (Technically the `protobufjs/minimal` package is used for actually reading/writing bytes.)
154
154
  - TypeScript-first output
155
155
  - Interfaces over classes
156
156
  - As much as possible, types are just interfaces, so you can work with messages just like regular hashes/data structures.
@@ -248,7 +248,7 @@ creating a class and calling the right getters/setters.
248
248
 
249
249
  (Note: this is currently only supported by the Twirp clients.)
250
250
 
251
- If you're using ts-proto's clients to call backend micro-services, similar to the N+1 problem in SQL applications, it is easy for micro-service clients to (when serving an individual request) inadvertantly trigger multiple separate RPC calls for "get book 1", "get book 2", "get book 3", that should really be batched into a single "get books [1, 2, 3]" (assuming the backend supports a batch-oriented RPC method).
251
+ If you're using ts-proto's clients to call backend micro-services, similar to the N+1 problem in SQL applications, it is easy for micro-service clients to (when serving an individual request) inadvertently trigger multiple separate RPC calls for "get book 1", "get book 2", "get book 3", that should really be batched into a single "get books [1, 2, 3]" (assuming the backend supports a batch-oriented RPC method).
252
252
 
253
253
  ts-proto can help with this, and essentially auto-batch your individual "get book" calls into batched "get books" calls.
254
254
 
@@ -262,7 +262,7 @@ For ts-proto to do this, you need to implement your service's RPC methods with t
262
262
 
263
263
  When ts-proto recognizes methods of this pattern, it will automatically create a "non-batch" version of `<OperationName>` for the client, i.e. `client.Get<OperationName>`, that takes a single id and returns a single result.
264
264
 
265
- This provides the client code with the illusion that it can make individual `Get<OperationName>` calls (which is generally preferrable/easier when implementing the client's business logic), but the actual implementation that ts-proto provides will end up making `Batch<OperationName>` calls to the backend service.
265
+ This provides the client code with the illusion that it can make individual `Get<OperationName>` calls (which is generally preferable/easier when implementing the client's business logic), but the actual implementation that ts-proto provides will end up making `Batch<OperationName>` calls to the backend service.
266
266
 
267
267
  You also need to enable the `useContext=true` build-time parameter, which gives all client methods a Go-style `ctx` parameter, with a `getDataLoaders` method that lets ts-proto cache/resolve request-scoped [DataLoaders](https://github.com/graphql/dataloader), which provide the fundamental auto-batch detection/flushing behavior.
268
268
 
@@ -325,7 +325,7 @@ Generated code will be placed in the Gradle build directory.
325
325
 
326
326
  The default behavior is `forceLong=number`, which will internally still use the `long` library to encode/decode values on the wire (so you will still see a `util.Long = Long` line in your output), but will convert the `long` values to `number` automatically for you. Note that a runtime error is thrown if, while doing this conversion, a 64-bit value is larger than can be correctly stored as a `number`.
327
327
 
328
- - With `--ts_proto_opt=useJsTypeOverride`, 64-bit numbers will be ouput as the [FieldOption.JSType](https://protobuf.dev/reference/java/api-docs/com/google/protobuf/DescriptorProtos.FieldOptions.JSType) specified on the field. This takes precendence over the `forceLong` option provided.
328
+ - With `--ts_proto_opt=useJsTypeOverride`, 64-bit numbers will be output as the [FieldOption.JSType](https://protobuf.dev/reference/java/api-docs/com/google/protobuf/DescriptorProtos.FieldOptions.JSType) specified on the field. This takes precedence over the `forceLong` option provided.
329
329
 
330
330
  - With `--ts_proto_opt=esModuleInterop=true` changes output to be `esModuleInterop` compliant.
331
331
 
@@ -438,7 +438,7 @@ Generated code will be placed in the Gradle build directory.
438
438
 
439
439
  (Requires `nestJs=true`.)
440
440
 
441
- - With`--ts_proto_opt=addNestjsRestParameter=true`, the last argument of service methods will be an rest parameter with type any. This way you can use custom decorators you could normally use in nestjs.
441
+ - With`--ts_proto_opt=addNestjsRestParameter=true`, the last argument of service methods will be a rest parameter with type any. This way you can use custom decorators you could normally use in nestjs.
442
442
 
443
443
  (Requires `nestJs=true`.)
444
444
 
@@ -476,11 +476,11 @@ Generated code will be placed in the Gradle build directory.
476
476
 
477
477
  - With `--ts_proto_opt=outputServices=false`, or `=none`, ts-proto will output NO service definitions.
478
478
 
479
- - With `--ts_proto_opt=rpcBeforeRequest=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `beforeRequest(service: string, message: string, request: <RequestType>)`. It will will also automatically set `outputServices=default`. Each of the Service's methods will call `beforeRequest` before performing it's request.
479
+ - With `--ts_proto_opt=rpcBeforeRequest=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `beforeRequest(service: string, message: string, request: <RequestType>)`. It will also automatically set `outputServices=default`. Each of the Service's methods will call `beforeRequest` before performing its request.
480
480
 
481
- - With `--ts_proto_opt=rpcAfterResponse=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `afterResponse(service: string, message: string, response: <ResponseType>)`. It will will also automatically set `outputServices=default`. Each of the Service's methods will call `afterResponse` before returning the response.
481
+ - With `--ts_proto_opt=rpcAfterResponse=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `afterResponse(service: string, message: string, response: <ResponseType>)`. It will also automatically set `outputServices=default`. Each of the Service's methods will call `afterResponse` before returning the response.
482
482
 
483
- - With `--ts_proto_opt=rpcErrorHandler=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `handleError(service: string, message: string, error: Error)`. It will will also automatically set `outputServices=default`.
483
+ - With `--ts_proto_opt=rpcErrorHandler=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `handleError(service: string, message: string, error: Error)`. It will also automatically set `outputServices=default`.
484
484
 
485
485
  - With `--ts_proto_opt=useAbortSignal=true`, the generated services will accept an `AbortSignal` to cancel RPC calls.
486
486
 
@@ -522,7 +522,7 @@ Generated code will be placed in the Gradle build directory.
522
522
 
523
523
  - With `--ts_proto_opt=useNumericEnumForJson=true`, the JSON converter (`toJSON`) will encode enum values as int, rather than a string literal.
524
524
 
525
- - With `--ts_proto_opt=initializeFieldsAsUndefined=false`, all optional field initializers will be omited from the generated base instances.
525
+ - With `--ts_proto_opt=initializeFieldsAsUndefined=false`, all optional field initializers will be omitted from the generated base instances.
526
526
 
527
527
  - With `--ts_proto_opt=disableProto2Optionals=true`, all optional fields on proto2 files will not be set to be optional. Please note that this flag is primarily for preserving ts-proto's legacy handling of proto2 files, to avoid breaking changes, and as a result, it is not intended to be used moving forward.
528
528
 
@@ -533,14 +533,14 @@ Generated code will be placed in the Gradle build directory.
533
533
  - `Mfoo/bar.proto=@myorg/some-lib` will map `foo/bar.proto` imports into `import ... from '@myorg/some-lib'`.
534
534
  - `Mfoo/bar.proto=./some/local/lib` will map `foo/bar.proto` imports into `import ... from './some/local/lib'`.
535
535
  - `Mfoo/bar.proto=some-modules/some-lib` will map `foo/bar.proto` imports into `import ... from 'some-module/some-lib'`.
536
- - **Note**: Uses are accummulated, so multiple values are expected in the form of `--ts_proto_opt=M... --ts_proto_opt=M...` (one `ts_proto_opt` per mapping).
536
+ - **Note**: Uses are accumulated, so multiple values are expected in the form of `--ts_proto_opt=M... --ts_proto_opt=M...` (one `ts_proto_opt` per mapping).
537
537
  - **Note**: Proto files that match mapped imports **will not be generated**.
538
538
 
539
539
  - With `--ts_proto_opt=useMapType=true`, the generated code for protobuf `map<key_type, value_type>` will become `Map<key_type, value_type>` that uses JavaScript Map type.
540
540
 
541
541
  The default behavior is `useMapType=false`, which makes it generate the code for protobuf `map<key_type, value_type` with the key-value pair like `{[key: key_type]: value_type}`.
542
542
 
543
- - With `--ts_proto_opt=useReadonlyTypes=true`, the generated types will be declared as immutable using typescript's `readonly` modifer.
543
+ - With `--ts_proto_opt=useReadonlyTypes=true`, the generated types will be declared as immutable using typescript's `readonly` modifier.
544
544
 
545
545
  - With `--ts_proto_opt=useSnakeTypeName=false` will remove snake casing from types.
546
546
 
@@ -633,7 +633,7 @@ export interface User {
633
633
  }
634
634
  ```
635
635
 
636
- - With `--ts_proto_opt=noDefaultsForOptionals=true`, `undefined` primitive values will not be defaulted as per the protobuf spec. Additionally unlike the standard behavior, when a field is set to it's standard default value, it *will* be encoded allowing it to be sent over the wire and distinguished from undefined values. For example if a message does not set a boolean value, ordinarily this would be defaulted to `false` which is different to it being undefined.
636
+ - With `--ts_proto_opt=noDefaultsForOptionals=true`, `undefined` primitive values will not be defaulted as per the protobuf spec. Additionally unlike the standard behavior, when a field is set to its standard default value, it *will* be encoded allowing it to be sent over the wire and distinguished from undefined values. For example if a message does not set a boolean value, ordinarily this would be defaulted to `false` which is different to it being undefined.
637
637
 
638
638
  This option allows the library to act in a compatible way with the [Wire implementation](https://square.github.io/wire/) maintained and used by Square/Block. Note: this option should only be used in combination with other client/server code generated using Wire or ts-proto with this option enabled.
639
639
 
@@ -59,7 +59,7 @@ function generateDecoder(ctx, typeName) {
59
59
  }
60
60
  let TypeValue;
61
61
  if (name == "Timestamp") {
62
- TypeValue = (0, utils_1.impProto)(ctx.options, "google/protobuf/timestamp", name);
62
+ TypeValue = (0, utils_1.impProto)(ctx.options, "google/protobuf/timestamp", options.typePrefix + name + options.typeSuffix);
63
63
  const decoder = (0, ts_poet_1.code) `${TypeValue}.decode(value)`;
64
64
  if (ctx.options.useDate === options_1.DateOption.DATE ||
65
65
  ctx.options.useDate === options_1.DateOption.STRING ||
@@ -225,7 +225,7 @@ function generateServiceClientImpl(ctx, fileDesc, serviceDesc) {
225
225
  chunks.push((0, ts_poet_1.code) `}`);
226
226
  // Create a method for each FooService method
227
227
  for (const methodDesc of serviceDesc.method) {
228
- // See if this this fuzzy matches to a batchable method
228
+ // See if this fuzzy matches to a batchable method
229
229
  if (options.context) {
230
230
  const batchMethod = (0, types_1.detectBatchMethod)(ctx, fileDesc, serviceDesc, methodDesc);
231
231
  if (batchMethod) {
package/build/src/main.js CHANGED
@@ -636,7 +636,7 @@ function makeObjectIdMethods() {
636
636
  return { fromJsonObjectId, fromProtoObjectId, toProtoObjectId };
637
637
  }
638
638
  function makeTimestampMethods(options, longs, bytes) {
639
- const Timestamp = (0, utils_1.impProto)(options, "google/protobuf/timestamp", "Timestamp");
639
+ const Timestamp = (0, utils_1.impProto)(options, "google/protobuf/timestamp", `${options.typePrefix}Timestamp${options.typeSuffix}`);
640
640
  const NanoDate = (0, ts_poet_1.imp)("NanoDate=nano-date");
641
641
  let seconds = "Math.trunc(date.getTime() / 1_000)";
642
642
  let toNumberCode = "t.seconds";
@@ -726,12 +726,12 @@ function makeTimestampMethods(options, longs, bytes) {
726
726
  } else if (typeof o === "string") {
727
727
  return new ${bytes.globalThis}.Date(o);
728
728
  } else {
729
- return ${fromTimestamp}(Timestamp.fromJSON(o));
729
+ return ${fromTimestamp}(${options.typePrefix}Timestamp${options.typeSuffix}.fromJSON(o));
730
730
  }
731
731
  }
732
732
  `
733
733
  : (0, ts_poet_1.code) `
734
- function fromJsonTimestamp(o: any): Timestamp {
734
+ function fromJsonTimestamp(o: any): ${options.typePrefix}Timestamp${options.typeSuffix} {
735
735
  if (o instanceof ${bytes.globalThis}.Date) {
736
736
  return ${toTimestamp}(o);
737
737
  } else if (typeof o === "string") {
@@ -1030,7 +1030,7 @@ function generateDecode(ctx, fullName, messageDesc) {
1030
1030
  messageDesc.field.forEach((field) => {
1031
1031
  const fieldName = (0, utils_1.getFieldName)(field, options);
1032
1032
  const messageProperty = (0, utils_1.getPropertyAccessor)("message", fieldName);
1033
- chunks.push((0, ts_poet_1.code) `case ${field.number}:`);
1033
+ chunks.push((0, ts_poet_1.code) `case ${field.number}: {`);
1034
1034
  const tag = ((field.number << 3) | (0, types_1.basicWireType)(field.type)) >>> 0;
1035
1035
  const tagCheck = (0, ts_poet_1.code) `
1036
1036
  if (tag !== ${tag}) {
@@ -1083,11 +1083,23 @@ function generateDecode(ctx, fullName, messageDesc) {
1083
1083
  }`
1084
1084
  : "";
1085
1085
  if ((0, types_1.packedType)(field.type) === undefined) {
1086
- chunks.push((0, ts_poet_1.code) `
1087
- ${tagCheck}
1088
- ${initializerSnippet}
1089
- ${messageProperty}${maybeNonNullAssertion}.push(${readSnippet});
1090
- `);
1086
+ if (options.useOptionals === "all") {
1087
+ chunks.push((0, ts_poet_1.code) `
1088
+ ${tagCheck}
1089
+ ${initializerSnippet}
1090
+ const el = ${readSnippet};
1091
+ if (el !== undefined) {
1092
+ ${messageProperty}${maybeNonNullAssertion}.push(el);
1093
+ }
1094
+ `);
1095
+ }
1096
+ else {
1097
+ chunks.push((0, ts_poet_1.code) `
1098
+ ${tagCheck}
1099
+ ${initializerSnippet}
1100
+ ${messageProperty}${maybeNonNullAssertion}.push(${readSnippet});
1101
+ `);
1102
+ }
1091
1103
  }
1092
1104
  else {
1093
1105
  const packedTag = ((field.number << 3) | 2) >>> 0;
@@ -1110,7 +1122,7 @@ function generateDecode(ctx, fullName, messageDesc) {
1110
1122
  }
1111
1123
 
1112
1124
  break;
1113
- `);
1125
+ }`);
1114
1126
  }
1115
1127
  }
1116
1128
  }
@@ -1131,7 +1143,7 @@ function generateDecode(ctx, fullName, messageDesc) {
1131
1143
  `);
1132
1144
  }
1133
1145
  if (!(0, types_1.isRepeated)(field) || (0, types_1.packedType)(field.type) === undefined) {
1134
- chunks.push((0, ts_poet_1.code) `continue;`);
1146
+ chunks.push((0, ts_poet_1.code) `continue; }`);
1135
1147
  }
1136
1148
  });
1137
1149
  chunks.push((0, ts_poet_1.code) `}`);
@@ -197,9 +197,9 @@ function encodedOptionsToOptions(ctx, extendee, encodedOptions) {
197
197
  // getExtensionValue is to decode the encoded value into a message, but this
198
198
  // Message.decode(...) method is not always included in the generated code.
199
199
  // We should fix this so that we can always create an option definition by
200
- // somehow premptively decoding the encoded value and then inserting it into
201
- // the option defintion.
202
- // please refer to inteegration/options-types-only to see this in action
200
+ // somehow preemptively decoding the encoded value and then inserting it into
201
+ // the option definition.
202
+ // please refer to integration/options-types-only to see this in action
203
203
  resultOptions.push(getExtensionValue(ctx, extension, value));
204
204
  }
205
205
  }
@@ -69,10 +69,10 @@ export default class SourceInfo implements SourceDescription {
69
69
  get leadingComments(): string;
70
70
  /** Documentation is unclear about what exactly this is */
71
71
  get trailingComments(): string;
72
- /** Detached comments are those preceeding but separated by a blank non-comment line */
72
+ /** Detached comments are those preceding but separated by a blank non-comment line */
73
73
  get leadingDetachedComments(): string[];
74
- /** Return the source info for the field id and index specficied */
74
+ /** Return the source info for the field id and index specified */
75
75
  lookup(type: FieldID, index?: number): SourceDescription;
76
- /** Returns a new SourceInfo class representing the field id and index specficied */
76
+ /** Returns a new SourceInfo class representing the field id and index specified */
77
77
  open(type: FieldID, index: number): SourceInfo;
78
78
  }
@@ -80,18 +80,18 @@ class SourceInfo {
80
80
  get trailingComments() {
81
81
  return this.selfDescription.trailingComments;
82
82
  }
83
- /** Detached comments are those preceeding but separated by a blank non-comment line */
83
+ /** Detached comments are those preceding but separated by a blank non-comment line */
84
84
  get leadingDetachedComments() {
85
85
  return this.selfDescription.leadingDetachedComments;
86
86
  }
87
- /** Return the source info for the field id and index specficied */
87
+ /** Return the source info for the field id and index specified */
88
88
  lookup(type, index) {
89
89
  if (index === undefined) {
90
90
  return this.sourceCode[`${type}`] || new EmptyDescription();
91
91
  }
92
92
  return this.sourceCode[`${type}.${index}`] || new EmptyDescription();
93
93
  }
94
- /** Returns a new SourceInfo class representing the field id and index specficied */
94
+ /** Returns a new SourceInfo class representing the field id and index specified */
95
95
  open(type, index) {
96
96
  const prefix = `${type}.${index}.`;
97
97
  const map = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "",
5
5
  "main": "build/src/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",