ts-proto 1.87.1 → 1.90.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.
- package/CHANGELOG.md +28 -0
- package/README.markdown +189 -23
- package/build/encode.js +14 -2
- package/build/main.js +157 -27
- package/build/types.js +34 -2
- package/build/utils.js +10 -1
- package/package.json +5 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [1.90.1](https://github.com/stephenh/ts-proto/compare/v1.90.0...v1.90.1) (2021-11-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* code-generation for Services with Struct response types ([#407](https://github.com/stephenh/ts-proto/issues/407)) ([f041fa1](https://github.com/stephenh/ts-proto/commit/f041fa1047816748c366bcb81895b6b917eb328d))
|
|
7
|
+
|
|
8
|
+
# [1.90.0](https://github.com/stephenh/ts-proto/compare/v1.89.0...v1.90.0) (2021-11-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Add support for 'json_name' annotation ([#408](https://github.com/stephenh/ts-proto/issues/408)) ([b519717](https://github.com/stephenh/ts-proto/commit/b5197174bcaacb8f163cd197d52ab9c645d21d4c))
|
|
14
|
+
|
|
15
|
+
# [1.89.0](https://github.com/stephenh/ts-proto/compare/v1.88.0...v1.89.0) (2021-11-24)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* Improve map reading (fromJSON/fromPartial) ([#410](https://github.com/stephenh/ts-proto/issues/410)) ([057d438](https://github.com/stephenh/ts-proto/commit/057d438548d95c354331f7d2d767ccff952ad5c6))
|
|
21
|
+
|
|
22
|
+
# [1.88.0](https://github.com/stephenh/ts-proto/compare/v1.87.1...v1.88.0) (2021-11-22)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* Support for Google.Protobuf.Value, ListValue and Struct ([#396](https://github.com/stephenh/ts-proto/issues/396)) ([7dd9c16](https://github.com/stephenh/ts-proto/commit/7dd9c16ffdec4d9ea296fbdc30d390fe44192c42))
|
|
28
|
+
|
|
1
29
|
## [1.87.1](https://github.com/stephenh/ts-proto/compare/v1.87.0...v1.87.1) (2021-11-21)
|
|
2
30
|
|
|
3
31
|
|
package/README.markdown
CHANGED
|
@@ -22,10 +22,13 @@
|
|
|
22
22
|
- [Assumptions](#assumptions)
|
|
23
23
|
- [Todo](#todo)
|
|
24
24
|
- [OneOf Handling](#oneof-handling)
|
|
25
|
-
- [
|
|
25
|
+
- [Default Values and Unset Fields](#default-values-and-unset-fields)
|
|
26
|
+
- [Well-Known Types](#well-known-types)
|
|
27
|
+
- [Wrapper Types](#wrapper-types)
|
|
28
|
+
- [JSON Types (Struct Types)](#json-types-struct-types)
|
|
29
|
+
- [Timestamps](#timestamp)
|
|
26
30
|
- [Wrapper Types](#wrapper-types)
|
|
27
31
|
- [Number Types](#number-types)
|
|
28
|
-
- [Timestamps](#timestamps)
|
|
29
32
|
- [Current Status of Optional Values](#current-status-of-optional-values)
|
|
30
33
|
|
|
31
34
|
# Overview
|
|
@@ -376,7 +379,6 @@ The test suite's proto files (i.e. `simple.proto`, `batching.proto`, etc.) curre
|
|
|
376
379
|
# Todo
|
|
377
380
|
|
|
378
381
|
- Support the string-based encoding of duration in `fromJSON`/`toJSON`
|
|
379
|
-
- Support the `json_name` annotation
|
|
380
382
|
- Make `oneof=unions` the default behavior in 2.0
|
|
381
383
|
- Probably change `forceLong` default in 2.0, should default to `forceLong=long`
|
|
382
384
|
- Make `esModuleInterop=true` the default in 2.0
|
|
@@ -399,29 +401,201 @@ As this will automatically enforce only one of `field_a` or `field_b` "being set
|
|
|
399
401
|
|
|
400
402
|
In ts-proto's currently-unscheduled 2.x release, `oneof=unions` will become the default behavior.
|
|
401
403
|
|
|
402
|
-
#
|
|
404
|
+
# Default values and unset fields
|
|
403
405
|
|
|
404
|
-
|
|
406
|
+
In core Protobuf, values that are _unset_ or equal to the default value are not sent over the wire.
|
|
407
|
+
The default value of a message is `undefined`. Primitive types take their natural default value, i.e. `string` is `''`, `number` is `0`, etc.
|
|
408
|
+
This behavior enables forward compatibility, as primitive fields will always have a value, even when omitted by outdated agents, but it also means _default_ and _unset_ values cannot be distinguished.
|
|
405
409
|
|
|
406
|
-
|
|
410
|
+
If you need primitive fields where you can detect set/unset, see [Wrapper Types](#wrapper-types).
|
|
407
411
|
|
|
408
|
-
|
|
412
|
+
**Encode / Decode**
|
|
409
413
|
|
|
410
|
-
|
|
414
|
+
`ts-proto` follows the Protobuf rules, and always returns default values for unsets fields when decoding, while omitting them from the output when serialized in binary format.
|
|
411
415
|
|
|
412
|
-
|
|
416
|
+
```protobuf
|
|
417
|
+
syntax = "proto3";
|
|
418
|
+
message Foo {
|
|
419
|
+
string bar = 1;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
protobufBytes; // assume this is an empty Foo object, in protobuf binary format
|
|
425
|
+
Foo.decode(protobufBytes); // => { bar: '' }
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
Foo.encode({ bar: '' }); // => { }, writes an empty Foo object, in protobuf binary format
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**fromJSON / toJSON**
|
|
433
|
+
|
|
434
|
+
Reading JSON will also initialize the default values. Since senders may either omit unset fields, or set them to the default value, use `fromJSON` to normalize the input.
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
Foo.fromJSON({ }); // => { bar: '' }
|
|
438
|
+
Foo.fromJSON({ bar: '' }); // => { bar: '' }
|
|
439
|
+
Foo.fromJSON({ bar: 'baz' }); // => { bar: 'baz' }
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
When writing JSON, `ts-proto` currently does **not** normalize message when converting to JSON, other than omitting unset fields, but it may do so in the future.
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
// Current ts-proto behavior
|
|
446
|
+
Foo.toJSON({ }); // => { }
|
|
447
|
+
Foo.toJSON({ bar: undefined }); // => { }
|
|
448
|
+
Foo.toJSON({ bar: '' }); // => { bar: '' } - note: this is the default value, but it's not omitted
|
|
449
|
+
Foo.toJSON({ bar: 'baz' }); // => { bar: 'baz' }
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
// Possible future behavior, where ts-proto would normalize message
|
|
454
|
+
Foo.toJSON({ }); // => { }
|
|
455
|
+
Foo.toJSON({ bar: undefined }); // => { }
|
|
456
|
+
Foo.toJSON({ bar: '' }); // => { } - note: omitting the default value, as expected
|
|
457
|
+
Foo.toJSON({ bar: 'baz' }); // => { bar: 'baz' }
|
|
458
|
+
```
|
|
413
459
|
|
|
414
|
-
|
|
460
|
+
- Please open an issue if you need this behavior.
|
|
415
461
|
|
|
416
|
-
|
|
462
|
+
# Well-Known Types
|
|
417
463
|
|
|
418
|
-
|
|
464
|
+
Protobuf comes with several predefined message definitions, called "[Well-Known Types](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf)".
|
|
465
|
+
Their interpretation is defined by the Protobuf specification, and libraries are expected to convert these messages to corresponding native types in the target language.
|
|
419
466
|
|
|
420
|
-
|
|
467
|
+
`ts-proto` currently automatically converts these messages to their corresponding native types.
|
|
421
468
|
|
|
422
|
-
|
|
469
|
+
- Wrapper Types:
|
|
470
|
+
|
|
471
|
+
* [google.protobuf.DoubleValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#DoubleValue) ⇆ `number | undefined`
|
|
472
|
+
* [google.protobuf.FloatValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#FloatValue) ⇆ `number | undefined`
|
|
473
|
+
* [google.protobuf.Int64Value](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#Int64Value) ⇆ `number | undefined`
|
|
474
|
+
* [google.protobuf.UInt64Value](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#UInt64Value) ⇆ `number | undefined`
|
|
475
|
+
* [google.protobuf.Int32Value](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#Int32Value) ⇆ `number | undefined`
|
|
476
|
+
* [google.protobuf.UInt32Value](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#UInt32Value) ⇆ `number | undefined`
|
|
477
|
+
* [google.protobuf.BoolValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#BoolValue) ⇆ `boolean | undefined`
|
|
478
|
+
* [google.protobuf.StringValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#StringValue) ⇆ `string | undefined`
|
|
479
|
+
* [google.protobuf.BytesValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.BytesValue) ⇆ `Uint8Array | undefined`
|
|
480
|
+
|
|
481
|
+
- JSON Types (Struct Types):
|
|
482
|
+
|
|
483
|
+
* [google.protobuf.Value](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#Value) ⇆ `any | undefined` (i.e. `number | string | boolean | null | array | object`)
|
|
484
|
+
* [google.protobuf.ListValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#ListValue) ⇆ `any[]`
|
|
485
|
+
* [google.protobuf.Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#Struct) ⇆ `{ [key: string]: any } | undefined`
|
|
486
|
+
|
|
487
|
+
## Wrapper Types
|
|
488
|
+
|
|
489
|
+
Wrapper Types are messages containing a single primitive field, and can be imported in `.proto` files with `import "google/protobuf/wrappers.proto"`.
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
Since these are _messages_, their default value is `undefined`, allowing you to distinguish unset primitives from their default values, when using Wrapper Types.
|
|
493
|
+
`ts-proto` generates these fields as `<primitive> | undefined`.
|
|
494
|
+
|
|
495
|
+
For example:
|
|
496
|
+
|
|
497
|
+
```protobuf
|
|
498
|
+
// Protobuf
|
|
499
|
+
syntax = "proto3";
|
|
500
|
+
|
|
501
|
+
import "google/protobuf/wrappers.proto";
|
|
502
|
+
|
|
503
|
+
message ExampleMessage {
|
|
504
|
+
google.protobuf.StringValue name = 1;
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
// TypeScript
|
|
510
|
+
interface ExampleMessage {
|
|
511
|
+
name: string | undefined;
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
When encoding a message the primitive value is converted back to its corresponding wrapper type:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
ExampleMessage.encode({ name: 'foo' }) // => { name: { value: 'foo' } }, in binary
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
When calling toJSON, the value is not converted, because wrapper types are idiomatic in JSON.
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
ExampleMessage.toJSON({ name: 'foo' }) // => { name: 'foo' }
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
## JSON Types (Struct Types)
|
|
528
|
+
|
|
529
|
+
Protobuf's language and types are not sufficient to represent all possible JSON values, since JSON may contain values whose type is unknown in advance.
|
|
530
|
+
For this reason, Protobuf offers several additional types to represent arbitrary JSON values.
|
|
531
|
+
|
|
532
|
+
These are called Struct Types, and can be imported in `.proto` files with `import "google/protobuf/struct.proto"`.
|
|
533
|
+
|
|
534
|
+
- [google.protobuf.Value](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#Value) ⇆ `any`
|
|
535
|
+
- This is the most general type, and can represent any JSON value (i.e. `number | string | boolean | null | array | object`).
|
|
536
|
+
- [google.protobuf.ListValue](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#ListValue) ⇆ `any[]`
|
|
537
|
+
- To represent a JSON array
|
|
538
|
+
- [google.protobuf.Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#Struct) ⇆ `{ [key: string]: any }`
|
|
539
|
+
- To represent a JSON object
|
|
540
|
+
|
|
541
|
+
`ts-proto` automatically converts back and forth between these Struct Types and their corresponding JSON types.
|
|
542
|
+
|
|
543
|
+
Example:
|
|
544
|
+
|
|
545
|
+
```protobuf
|
|
546
|
+
// Protobuf
|
|
547
|
+
syntax = "proto3";
|
|
548
|
+
|
|
549
|
+
import "google/protobuf/struct.proto";
|
|
550
|
+
|
|
551
|
+
message ExampleMessage {
|
|
552
|
+
google.protobuf.Value anything = 1;
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
// TypeScript
|
|
558
|
+
interface ExampleMessage {
|
|
559
|
+
anything: any | undefined;
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
Encoding a JSON value embedded in a message, converts it to a Struct Type:
|
|
564
|
+
```typescript
|
|
565
|
+
ExampleMessage.encode({ anything: { "name": "hello" } })
|
|
566
|
+
/* Outputs the following structure, encoded in protobuf binary format:
|
|
567
|
+
{
|
|
568
|
+
anything: Value {
|
|
569
|
+
structValue = Struct {
|
|
570
|
+
fields = [
|
|
571
|
+
MapEntry {
|
|
572
|
+
key = "name",
|
|
573
|
+
value = Value {
|
|
574
|
+
stringValue = "hello"
|
|
575
|
+
}
|
|
576
|
+
]
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}*/
|
|
581
|
+
|
|
582
|
+
ExampleMessage.encode({ anything: true })
|
|
583
|
+
/* Outputs the following structure encoded in protobuf binary format:
|
|
584
|
+
{
|
|
585
|
+
anything: Value {
|
|
586
|
+
boolValue = true
|
|
587
|
+
}
|
|
588
|
+
}*/
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
## Timestamp
|
|
592
|
+
|
|
593
|
+
The representation of `google.protobuf.Timestamp` is configurable by the `useDate` flag.
|
|
594
|
+
|
|
595
|
+
| Protobuf well-known type | Default/`useDate=true` | `useDate=false` | `useDate=string` |
|
|
596
|
+
| --------------------------- | ---------------------- | ------------------------------------ | ---------------- |
|
|
597
|
+
| `google.protobuf.Timestamp` | `Date` | `{ seconds: number, nanos: number }` | `string` |
|
|
423
598
|
|
|
424
|
-
This makes dealing with `string | unset` in your code much nicer, albeit it's unfortunate that, in Protobuf core, this is not as simple as marking a `string name = 1` field as `optional`, i.e. you have to "dirty" your proto files a bit by knowing to use the `StringValue` convention.
|
|
425
599
|
|
|
426
600
|
# Number Types
|
|
427
601
|
|
|
@@ -452,14 +626,6 @@ The protobuf number types map to JavaScript types based on the `forceLong` confi
|
|
|
452
626
|
|
|
453
627
|
Where (\*) indicates they might throw an error at runtime.
|
|
454
628
|
|
|
455
|
-
# Timestamps
|
|
456
|
-
|
|
457
|
-
The representation of `google.protobuf.Timestamp` is configurable by the `useDate` flag.
|
|
458
|
-
|
|
459
|
-
| Protobuf well-known type | Default/`useDate=true` | `useDate=false` | `useDate=string` |
|
|
460
|
-
| --------------------------- | ---------------------- | ------------------------------------ | ---------------- |
|
|
461
|
-
| `google.protobuf.Timestamp` | `Date` | `{ seconds: number, nanos: number }` | `string` |
|
|
462
|
-
|
|
463
629
|
# Current Status of Optional Values
|
|
464
630
|
|
|
465
631
|
- Required primitives: use as-is, i.e. `string name = 1`.
|
package/build/encode.js
CHANGED
|
@@ -7,12 +7,20 @@ const options_1 = require("./options");
|
|
|
7
7
|
function generateEncoder(ctx, typeName) {
|
|
8
8
|
const name = types_1.wrapperTypeName(typeName);
|
|
9
9
|
if (!name) {
|
|
10
|
-
return ts_poet_1.code `${types_1.messageToTypeName(ctx, typeName)}.encode(value).finish()`;
|
|
10
|
+
return ts_poet_1.code `${types_1.messageToTypeName(ctx, typeName, { keepValueType: true })}.encode(value).finish()`;
|
|
11
11
|
}
|
|
12
12
|
if (name == 'Timestamp') {
|
|
13
13
|
const TimestampValue = ts_poet_1.imp(`${name}@./google/protobuf/timestamp`);
|
|
14
14
|
return ts_poet_1.code `${TimestampValue}.encode(${ctx.utils.toTimestamp}(value)).finish()`;
|
|
15
15
|
}
|
|
16
|
+
if (name == 'Struct') {
|
|
17
|
+
const StructType = ts_poet_1.imp(`${name}@./google/protobuf/struct`);
|
|
18
|
+
return ts_poet_1.code `${StructType}.encode(${StructType}.wrap(value)).finish()`;
|
|
19
|
+
}
|
|
20
|
+
if (name == 'ListValue') {
|
|
21
|
+
const ListValueType = ts_poet_1.imp(`${name}@./google/protobuf/struct`);
|
|
22
|
+
return ts_poet_1.code `${ListValueType}.encode({values: value ?? []}).finish()`;
|
|
23
|
+
}
|
|
16
24
|
const TypeValue = ts_poet_1.imp(`${name}@./google/protobuf/wrappers`);
|
|
17
25
|
switch (name) {
|
|
18
26
|
case 'StringValue':
|
|
@@ -39,13 +47,17 @@ exports.generateEncoder = generateEncoder;
|
|
|
39
47
|
function generateDecoder(ctx, typeName) {
|
|
40
48
|
let name = types_1.wrapperTypeName(typeName);
|
|
41
49
|
if (!name) {
|
|
42
|
-
return ts_poet_1.code `${types_1.messageToTypeName(ctx, typeName)}.decode(value)`;
|
|
50
|
+
return ts_poet_1.code `${types_1.messageToTypeName(ctx, typeName, { keepValueType: true })}.decode(value)`;
|
|
43
51
|
}
|
|
44
52
|
let TypeValue;
|
|
45
53
|
if (name == 'Timestamp') {
|
|
46
54
|
TypeValue = ts_poet_1.imp(`${name}@./google/protobuf/timestamp`);
|
|
47
55
|
return ts_poet_1.code `${TypeValue}.decode(value)`;
|
|
48
56
|
}
|
|
57
|
+
if (name == 'Struct' || name == 'ListValue') {
|
|
58
|
+
TypeValue = ts_poet_1.imp(`${name}@./google/protobuf/struct`);
|
|
59
|
+
return ts_poet_1.code `${TypeValue}.unwrap(${TypeValue}.decode(value))`;
|
|
60
|
+
}
|
|
49
61
|
TypeValue = ts_poet_1.imp(`${name}@./google/protobuf/wrappers`);
|
|
50
62
|
return ts_poet_1.code `${TypeValue}.decode(value).value`;
|
|
51
63
|
}
|
package/build/main.js
CHANGED
|
@@ -77,6 +77,8 @@ function generateFile(ctx, fileDesc) {
|
|
|
77
77
|
if (options.outputPartialMethods) {
|
|
78
78
|
staticMembers.push(generateFromPartial(ctx, fullName, message));
|
|
79
79
|
}
|
|
80
|
+
staticMembers.push(...generateWrap(fullTypeName));
|
|
81
|
+
staticMembers.push(...generateUnwrap(fullTypeName));
|
|
80
82
|
chunks.push(ts_poet_1.code `
|
|
81
83
|
export const ${ts_poet_1.def(fullName)} = {
|
|
82
84
|
${ts_poet_1.joinCode(staticMembers, { on: ',\n\n' })}
|
|
@@ -529,7 +531,14 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
529
531
|
}
|
|
530
532
|
else if (types_1.isValueType(ctx, field)) {
|
|
531
533
|
const type = types_1.basicTypeName(ctx, field, { keepValueType: true });
|
|
532
|
-
|
|
534
|
+
const unwrap = (decodedValue) => {
|
|
535
|
+
if (types_1.isListValueType(field) || types_1.isStructType(field) || types_1.isAnyValueType(field)) {
|
|
536
|
+
return ts_poet_1.code `${type}.unwrap(${decodedValue})`;
|
|
537
|
+
}
|
|
538
|
+
return ts_poet_1.code `${decodedValue}.value`;
|
|
539
|
+
};
|
|
540
|
+
const decoder = ts_poet_1.code `${type}.decode(reader, reader.uint32())`;
|
|
541
|
+
readSnippet = ts_poet_1.code `${unwrap(decoder)}`;
|
|
533
542
|
}
|
|
534
543
|
else if (types_1.isTimestamp(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
|
|
535
544
|
const type = types_1.basicTypeName(ctx, field, { keepValueType: true });
|
|
@@ -624,10 +633,16 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
624
633
|
writeSnippet = (place) => ts_poet_1.code `${type}.encode(${utils.toTimestamp}(${place}), writer.uint32(${tag}).fork()).ldelim()`;
|
|
625
634
|
}
|
|
626
635
|
else if (types_1.isValueType(ctx, field)) {
|
|
627
|
-
const tag = ((field.number << 3) | 2) >>> 0;
|
|
628
|
-
const type = types_1.basicTypeName(ctx, field, { keepValueType: true });
|
|
629
636
|
const maybeTypeField = options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : '';
|
|
630
|
-
|
|
637
|
+
const type = types_1.basicTypeName(ctx, field, { keepValueType: true });
|
|
638
|
+
const wrappedValue = (place) => {
|
|
639
|
+
if (types_1.isAnyValueType(field) || types_1.isListValueType(field) || types_1.isStructType(field)) {
|
|
640
|
+
return ts_poet_1.code `${type}.wrap(${place})`;
|
|
641
|
+
}
|
|
642
|
+
return ts_poet_1.code `{${maybeTypeField} value: ${place}!}`;
|
|
643
|
+
};
|
|
644
|
+
const tag = ((field.number << 3) | 2) >>> 0;
|
|
645
|
+
writeSnippet = (place) => ts_poet_1.code `${type}.encode(${wrappedValue(place)}, writer.uint32(${tag}).fork()).ldelim()`;
|
|
631
646
|
}
|
|
632
647
|
else if (types_1.isMessage(field)) {
|
|
633
648
|
const tag = ((field.number << 3) | 2) >>> 0;
|
|
@@ -743,6 +758,7 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
743
758
|
// add a check for each incoming field
|
|
744
759
|
messageDesc.field.forEach((field) => {
|
|
745
760
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
761
|
+
const jsonName = utils_1.determineFieldJsonName(field, options);
|
|
746
762
|
// get a generic 'reader.doSomething' bit that is specific to the basic type
|
|
747
763
|
const readSnippet = (from) => {
|
|
748
764
|
if (types_1.isEnum(field)) {
|
|
@@ -775,6 +791,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
775
791
|
(options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.TIMESTAMP)) {
|
|
776
792
|
return ts_poet_1.code `${utils.fromJsonTimestamp}(${from})`;
|
|
777
793
|
}
|
|
794
|
+
else if (types_1.isAnyValueType(field) || types_1.isStructType(field)) {
|
|
795
|
+
return ts_poet_1.code `${from}`;
|
|
796
|
+
}
|
|
778
797
|
else if (types_1.isValueType(ctx, field)) {
|
|
779
798
|
const valueType = types_1.valueTypeName(ctx, field.typeName);
|
|
780
799
|
if (types_1.isLongValueType(field) && options.forceLong === options_1.LongOption.LONG) {
|
|
@@ -783,6 +802,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
783
802
|
else if (types_1.isBytesValueType(field)) {
|
|
784
803
|
return ts_poet_1.code `new ${case_1.capitalize(valueType.toCodeString())}(${from})`;
|
|
785
804
|
}
|
|
805
|
+
else if (types_1.isListValueType(field)) {
|
|
806
|
+
return ts_poet_1.code `[...${from}]`;
|
|
807
|
+
}
|
|
786
808
|
else {
|
|
787
809
|
return ts_poet_1.code `${case_1.capitalize(valueType.toCodeString())}(${from})`;
|
|
788
810
|
}
|
|
@@ -822,6 +844,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
822
844
|
const type = types_1.basicTypeName(ctx, valueType);
|
|
823
845
|
return ts_poet_1.code `${from} as ${type}`;
|
|
824
846
|
}
|
|
847
|
+
else if (types_1.isAnyValueType(valueType)) {
|
|
848
|
+
return ts_poet_1.code `${from}`;
|
|
849
|
+
}
|
|
825
850
|
else {
|
|
826
851
|
const type = types_1.basicTypeName(ctx, valueType);
|
|
827
852
|
return ts_poet_1.code `${type}.fromJSON(${from})`;
|
|
@@ -839,36 +864,53 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
839
864
|
// and then use the snippet to handle repeated fields if necessary
|
|
840
865
|
if (types_1.isRepeated(field)) {
|
|
841
866
|
if (types_1.isMapType(ctx, messageDesc, field)) {
|
|
842
|
-
|
|
843
|
-
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
867
|
+
const fieldType = types_1.toTypeName(ctx, messageDesc, field);
|
|
844
868
|
const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
|
|
845
869
|
chunks.push(ts_poet_1.code `
|
|
846
|
-
Object.entries(object.${
|
|
847
|
-
|
|
848
|
-
|
|
870
|
+
message.${fieldName} = Object.entries(object.${jsonName} ?? {}).reduce<${fieldType}>((acc, [key, value]) => {
|
|
871
|
+
acc[${i}] = ${readSnippet('value')};
|
|
872
|
+
return acc;
|
|
873
|
+
}, {});
|
|
874
|
+
`);
|
|
875
|
+
}
|
|
876
|
+
else if (types_1.isAnyValueType(field)) {
|
|
877
|
+
chunks.push(ts_poet_1.code `
|
|
878
|
+
message.${fieldName} = Array.isArray(object?.${jsonName}) ? [...object.${jsonName}] : [];
|
|
849
879
|
`);
|
|
850
|
-
chunks.push(ts_poet_1.code `}`);
|
|
851
880
|
}
|
|
852
881
|
else {
|
|
853
882
|
// Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
|
|
854
883
|
chunks.push(ts_poet_1.code `
|
|
855
|
-
message.${fieldName} = (object.${
|
|
884
|
+
message.${fieldName} = (object.${jsonName} ?? []).map((e: any) => ${readSnippet('e')});
|
|
856
885
|
`);
|
|
857
886
|
}
|
|
858
887
|
}
|
|
859
888
|
else if (types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
|
|
860
|
-
chunks.push(ts_poet_1.code `if (object.${
|
|
889
|
+
chunks.push(ts_poet_1.code `if (object.${jsonName} !== undefined && object.${jsonName} !== null) {`);
|
|
861
890
|
const oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
862
891
|
chunks.push(ts_poet_1.code `
|
|
863
|
-
message.${oneofName} = { $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${
|
|
892
|
+
message.${oneofName} = { $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${jsonName}`)} }
|
|
864
893
|
`);
|
|
865
894
|
chunks.push(ts_poet_1.code `}`);
|
|
866
895
|
}
|
|
896
|
+
else if (types_1.isAnyValueType(field)) {
|
|
897
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = object.${fieldName};`);
|
|
898
|
+
}
|
|
899
|
+
else if (types_1.isStructType(field)) {
|
|
900
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = typeof(object.${fieldName}) === 'object' ? object.${fieldName} : undefined;`);
|
|
901
|
+
}
|
|
902
|
+
else if (types_1.isListValueType(field)) {
|
|
903
|
+
chunks.push(ts_poet_1.code `
|
|
904
|
+
message.${fieldName} = Array.isArray(object?.${fieldName})
|
|
905
|
+
? ${readSnippet(`object.${fieldName}`)}
|
|
906
|
+
: ${'undefined'};
|
|
907
|
+
`);
|
|
908
|
+
}
|
|
867
909
|
else {
|
|
868
910
|
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
869
911
|
chunks.push(ts_poet_1.code `
|
|
870
|
-
message.${fieldName} = (object.${
|
|
871
|
-
? ${readSnippet(`object.${
|
|
912
|
+
message.${fieldName} = (object.${jsonName} !== undefined && object.${jsonName} !== null)
|
|
913
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
872
914
|
: ${fallback};
|
|
873
915
|
`);
|
|
874
916
|
}
|
|
@@ -889,6 +931,7 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
889
931
|
// then add a case for each field
|
|
890
932
|
messageDesc.field.forEach((field) => {
|
|
891
933
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
934
|
+
const jsonName = utils_1.determineFieldJsonName(field, options);
|
|
892
935
|
const readSnippet = (from) => {
|
|
893
936
|
if (types_1.isEnum(field)) {
|
|
894
937
|
const toJson = types_1.getEnumMethod(typeMap, field.typeName, 'ToJSON');
|
|
@@ -930,11 +973,17 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
930
973
|
else if (types_1.isScalar(valueType) || types_1.isValueType(ctx, valueType)) {
|
|
931
974
|
return ts_poet_1.code `${from}`;
|
|
932
975
|
}
|
|
976
|
+
else if (types_1.isAnyValueType(valueType)) {
|
|
977
|
+
return ts_poet_1.code `${from}`;
|
|
978
|
+
}
|
|
933
979
|
else {
|
|
934
980
|
const type = types_1.basicTypeName(ctx, valueType);
|
|
935
981
|
return ts_poet_1.code `${type}.toJSON(${from})`;
|
|
936
982
|
}
|
|
937
983
|
}
|
|
984
|
+
else if (types_1.isAnyValueType(field)) {
|
|
985
|
+
return ts_poet_1.code `${from}`;
|
|
986
|
+
}
|
|
938
987
|
else if (types_1.isMessage(field) && !types_1.isValueType(ctx, field) && !types_1.isMapType(ctx, messageDesc, field)) {
|
|
939
988
|
const type = types_1.basicTypeName(ctx, field, { keepValueType: true });
|
|
940
989
|
return ts_poet_1.code `${from} ? ${type}.toJSON(${from}) : ${types_1.defaultValue(ctx, field)}`;
|
|
@@ -958,10 +1007,10 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
958
1007
|
if (types_1.isMapType(ctx, messageDesc, field)) {
|
|
959
1008
|
// Maps might need their values transformed, i.e. bytes --> base64
|
|
960
1009
|
chunks.push(ts_poet_1.code `
|
|
961
|
-
obj.${
|
|
1010
|
+
obj.${jsonName} = {};
|
|
962
1011
|
if (message.${fieldName}) {
|
|
963
1012
|
Object.entries(message.${fieldName}).forEach(([k, v]) => {
|
|
964
|
-
obj.${
|
|
1013
|
+
obj.${jsonName}[k] = ${readSnippet('v')};
|
|
965
1014
|
});
|
|
966
1015
|
}
|
|
967
1016
|
`);
|
|
@@ -970,9 +1019,9 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
970
1019
|
// Arrays might need their elements transformed
|
|
971
1020
|
chunks.push(ts_poet_1.code `
|
|
972
1021
|
if (message.${fieldName}) {
|
|
973
|
-
obj.${
|
|
1022
|
+
obj.${jsonName} = message.${fieldName}.map(e => ${readSnippet('e')});
|
|
974
1023
|
} else {
|
|
975
|
-
obj.${
|
|
1024
|
+
obj.${jsonName} = [];
|
|
976
1025
|
}
|
|
977
1026
|
`);
|
|
978
1027
|
}
|
|
@@ -980,11 +1029,11 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
980
1029
|
// oneofs in a union are only output as `oneof name = ...`
|
|
981
1030
|
const oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
982
1031
|
const v = readSnippet(`message.${oneofName}?.${fieldName}`);
|
|
983
|
-
chunks.push(ts_poet_1.code `message.${oneofName}?.$case === '${fieldName}' && (obj.${
|
|
1032
|
+
chunks.push(ts_poet_1.code `message.${oneofName}?.$case === '${fieldName}' && (obj.${jsonName} = ${v});`);
|
|
984
1033
|
}
|
|
985
1034
|
else {
|
|
986
1035
|
const v = readSnippet(`message.${fieldName}`);
|
|
987
|
-
chunks.push(ts_poet_1.code `message.${fieldName} !== undefined && (obj.${
|
|
1036
|
+
chunks.push(ts_poet_1.code `message.${fieldName} !== undefined && (obj.${jsonName} = ${v});`);
|
|
988
1037
|
}
|
|
989
1038
|
});
|
|
990
1039
|
chunks.push(ts_poet_1.code `return obj;`);
|
|
@@ -1030,6 +1079,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1030
1079
|
return ts_poet_1.code `${cstr}(${from})`;
|
|
1031
1080
|
}
|
|
1032
1081
|
}
|
|
1082
|
+
else if (types_1.isAnyValueType(valueType)) {
|
|
1083
|
+
return ts_poet_1.code `${from}`;
|
|
1084
|
+
}
|
|
1033
1085
|
else if (types_1.isTimestamp(valueType) &&
|
|
1034
1086
|
(options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
|
|
1035
1087
|
return ts_poet_1.code `${from}`;
|
|
@@ -1042,6 +1094,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1042
1094
|
return ts_poet_1.code `${type}.fromPartial(${from})`;
|
|
1043
1095
|
}
|
|
1044
1096
|
}
|
|
1097
|
+
else if (types_1.isAnyValueType(field)) {
|
|
1098
|
+
return ts_poet_1.code `${from}`;
|
|
1099
|
+
}
|
|
1045
1100
|
else {
|
|
1046
1101
|
const type = types_1.basicTypeName(ctx, field);
|
|
1047
1102
|
return ts_poet_1.code `${type}.fromPartial(${from})`;
|
|
@@ -1054,17 +1109,16 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1054
1109
|
// and then use the snippet to handle repeated fields if necessary
|
|
1055
1110
|
if (types_1.isRepeated(field)) {
|
|
1056
1111
|
if (types_1.isMapType(ctx, messageDesc, field)) {
|
|
1057
|
-
|
|
1058
|
-
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
1112
|
+
const fieldType = types_1.toTypeName(ctx, messageDesc, field);
|
|
1059
1113
|
const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
|
|
1060
1114
|
chunks.push(ts_poet_1.code `
|
|
1061
|
-
Object.entries(object.${fieldName}).
|
|
1115
|
+
message.${fieldName} = Object.entries(object.${fieldName} ?? {}).reduce<${fieldType}>((acc, [key, value]) => {
|
|
1062
1116
|
if (value !== undefined) {
|
|
1063
|
-
|
|
1117
|
+
acc[${i}] = ${readSnippet('value')};
|
|
1064
1118
|
}
|
|
1065
|
-
|
|
1119
|
+
return acc;
|
|
1120
|
+
}, {});
|
|
1066
1121
|
`);
|
|
1067
|
-
chunks.push(ts_poet_1.code `}`);
|
|
1068
1122
|
}
|
|
1069
1123
|
else {
|
|
1070
1124
|
chunks.push(ts_poet_1.code `
|
|
@@ -1104,6 +1158,82 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1104
1158
|
chunks.push(ts_poet_1.code `}`);
|
|
1105
1159
|
return ts_poet_1.joinCode(chunks, { on: '\n' });
|
|
1106
1160
|
}
|
|
1161
|
+
function generateWrap(fullProtoTypeName) {
|
|
1162
|
+
const chunks = [];
|
|
1163
|
+
if (types_1.isStructTypeName(fullProtoTypeName)) {
|
|
1164
|
+
chunks.push(ts_poet_1.code `wrap(object: {[key: string]: any} | undefined): Struct {
|
|
1165
|
+
const struct = Struct.fromPartial({});
|
|
1166
|
+
if (object !== undefined) {
|
|
1167
|
+
Object.keys(object).forEach(key => {
|
|
1168
|
+
struct.fields[key] = object[key];
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
return struct;
|
|
1172
|
+
}`);
|
|
1173
|
+
}
|
|
1174
|
+
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1175
|
+
chunks.push(ts_poet_1.code `wrap(value: any): Value {
|
|
1176
|
+
if (value === null) {
|
|
1177
|
+
return {nullValue: 0} as Value;
|
|
1178
|
+
} else if (typeof value === 'boolean') {
|
|
1179
|
+
return {boolValue: value} as Value;
|
|
1180
|
+
} else if (typeof value === 'number') {
|
|
1181
|
+
return {numberValue: value} as Value;
|
|
1182
|
+
} else if (typeof value === 'string') {
|
|
1183
|
+
return {stringValue: value} as Value;
|
|
1184
|
+
} else if (Array.isArray(value)) {
|
|
1185
|
+
return {listValue: value} as Value;
|
|
1186
|
+
} else if (typeof value === 'object') {
|
|
1187
|
+
return {structValue: value} as Value;
|
|
1188
|
+
} else if (typeof value === 'undefined') {
|
|
1189
|
+
return {} as Value;
|
|
1190
|
+
} else {
|
|
1191
|
+
throw new Error('Unsupported any value type: ' + typeof value);
|
|
1192
|
+
}
|
|
1193
|
+
}`);
|
|
1194
|
+
}
|
|
1195
|
+
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
|
1196
|
+
chunks.push(ts_poet_1.code `wrap(value: Array<any>): ListValue {
|
|
1197
|
+
return {values: value};
|
|
1198
|
+
}`);
|
|
1199
|
+
}
|
|
1200
|
+
return chunks;
|
|
1201
|
+
}
|
|
1202
|
+
function generateUnwrap(fullProtoTypeName) {
|
|
1203
|
+
const chunks = [];
|
|
1204
|
+
if (types_1.isStructTypeName(fullProtoTypeName)) {
|
|
1205
|
+
chunks.push(ts_poet_1.code `unwrap(message: Struct): {[key: string]: any} {
|
|
1206
|
+
const object: { [key: string]: any } = {};
|
|
1207
|
+
Object.keys(message.fields).forEach(key => {
|
|
1208
|
+
object[key] = message.fields[key];
|
|
1209
|
+
});
|
|
1210
|
+
return object;
|
|
1211
|
+
}`);
|
|
1212
|
+
}
|
|
1213
|
+
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1214
|
+
chunks.push(ts_poet_1.code `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
1215
|
+
if (message.stringValue !== undefined) {
|
|
1216
|
+
return message.stringValue;
|
|
1217
|
+
} else if (message.numberValue !== undefined) {
|
|
1218
|
+
return message.numberValue;
|
|
1219
|
+
} else if (message.boolValue !== undefined) {
|
|
1220
|
+
return message.boolValue;
|
|
1221
|
+
} else if (message.structValue !== undefined) {
|
|
1222
|
+
return message.structValue;
|
|
1223
|
+
} else if (message.listValue !== undefined) {
|
|
1224
|
+
return message.listValue;
|
|
1225
|
+
} else if (message.nullValue !== undefined) {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
}`);
|
|
1229
|
+
}
|
|
1230
|
+
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
|
1231
|
+
chunks.push(ts_poet_1.code `unwrap(message: ListValue): Array<any> {
|
|
1232
|
+
return message.values;
|
|
1233
|
+
}`);
|
|
1234
|
+
}
|
|
1235
|
+
return chunks;
|
|
1236
|
+
}
|
|
1107
1237
|
exports.contextTypeVar = 'Context extends DataLoaders';
|
|
1108
1238
|
function maybeCastToNumber(ctx, messageDesc, field, variableName) {
|
|
1109
1239
|
const { keyType } = types_1.detectMapType(ctx, messageDesc, field);
|
package/build/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectBatchMethod = exports.responsePromiseOrObservable = exports.responseObservable = exports.responsePromise = exports.responseType = exports.requestType = exports.rawRequestType = exports.detectMapType = exports.toTypeName = exports.getEnumMethod = exports.messageToTypeName = exports.wrapperTypeName = exports.valueTypeName = exports.isEmptyType = exports.isLongValueType = exports.isBytesValueType = exports.isValueType = exports.isTimestamp = exports.isMapType = exports.isLong = exports.isRepeated = exports.isWithinOneOfThatShouldBeUnion = exports.isWithinOneOf = exports.isEnum = exports.isMessage = exports.isBytes = exports.isPrimitive = exports.isScalar = exports.createTypeMap = exports.notDefaultCheck = exports.defaultValue = exports.packedType = exports.toReaderCall = exports.basicTypeName = exports.basicLongWireType = exports.basicWireType = void 0;
|
|
3
|
+
exports.detectBatchMethod = exports.responsePromiseOrObservable = exports.responseObservable = exports.responsePromise = exports.responseType = exports.requestType = exports.rawRequestType = exports.detectMapType = exports.toTypeName = exports.getEnumMethod = exports.messageToTypeName = exports.wrapperTypeName = exports.valueTypeName = exports.isEmptyType = exports.isLongValueType = exports.isStructTypeName = exports.isStructType = exports.isListValueTypeName = exports.isListValueType = exports.isBytesValueType = exports.isAnyValueTypeName = exports.isAnyValueType = exports.isValueType = exports.isTimestamp = exports.isMapType = exports.isLong = exports.isRepeated = exports.isWithinOneOfThatShouldBeUnion = exports.isWithinOneOf = exports.isEnum = exports.isMessage = exports.isBytes = exports.isPrimitive = exports.isScalar = exports.createTypeMap = exports.notDefaultCheck = exports.defaultValue = exports.packedType = exports.toReaderCall = exports.basicTypeName = exports.basicLongWireType = exports.basicWireType = void 0;
|
|
4
4
|
const ts_proto_descriptors_1 = require("ts-proto-descriptors");
|
|
5
5
|
const ts_poet_1 = require("ts-poet");
|
|
6
6
|
const options_1 = require("./options");
|
|
@@ -359,10 +359,34 @@ function isValueType(ctx, field) {
|
|
|
359
359
|
return valueTypeName(ctx, field.typeName) !== undefined;
|
|
360
360
|
}
|
|
361
361
|
exports.isValueType = isValueType;
|
|
362
|
+
function isAnyValueType(field) {
|
|
363
|
+
return isAnyValueTypeName(field.typeName);
|
|
364
|
+
}
|
|
365
|
+
exports.isAnyValueType = isAnyValueType;
|
|
366
|
+
function isAnyValueTypeName(typeName) {
|
|
367
|
+
return typeName === 'google.protobuf.Value' || typeName === '.google.protobuf.Value';
|
|
368
|
+
}
|
|
369
|
+
exports.isAnyValueTypeName = isAnyValueTypeName;
|
|
362
370
|
function isBytesValueType(field) {
|
|
363
371
|
return field.typeName === '.google.protobuf.BytesValue';
|
|
364
372
|
}
|
|
365
373
|
exports.isBytesValueType = isBytesValueType;
|
|
374
|
+
function isListValueType(field) {
|
|
375
|
+
return isListValueTypeName(field.typeName);
|
|
376
|
+
}
|
|
377
|
+
exports.isListValueType = isListValueType;
|
|
378
|
+
function isListValueTypeName(typeName) {
|
|
379
|
+
return typeName === 'google.protobuf.ListValue' || typeName === '.google.protobuf.ListValue';
|
|
380
|
+
}
|
|
381
|
+
exports.isListValueTypeName = isListValueTypeName;
|
|
382
|
+
function isStructType(field) {
|
|
383
|
+
return isStructTypeName(field.typeName);
|
|
384
|
+
}
|
|
385
|
+
exports.isStructType = isStructType;
|
|
386
|
+
function isStructTypeName(typeName) {
|
|
387
|
+
return typeName === 'google.protobuf.Struct' || typeName === '.google.protobuf.Struct';
|
|
388
|
+
}
|
|
389
|
+
exports.isStructTypeName = isStructTypeName;
|
|
366
390
|
function isLongValueType(field) {
|
|
367
391
|
return field.typeName === '.google.protobuf.Int64Value' || field.typeName === '.google.protobuf.UInt64Value';
|
|
368
392
|
}
|
|
@@ -388,6 +412,12 @@ function valueTypeName(ctx, typeName) {
|
|
|
388
412
|
return ts_poet_1.code `boolean`;
|
|
389
413
|
case '.google.protobuf.BytesValue':
|
|
390
414
|
return ts_poet_1.code `Uint8Array`;
|
|
415
|
+
case '.google.protobuf.ListValue':
|
|
416
|
+
return ts_poet_1.code `Array<any>`;
|
|
417
|
+
case '.google.protobuf.Value':
|
|
418
|
+
return ts_poet_1.code `any`;
|
|
419
|
+
case '.google.protobuf.Struct':
|
|
420
|
+
return ts_poet_1.code `{[key: string]: any}`;
|
|
391
421
|
default:
|
|
392
422
|
return undefined;
|
|
393
423
|
}
|
|
@@ -404,7 +434,9 @@ function wrapperTypeName(typeName) {
|
|
|
404
434
|
case '.google.protobuf.UInt64Value':
|
|
405
435
|
case '.google.protobuf.BoolValue':
|
|
406
436
|
case '.google.protobuf.BytesValue':
|
|
437
|
+
case '.google.protobuf.ListValue':
|
|
407
438
|
case '.google.protobuf.Timestamp':
|
|
439
|
+
case '.google.protobuf.Struct':
|
|
408
440
|
return typeName.split('.')[3];
|
|
409
441
|
default:
|
|
410
442
|
return undefined;
|
|
@@ -525,7 +557,7 @@ function requestType(ctx, methodDesc) {
|
|
|
525
557
|
}
|
|
526
558
|
exports.requestType = requestType;
|
|
527
559
|
function responseType(ctx, methodDesc) {
|
|
528
|
-
return messageToTypeName(ctx, methodDesc.outputType);
|
|
560
|
+
return messageToTypeName(ctx, methodDesc.outputType, { keepValueType: true });
|
|
529
561
|
}
|
|
530
562
|
exports.responseType = responseType;
|
|
531
563
|
function responsePromise(ctx, methodDesc) {
|
package/build/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.protoFilesToGenerate = void 0;
|
|
3
|
+
exports.determineFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.protoFilesToGenerate = void 0;
|
|
4
4
|
const ts_poet_1 = require("ts-poet");
|
|
5
5
|
const options_1 = require("./options");
|
|
6
6
|
const case_1 = require("./case");
|
|
@@ -144,3 +144,12 @@ class FormattedMethodDescriptor {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
exports.FormattedMethodDescriptor = FormattedMethodDescriptor;
|
|
147
|
+
function determineFieldJsonName(field, options) {
|
|
148
|
+
// By default jsonName is camelCased by the protocol compilier unless the user has
|
|
149
|
+
// set a "json_name" option on this field.
|
|
150
|
+
if (field.jsonName.length > 0) {
|
|
151
|
+
return field.jsonName;
|
|
152
|
+
}
|
|
153
|
+
return case_1.maybeSnakeToCamel(field.name, options);
|
|
154
|
+
}
|
|
155
|
+
exports.determineFieldJsonName = determineFieldJsonName;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-proto",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.90.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/plugin.js",
|
|
6
6
|
"repository": "github:stephenh/ts-proto",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"@grpc/proto-loader": "^0.5.6",
|
|
26
26
|
"@improbable-eng/grpc-web": "^0.14.0",
|
|
27
27
|
"@improbable-eng/grpc-web-node-http-transport": "^0.14.0",
|
|
28
|
-
"@nestjs/common": "^
|
|
29
|
-
"@nestjs/core": "^
|
|
30
|
-
"@nestjs/microservices": "^
|
|
28
|
+
"@nestjs/common": "^8.2.2",
|
|
29
|
+
"@nestjs/core": "^8.2.2",
|
|
30
|
+
"@nestjs/microservices": "^8.2.2",
|
|
31
31
|
"@semantic-release/changelog": "^5.0.1",
|
|
32
32
|
"@semantic-release/commit-analyzer": "^8.0.1",
|
|
33
33
|
"@semantic-release/git": "^9.0.0",
|
|
@@ -36,11 +36,10 @@
|
|
|
36
36
|
"@semantic-release/release-notes-generator": "^9.0.2",
|
|
37
37
|
"@types/jest": "^26.0.22",
|
|
38
38
|
"@types/node": "^14.14.37",
|
|
39
|
-
"grpc": "^1.24.6",
|
|
40
39
|
"jest": "^26.6.3",
|
|
41
40
|
"prettier": "^2.2.1",
|
|
42
41
|
"reflect-metadata": "^0.1.13",
|
|
43
|
-
"rxjs": "^
|
|
42
|
+
"rxjs": "^7.4.0",
|
|
44
43
|
"semantic-release": "^17.4.2",
|
|
45
44
|
"ts-jest": "^26.5.4",
|
|
46
45
|
"ts-node": "^9.1.1",
|