ts-proto 2.15.3 → 2.17.0

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
@@ -569,6 +569,8 @@ With `--ts_proto_opt=protoJsonFormat=false`, strict proto3 compliance is disable
569
569
 
570
570
  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}`.
571
571
 
572
+ - With `--ts_proto_opt=useUnknownForValue=true`, `google.protobuf.Value` fields are typed as `unknown` instead of `any`, and so are the items of `google.protobuf.ListValue` and the values of `google.protobuf.Struct`. This makes TypeScript ask you to narrow the value before using it.
573
+
572
574
  - With `--ts_proto_opt=useReadonlyTypes=true`, the generated types will be declared as immutable using typescript's `readonly` modifier.
573
575
 
574
576
  - With `--ts_proto_opt=useSnakeTypeName=false` will remove snake casing from types.
@@ -612,6 +614,8 @@ With `--ts_proto_opt=protoJsonFormat=false`, strict proto3 compliance is disable
612
614
 
613
615
  - With `--ts_proto_opt=typeSuffix=MySuffix`, the generated interfaces, enums, and factories will have a suffix of `MySuffix` in their names.
614
616
 
617
+ - With `--ts_proto_opt=messagePrefix=MyPrefix` / `messageSuffix=MySuffix`, only the generated message interfaces and factories get the prefix/suffix, and with `enumPrefix=MyPrefix` / `enumSuffix=MySuffix` only the enums do. They are added inside `typePrefix`/`typeSuffix` when both are set, e.g. `typePrefix=T,messagePrefix=M` gives `TMFoo`.
618
+
615
619
  ```protobuf
616
620
  message ProfileInfo {
617
621
  int32 id = 1;
@@ -48,7 +48,7 @@ function generateWrapDeep(ctx, fullProtoTypeName, fieldNames) {
48
48
  chunks.push((0, ts_poet_1.code) `wrap(value: any): ${(0, utils_1.wrapTypeName)(ctx.options, "Value")} {
49
49
  const result = {} as any;
50
50
  if (value === null) {
51
- result.${fieldNames.nullValue} = ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue")}.NULL_VALUE;
51
+ result.${fieldNames.nullValue} = ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue", "enum")}.NULL_VALUE;
52
52
  } else if (typeof value === 'boolean') {
53
53
  result.${fieldNames.boolValue} = value;
54
54
  } else if (typeof value === 'number') {
@@ -180,7 +180,7 @@ function generateWrapShallow(ctx, fullProtoTypeName, fieldNames) {
180
180
  chunks.push((0, ts_poet_1.code) `wrap(value: any): ${(0, utils_1.wrapTypeName)(ctx.options, "Value")} {
181
181
  const result = createBase${(0, utils_1.wrapTypeName)(ctx.options, "Value")}()${maybeAsAny(ctx.options)};
182
182
  if (value === null) {
183
- result.kind = {$case: '${fieldNames.nullValue}', ${fieldNames.nullValue}: ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue")}.NULL_VALUE};
183
+ result.kind = {$case: '${fieldNames.nullValue}', ${fieldNames.nullValue}: ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue", "enum")}.NULL_VALUE};
184
184
  } else if (typeof value === 'boolean') {
185
185
  result.kind = {$case: '${fieldNames.boolValue}', ${fieldNames.boolValue}: value};
186
186
  } else if (typeof value === 'number') {
@@ -201,7 +201,7 @@ function generateWrapShallow(ctx, fullProtoTypeName, fieldNames) {
201
201
  chunks.push((0, ts_poet_1.code) `wrap(value: any): ${(0, utils_1.wrapTypeName)(ctx.options, "Value")} {
202
202
  const result = createBase${(0, utils_1.wrapTypeName)(ctx.options, "Value")}()${maybeAsAny(ctx.options)};
203
203
  if (value === null) {
204
- result.kind = {$case: '${fieldNames.nullValue}', value: ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue")}.NULL_VALUE};
204
+ result.kind = {$case: '${fieldNames.nullValue}', value: ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue", "enum")}.NULL_VALUE};
205
205
  } else if (typeof value === 'boolean') {
206
206
  result.kind = {$case: '${fieldNames.boolValue}', value };
207
207
  } else if (typeof value === 'number') {
@@ -222,7 +222,7 @@ function generateWrapShallow(ctx, fullProtoTypeName, fieldNames) {
222
222
  chunks.push((0, ts_poet_1.code) `wrap(value: any): ${(0, utils_1.wrapTypeName)(ctx.options, "Value")} {
223
223
  const result = createBase${(0, utils_1.wrapTypeName)(ctx.options, "Value")}()${maybeAsAny(ctx.options)};
224
224
  if (value === null) {
225
- result.${fieldNames.nullValue} = ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue")}.NULL_VALUE;
225
+ result.${fieldNames.nullValue} = ${(0, utils_1.wrapTypeName)(ctx.options, "NullValue", "enum")}.NULL_VALUE;
226
226
  } else if (typeof value === 'boolean') {
227
227
  result.${fieldNames.boolValue} = value;
228
228
  } else if (typeof value === 'number') {
package/build/src/main.js CHANGED
@@ -506,6 +506,9 @@ function makeDeepPartial(options, longs) {
506
506
  const maybeLong = options.forceLong === options_1.LongOption.LONG ? (0, ts_poet_1.code) ` : T extends ${longs.Long} ? string | number | Long ` : "";
507
507
  // Allow passing bigints as numbers or strings; fromPartial coerces them via BigInt()
508
508
  const maybeBigInt = options.forceLong === options_1.LongOption.BIGINT ? (0, ts_poet_1.code) `T extends bigint ? string | number | bigint : ` : "";
509
+ // Keep `unknown` (useUnknownForValue) as is; mapping over it would turn it into `{}`
510
+ const maybeUnknownT = options.useUnknownForValue ? "unknown extends T ? T : " : "";
511
+ const maybeUnknownP = options.useUnknownForValue ? "unknown extends P ? P : " : "";
509
512
  const optionalBuiltins = [];
510
513
  if (options.forceLong === options_1.LongOption.BIGINT) {
511
514
  optionalBuiltins.push("bigint");
@@ -518,7 +521,7 @@ function makeDeepPartial(options, longs) {
518
521
  const maybeExcludeType = (0, options_1.addTypeToMessages)(options) ? `| '$type'` : "";
519
522
  const Exact = (0, ts_poet_1.conditionalOutput)("Exact", (0, ts_poet_1.code) `
520
523
  type KeysOfUnion<T> = T extends T ? keyof T : never;
521
- ${maybeExport} type Exact<P, I extends P> = P extends ${Builtin}
524
+ ${maybeExport} type Exact<P, I extends P> = ${maybeUnknownP}P extends ${Builtin}
522
525
  ? P
523
526
  : P &
524
527
  { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P> ${maybeExcludeType}>]: never };
@@ -526,7 +529,7 @@ function makeDeepPartial(options, longs) {
526
529
  // Based on the type from ts-essentials
527
530
  const keys = (0, options_1.addTypeToMessages)(options) ? (0, ts_poet_1.code) `Exclude<keyof T, '$type'>` : (0, ts_poet_1.code) `keyof T`;
528
531
  const DeepPartial = (0, ts_poet_1.conditionalOutput)("DeepPartial", (0, ts_poet_1.code) `
529
- ${maybeExport} type DeepPartial<T> = ${maybeBigInt} T extends ${Builtin}
532
+ ${maybeExport} type DeepPartial<T> = ${maybeUnknownT}${maybeBigInt} T extends ${Builtin}
530
533
  ? T
531
534
  ${maybeLong}
532
535
  : T extends globalThis.Array<infer U>
@@ -103,6 +103,7 @@ export type Options = {
103
103
  initializeFieldsAsUndefined: boolean;
104
104
  useMapType: boolean;
105
105
  useReadonlyTypes: boolean;
106
+ useUnknownForValue: boolean;
106
107
  useSnakeTypeName: boolean;
107
108
  outputExtensions: boolean;
108
109
  outputIndex: boolean;
@@ -121,6 +122,10 @@ export type Options = {
121
122
  bigIntLiteral: boolean;
122
123
  typePrefix: string;
123
124
  typeSuffix: string;
125
+ messagePrefix: string;
126
+ messageSuffix: string;
127
+ enumPrefix: string;
128
+ enumSuffix: string;
124
129
  useDuration: DurationOption;
125
130
  anyType: AnyTypeOption;
126
131
  };
@@ -119,6 +119,7 @@ function defaultOptions() {
119
119
  initializeFieldsAsUndefined: true,
120
120
  useMapType: false,
121
121
  useReadonlyTypes: false,
122
+ useUnknownForValue: false,
122
123
  useSnakeTypeName: true,
123
124
  outputExtensions: false,
124
125
  outputIndex: false,
@@ -135,6 +136,10 @@ function defaultOptions() {
135
136
  bigIntLiteral: true,
136
137
  typePrefix: "",
137
138
  typeSuffix: "",
139
+ messagePrefix: "",
140
+ messageSuffix: "",
141
+ enumPrefix: "",
142
+ enumSuffix: "",
138
143
  useDuration: DurationOption.DURATION,
139
144
  anyType: AnyTypeOption.AT_TYPE,
140
145
  };
@@ -542,12 +542,16 @@ function valueTypeName(ctx, typeName) {
542
542
  : ctx.options.useJsonWireFormat
543
543
  ? (0, ts_poet_1.code) `string`
544
544
  : (0, ts_poet_1.code) `Uint8Array`;
545
- case ".google.protobuf.ListValue":
546
- return ctx.options.useReadonlyTypes ? (0, ts_poet_1.code) `ReadonlyArray<any>` : (0, ts_poet_1.code) `Array<any>`;
545
+ case ".google.protobuf.ListValue": {
546
+ const item = ctx.options.useUnknownForValue ? "unknown" : "any";
547
+ return ctx.options.useReadonlyTypes ? (0, ts_poet_1.code) `ReadonlyArray<${item}>` : (0, ts_poet_1.code) `Array<${item}>`;
548
+ }
547
549
  case ".google.protobuf.Value":
548
- return (0, ts_poet_1.code) `any`;
549
- case ".google.protobuf.Struct":
550
- return ctx.options.useReadonlyTypes ? (0, ts_poet_1.code) `{readonly [key: string]: any}` : (0, ts_poet_1.code) `{[key: string]: any}`;
550
+ return ctx.options.useUnknownForValue ? (0, ts_poet_1.code) `unknown` : (0, ts_poet_1.code) `any`;
551
+ case ".google.protobuf.Struct": {
552
+ const item = ctx.options.useUnknownForValue ? "unknown" : "any";
553
+ return ctx.options.useReadonlyTypes ? (0, ts_poet_1.code) `{readonly [key: string]: ${item}}` : (0, ts_poet_1.code) `{[key: string]: ${item}}`;
554
+ }
551
555
  case ".google.protobuf.FieldMask":
552
556
  return ctx.options.useJsonWireFormat
553
557
  ? (0, ts_poet_1.code) `string`
@@ -80,4 +80,4 @@ export declare function getVersions(request: CodeGeneratorRequest): Promise<{
80
80
  protocVersion: string;
81
81
  tsProtoVersion: string;
82
82
  }>;
83
- export declare function wrapTypeName(options: Options, name: string): string;
83
+ export declare function wrapTypeName(options: Options, name: string, kind?: "message" | "enum"): string;
@@ -308,6 +308,7 @@ async function readPackageJson() {
308
308
  return await Promise.resolve(`${"../package.json"}`).then(s => require(s));
309
309
  }
310
310
  }
311
- function wrapTypeName(options, name) {
312
- return options.typePrefix + name + options.typeSuffix;
311
+ function wrapTypeName(options, name, kind = "message") {
312
+ const [prefix, suffix] = kind === "enum" ? [options.enumPrefix, options.enumSuffix] : [options.messagePrefix, options.messageSuffix];
313
+ return options.typePrefix + prefix + name + suffix + options.typeSuffix;
313
314
  }
@@ -13,7 +13,7 @@ function visit(proto, sourceInfo, messageFn, options, enumFn = () => { }, tsPref
13
13
  const protoFullName = protoPrefix + enumDesc.name;
14
14
  // I.e. FooBar_ZazInner
15
15
  const tsFullName = tsPrefix + (0, case_1.maybeSnakeToCamel)(enumDesc.name, options);
16
- const tsFullNameWithAffixes = messageName((0, utils_1.wrapTypeName)(options, tsFullName));
16
+ const tsFullNameWithAffixes = messageName((0, utils_1.wrapTypeName)(options, tsFullName, "enum"));
17
17
  const nestedSourceInfo = sourceInfo.open(childEnumType, index);
18
18
  enumFn(tsFullNameWithAffixes, enumDesc, nestedSourceInfo, protoFullName);
19
19
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "2.15.3",
3
+ "version": "2.17.0",
4
4
  "description": "",
5
5
  "main": "build/src/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",