ts-proto 1.151.1 → 1.152.1

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.
@@ -227,17 +227,16 @@ function createPromiseUnaryMethod(ctx) {
227
227
  ${useAbortSignal ? "abortSignal?: AbortSignal," : ""}
228
228
  ): Promise<any> {
229
229
  const request = { ..._request, ...methodDesc.requestType };
230
- const maybeCombinedMetadata =
231
- metadata && this.options.metadata
232
- ? new ${BrowserHeaders}({ ...this.options?.metadata.headersMap, ...metadata?.headersMap })
233
- : metadata || this.options.metadata;
230
+ const maybeCombinedMetadata = metadata && this.options.metadata
231
+ ? new ${BrowserHeaders}({ ...this.options?.metadata.headersMap, ...metadata?.headersMap })
232
+ : metadata ?? this.options.metadata;
234
233
  return new Promise((resolve, reject) => {
235
234
  ${useAbortSignal ? `const client =` : ""} ${grpc}.unary(methodDesc, {
236
235
  request,
237
236
  host: this.host,
238
- metadata: maybeCombinedMetadata,
239
- transport: this.options.transport,
240
- debug: this.options.debug,
237
+ metadata: maybeCombinedMetadata ?? {},
238
+ ...(this.options.transport !== undefined ? {transport: this.options.transport} : {}),
239
+ debug: this.options.debug ?? false,
241
240
  onEnd: function (response) {
242
241
  if (response.status === grpc.Code.OK) {
243
242
  resolve(response.message!.toObject());
@@ -271,17 +270,16 @@ function createObservableUnaryMethod(ctx) {
271
270
  ${useAbortSignal ? "abortSignal?: AbortSignal," : ""}
272
271
  ): ${(0, types_1.observableType)(ctx)}<any> {
273
272
  const request = { ..._request, ...methodDesc.requestType };
274
- const maybeCombinedMetadata =
275
- metadata && this.options.metadata
276
- ? new ${BrowserHeaders}({ ...this.options?.metadata.headersMap, ...metadata?.headersMap })
277
- : metadata || this.options.metadata;
273
+ const maybeCombinedMetadata = metadata && this.options.metadata
274
+ ? new ${BrowserHeaders}({ ...this.options?.metadata.headersMap, ...metadata?.headersMap })
275
+ : metadata ?? this.options.metadata;
278
276
  return new Observable(observer => {
279
277
  ${useAbortSignal ? `const client =` : ""} ${grpc}.unary(methodDesc, {
280
278
  request,
281
279
  host: this.host,
282
- metadata: maybeCombinedMetadata,
283
- transport: this.options.transport,
284
- debug: this.options.debug,
280
+ metadata: maybeCombinedMetadata ?? {},
281
+ ...(this.options.transport !== undefined ? {transport: this.options.transport} : {}),
282
+ debug: this.options.debug ?? false,
285
283
  onEnd: (next) => {
286
284
  if (next.status !== 0) {
287
285
  const err = new ${ctx.utils.GrpcWebError}(next.statusMessage, next.status, next.trailers);
@@ -317,21 +315,21 @@ function createInvokeMethod(ctx) {
317
315
  metadata: grpc.Metadata | undefined,
318
316
  ${useAbortSignal ? "abortSignal?: AbortSignal," : ""}
319
317
  ): ${(0, types_1.observableType)(ctx)}<any> {
320
- const upStreamCodes = this.options.upStreamRetryCodes || [];
318
+ const upStreamCodes = this.options.upStreamRetryCodes ?? [];
321
319
  const DEFAULT_TIMEOUT_TIME: number = 3_000;
322
320
  const request = { ..._request, ...methodDesc.requestType };
323
- const maybeCombinedMetadata =
324
- metadata && this.options.metadata
321
+ const transport = this.options.streamingTransport ?? this.options.transport;
322
+ const maybeCombinedMetadata = metadata && this.options.metadata
325
323
  ? new ${BrowserHeaders}({ ...this.options?.metadata.headersMap, ...metadata?.headersMap })
326
- : metadata || this.options.metadata;
324
+ : metadata ?? this.options.metadata;
327
325
  return new Observable(observer => {
328
326
  const upStream = (() => {
329
327
  const client = ${grpc}.invoke(methodDesc, {
330
328
  host: this.host,
331
329
  request,
332
- transport: this.options.streamingTransport || this.options.transport,
333
- metadata: maybeCombinedMetadata,
334
- debug: this.options.debug,
330
+ ...(transport !== undefined ? {transport} : {}),
331
+ metadata: maybeCombinedMetadata ?? {},
332
+ debug: this.options.debug ?? false,
335
333
  onMessage: (next) => observer.next(next),
336
334
  onEnd: (code: ${grpc}.Code, message: string, trailers: ${grpc}.Metadata) => {
337
335
  if (code === 0) {
@@ -206,7 +206,7 @@ function generateBatchingRpcMethod(ctx, batchMethod) {
206
206
  // If the return type is a map, lookup each key in the result
207
207
  lambda.push((0, ts_poet_1.code) `
208
208
  return this.${methodDesc.formattedName}(ctx, request).then(res => {
209
- return ${inputFieldName}.map(key => res.${outputFieldName}[key])
209
+ return ${inputFieldName}.map(key => res.${outputFieldName}[key] ?? ${ctx.utils.fail}())
210
210
  });
211
211
  `);
212
212
  }
package/build/main.js CHANGED
@@ -279,6 +279,7 @@ function makeUtils(options) {
279
279
  ...makeNiceGrpcServerStreamingMethodResult(),
280
280
  ...makeGrpcWebErrorClass(bytes),
281
281
  ...makeExtensionClass(options),
282
+ ...makeAssertionUtils(),
282
283
  };
283
284
  }
284
285
  exports.makeUtils = makeUtils;
@@ -365,10 +366,10 @@ function makeLongUtils(options, bytes) {
365
366
  }
366
367
  function makeByteUtils() {
367
368
  const globalThis = (0, ts_poet_1.conditionalOutput)("tsProtoGlobalThis", (0, ts_poet_1.code) `
368
- declare var self: any | undefined;
369
- declare var window: any | undefined;
370
- declare var global: any | undefined;
371
- var tsProtoGlobalThis: any = (() => {
369
+ declare const self: any | undefined;
370
+ declare const window: any | undefined;
371
+ declare const global: any | undefined;
372
+ const tsProtoGlobalThis: any = (() => {
372
373
  if (typeof globalThis !== "undefined") return globalThis;
373
374
  if (typeof self !== "undefined") return self;
374
375
  if (typeof window !== "undefined") return window;
@@ -589,6 +590,14 @@ function makeExtensionClass(options) {
589
590
  `);
590
591
  return { Extension };
591
592
  }
593
+ function makeAssertionUtils() {
594
+ const fail = (0, ts_poet_1.conditionalOutput)("fail", (0, ts_poet_1.code) `
595
+ function fail(message?: string): never {
596
+ throw new Error(message ?? "Failed");
597
+ }
598
+ `);
599
+ return { fail };
600
+ }
592
601
  // Create the interface with properties
593
602
  function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
594
603
  var _a;
@@ -615,12 +624,15 @@ function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fu
615
624
  const info = sourceInfo.lookup(sourceInfo_1.Fields.message.field, index);
616
625
  (0, utils_1.maybeAddComment)(info, chunks, (_a = fieldDesc.options) === null || _a === void 0 ? void 0 : _a.deprecated);
617
626
  const name = (0, case_1.maybeSnakeToCamel)(fieldDesc.name, options);
618
- const type = (0, types_1.toTypeName)(ctx, messageDesc, fieldDesc);
619
- const q = (0, types_1.isOptionalProperty)(fieldDesc, messageDesc.options, options) ? "?" : "";
620
- chunks.push((0, ts_poet_1.code) `${maybeReadonly(options)}${name}${q}: ${type}, `);
627
+ const isOptional = (0, types_1.isOptionalProperty)(fieldDesc, messageDesc.options, options);
628
+ const type = (0, types_1.toTypeName)(ctx, messageDesc, fieldDesc, isOptional);
629
+ if (isOptional && !type.toString().includes("undefined")) {
630
+ console.warn(name, type);
631
+ }
632
+ chunks.push((0, ts_poet_1.code) `${maybeReadonly(options)}${name}${isOptional ? "?" : ""}: ${type}, `);
621
633
  });
622
634
  if (ctx.options.unknownFields) {
623
- chunks.push((0, ts_poet_1.code) `_unknownFields?: {[key: number]: Uint8Array[]},`);
635
+ chunks.push((0, ts_poet_1.code) `_unknownFields?: {[key: number]: Uint8Array[]} | undefined,`);
624
636
  }
625
637
  chunks.push((0, ts_poet_1.code) `}`);
626
638
  return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
@@ -635,7 +647,7 @@ function generateOneofProperty(ctx, messageDesc, oneofIndex, sourceInfo) {
635
647
  return (0, ts_poet_1.code) `{ ${mbReadonly}$case: '${fieldName}', ${mbReadonly}${fieldName}: ${typeName} }`;
636
648
  }), { on: " | " });
637
649
  const name = (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[oneofIndex].name, options);
638
- return (0, ts_poet_1.code) `${mbReadonly}${name}?: ${unionType},`;
650
+ return (0, ts_poet_1.code) `${mbReadonly}${name}?: ${unionType} | undefined,`;
639
651
  /*
640
652
  // Ideally we'd put the comments for each oneof field next to the anonymous
641
653
  // type we've created in the type union above, but ts-poet currently lacks
@@ -1135,8 +1147,7 @@ function generateEncode(ctx, fullName, messageDesc) {
1135
1147
  });
1136
1148
  if (options.unknownFields) {
1137
1149
  chunks.push((0, ts_poet_1.code) `if (message._unknownFields !== undefined) {
1138
- for (const key in message._unknownFields) {
1139
- const values = message._unknownFields[key];
1150
+ for (const [key, values] of Object.entries(message._unknownFields)) {
1140
1151
  const tag = parseInt(key, 10);
1141
1152
  for (const value of values) {
1142
1153
  writer.uint32(tag);
@@ -1330,7 +1341,7 @@ function generateExtension(ctx, message, extension) {
1330
1341
  chunks.push((0, ts_poet_1.code) `const values: ${type} = [];`);
1331
1342
  // start loop over all buffers
1332
1343
  chunks.push((0, ts_poet_1.code) `
1333
- for (var buffer of input) {
1344
+ for (const buffer of input) {
1334
1345
  const reader = ${Reader}.create(buffer);
1335
1346
  `);
1336
1347
  if ((0, types_1.packedType)(extension.type) === undefined) {
@@ -1360,7 +1371,7 @@ function generateExtension(ctx, message, extension) {
1360
1371
  else {
1361
1372
  // pick the last entry, since it overrides all previous entries if not repeated
1362
1373
  chunks.push((0, ts_poet_1.code) `
1363
- const reader = ${Reader}.create(input[input.length -1]);
1374
+ const reader = ${Reader}.create(input[input.length -1] ?? ${ctx.utils.fail}());
1364
1375
  return ${readSnippet};
1365
1376
  },
1366
1377
  `);
package/build/types.js CHANGED
@@ -531,19 +531,15 @@ function longTypeName(ctx) {
531
531
  }
532
532
  /** Maps `.some_proto_namespace.Message` to a TypeName. */
533
533
  function messageToTypeName(ctx, protoType, typeOptions = {}) {
534
+ var _a;
534
535
  const { options, typeMap } = ctx;
535
536
  // Watch for the wrapper types `.google.protobuf.*Value`. If we're mapping
536
537
  // them to basic built-in types, we union the type with undefined to
537
538
  // indicate the value is optional. Exceptions:
538
539
  // - If the field is repeated, values cannot be undefined.
539
- // - If useOptionals='messages' or useOptionals='all', all non-scalar types
540
- // are already optional properties, so there's no need for that union.
541
540
  let valueType = valueTypeName(ctx, protoType);
542
541
  if (!typeOptions.keepValueType && valueType) {
543
- if (!!typeOptions.repeated ||
544
- options.useOptionals === true ||
545
- options.useOptionals === "messages" ||
546
- options.useOptionals === "all") {
542
+ if ((_a = typeOptions.repeated) !== null && _a !== void 0 ? _a : false) {
547
543
  return valueType;
548
544
  }
549
545
  return (0, ts_poet_1.code) `${valueType} | undefined`;
@@ -575,26 +571,32 @@ function getEnumMethod(ctx, enumProtoType, methodSuffix) {
575
571
  }
576
572
  exports.getEnumMethod = getEnumMethod;
577
573
  /** Return the TypeName for any field (primitive/message/etc.) as exposed in the interface. */
578
- function toTypeName(ctx, messageDesc, field) {
574
+ function toTypeName(ctx, messageDesc, field, ensureOptional = false) {
575
+ function finalize(type, isOptional) {
576
+ if (isOptional) {
577
+ return (0, ts_poet_1.code) `${type} | undefined`;
578
+ }
579
+ return type;
580
+ }
579
581
  let type = basicTypeName(ctx, field, { keepValueType: false });
580
582
  if (isRepeated(field)) {
581
583
  const mapType = messageDesc ? detectMapType(ctx, messageDesc, field) : false;
582
584
  if (mapType) {
583
585
  const { keyType, valueType } = mapType;
584
586
  if (ctx.options.useMapType) {
585
- return (0, ts_poet_1.code) `Map<${keyType}, ${valueType}>`;
587
+ return finalize((0, ts_poet_1.code) `Map<${keyType}, ${valueType}>`, ensureOptional);
586
588
  }
587
- return (0, ts_poet_1.code) `{ [key: ${keyType} ]: ${valueType} }`;
589
+ return finalize((0, ts_poet_1.code) `{ [key: ${keyType} ]: ${valueType} }`, ensureOptional);
588
590
  }
589
591
  if (ctx.options.useReadonlyTypes) {
590
- return (0, ts_poet_1.code) `readonly ${type}[]`;
592
+ return finalize((0, ts_poet_1.code) `readonly ${type}[]`, ensureOptional);
591
593
  }
592
- return (0, ts_poet_1.code) `${type}[]`;
594
+ return finalize((0, ts_poet_1.code) `${type}[]`, ensureOptional);
593
595
  }
594
596
  if (isValueType(ctx, field)) {
595
597
  // google.protobuf.*Value types are already unioned with `undefined`
596
598
  // in messageToTypeName, so no need to consider them for that here.
597
- return type;
599
+ return finalize(type, false);
598
600
  }
599
601
  // By default (useOptionals='none', oneof=properties), non-scalar fields
600
602
  // outside oneofs and all fields within a oneof clause need to be unioned
@@ -608,14 +610,12 @@ function toTypeName(ctx, messageDesc, field) {
608
610
  // clause, spelling each option out inside a large type union. No need for
609
611
  // union with `undefined` here, either.
610
612
  const { options } = ctx;
611
- if ((!isWithinOneOf(field) &&
613
+ return finalize(type, (!isWithinOneOf(field) &&
612
614
  isMessage(field) &&
613
615
  (options.useOptionals === false || options.useOptionals === "none")) ||
614
616
  (isWithinOneOf(field) && options.oneof === options_1.OneofOption.PROPERTIES) ||
615
- (isWithinOneOf(field) && field.proto3Optional)) {
616
- return (0, ts_poet_1.code) `${type} | undefined`;
617
- }
618
- return type;
617
+ (isWithinOneOf(field) && field.proto3Optional) ||
618
+ ensureOptional);
619
619
  }
620
620
  exports.toTypeName = toTypeName;
621
621
  function detectMapType(ctx, messageDesc, fieldDesc) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.151.1",
3
+ "version": "1.152.1",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",
@@ -16,6 +16,7 @@
16
16
  "proto2pbjs": "docker compose run --rm protoc pbjs.sh",
17
17
  "bin2ts": "docker compose run --rm protoc codegen.sh",
18
18
  "test": "yarn jest -c jest.config.js --maxWorkers=2",
19
+ "tsc:check": "./tsc-check.sh tsconfig.json tests/tsconfig.json integration/tsconfig.json integration/tsconfig.proto.json protos/tsconfig.json",
19
20
  "format": "prettier --write {src,tests}/**/*.ts integration/*.ts",
20
21
  "format:check": "prettier --list-different {src,tests}/**/*.ts",
21
22
  "setup:docker": "docker compose build",
@@ -42,8 +43,9 @@
42
43
  "@semantic-release/github": "^9.0.2",
43
44
  "@semantic-release/npm": "^10.0.3",
44
45
  "@semantic-release/release-notes-generator": "^11.0.2",
46
+ "@tsconfig/strictest": "^2.0.1",
45
47
  "@types/jest": "^29.5.2",
46
- "@types/node": "^14.14.37",
48
+ "@types/node": "^16.18.38",
47
49
  "chokidar": "^3.5.3",
48
50
  "jest": "^29.5.0",
49
51
  "jest-ts-webcompat-resolver": "^1.0.0",