ts-proto 1.92.1 → 1.93.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/CHANGELOG.md +28 -0
- package/README.markdown +20 -5
- package/build/encode.js +9 -7
- package/build/main.js +17 -15
- package/build/options.js +1 -0
- package/build/types.js +5 -5
- package/build/utils.js +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [1.93.2](https://github.com/stephenh/ts-proto/compare/v1.93.1...v1.93.2) (2021-12-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* standalone dockerized protoc alias ([#438](https://github.com/stephenh/ts-proto/issues/438)) ([466f7d9](https://github.com/stephenh/ts-proto/commit/466f7d91551c6297fc1b9677f7a5839f8cdba0c6))
|
|
7
|
+
|
|
8
|
+
## [1.93.1](https://github.com/stephenh/ts-proto/compare/v1.93.0...v1.93.1) (2021-12-08)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Unwrap google.protobuf.BytesValue to Buffer when env=node ([#439](https://github.com/stephenh/ts-proto/issues/439)) ([73aa836](https://github.com/stephenh/ts-proto/commit/73aa8368300818068f3cddc5f046d990c66ab4f2))
|
|
14
|
+
|
|
15
|
+
# [1.93.0](https://github.com/stephenh/ts-proto/compare/v1.92.2...v1.93.0) (2021-12-08)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* Allow optional suffix for generated files ([#431](https://github.com/stephenh/ts-proto/issues/431)) ([d826966](https://github.com/stephenh/ts-proto/commit/d826966f22830920444963b3894ffc0be9b7c319))
|
|
21
|
+
|
|
22
|
+
## [1.92.2](https://github.com/stephenh/ts-proto/compare/v1.92.1...v1.92.2) (2021-12-08)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* noImplicitReturns error in Value.unwrap ([#436](https://github.com/stephenh/ts-proto/issues/436)) ([2d7a5d0](https://github.com/stephenh/ts-proto/commit/2d7a5d04c72ace58fa3a6745c3857f6cc0468543)), closes [#432](https://github.com/stephenh/ts-proto/issues/432)
|
|
28
|
+
|
|
1
29
|
## [1.92.1](https://github.com/stephenh/ts-proto/compare/v1.92.0...v1.92.1) (2021-12-02)
|
|
2
30
|
|
|
3
31
|
|
package/README.markdown
CHANGED
|
@@ -9,25 +9,29 @@
|
|
|
9
9
|
|
|
10
10
|
## Table of contents
|
|
11
11
|
|
|
12
|
+
- [ts-proto](#ts-proto)
|
|
13
|
+
- [Table of contents](#table-of-contents)
|
|
14
|
+
- [Overview](#overview)
|
|
12
15
|
- [QuickStart](#quickstart)
|
|
13
16
|
- [Goals](#goals)
|
|
14
17
|
- [Example Types](#example-types)
|
|
15
18
|
- [Highlights](#highlights)
|
|
16
19
|
- [Auto-Batching / N+1 Prevention](#auto-batching--n1-prevention)
|
|
17
20
|
- [Usage](#usage)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
- [Supported options](#supported-options)
|
|
22
|
+
- [Only Types](#only-types)
|
|
23
|
+
- [NestJS Support](#nestjs-support)
|
|
24
|
+
- [Watch Mode](#watch-mode)
|
|
25
|
+
- [Sponsors](#sponsors)
|
|
21
26
|
- [Development](#development)
|
|
22
27
|
- [Assumptions](#assumptions)
|
|
23
28
|
- [Todo](#todo)
|
|
24
29
|
- [OneOf Handling](#oneof-handling)
|
|
25
|
-
- [Default
|
|
30
|
+
- [Default values and unset fields](#default-values-and-unset-fields)
|
|
26
31
|
- [Well-Known Types](#well-known-types)
|
|
27
32
|
- [Wrapper Types](#wrapper-types)
|
|
28
33
|
- [JSON Types (Struct Types)](#json-types-struct-types)
|
|
29
34
|
- [Timestamp](#timestamp)
|
|
30
|
-
- [Wrapper Types](#wrapper-types)
|
|
31
35
|
- [Number Types](#number-types)
|
|
32
36
|
- [Current Status of Optional Values](#current-status-of-optional-values)
|
|
33
37
|
|
|
@@ -344,6 +348,8 @@ Generated code will be placed in the Gradle build directory.
|
|
|
344
348
|
- With `--ts_proto_opt=emitImportedFiles=false`, ts-proto will not emit `google/protobuf/*` files unless you explicit add files to `protoc` like this
|
|
345
349
|
`protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto my_message.proto google/protobuf/duration.proto`
|
|
346
350
|
|
|
351
|
+
- With `--ts_proto_opt=fileSuffix=<SUFFIX>`, ts-proto will emit generated files using the specified suffix. A `helloworld.proto` file with `fileSuffix=.pb` would be generated as `helloworld.pb.ts`. This is common behavior in other protoc plugins and provides a way to quickly glob all the generated files.
|
|
352
|
+
|
|
347
353
|
### Only Types
|
|
348
354
|
|
|
349
355
|
If you're looking for `ts-proto` to generate only types for your Protobuf types then passing all three of `outputEncodeMethods`, `outputJsonMethods`, and `outputClientImpl` as `false` is probably what you want, i.e.:
|
|
@@ -354,6 +360,15 @@ If you're looking for `ts-proto` to generate only types for your Protobuf types
|
|
|
354
360
|
|
|
355
361
|
We have a great way of working together with [nestjs](https://docs.nestjs.com/microservices/grpc). `ts-proto` generates `interfaces` and `decorators` for you controller, client. For more information see the [nestjs readme](NESTJS.markdown).
|
|
356
362
|
|
|
363
|
+
### Watch Mode
|
|
364
|
+
|
|
365
|
+
If you want to run `ts-proto` on every change of a proto file, you'll need to use a tool like [chokidar-cli](https://www.npmjs.com/package/chokidar-cli) and use it as a script in `package.json`:
|
|
366
|
+
|
|
367
|
+
```json
|
|
368
|
+
"proto:generate": "protoc --ts_proto_out=. ./<proto_path>/<proto_name>.proto --ts_proto_opt=esModuleInterop=true",
|
|
369
|
+
"proto:watch": "chokidar \"**/*.proto\" -c \"npm run proto:generate\""
|
|
370
|
+
```
|
|
371
|
+
|
|
357
372
|
# Sponsors
|
|
358
373
|
|
|
359
374
|
Kudos to our sponsors:
|
package/build/encode.js
CHANGED
|
@@ -4,24 +4,25 @@ exports.generateDecoder = exports.generateEncoder = void 0;
|
|
|
4
4
|
const ts_poet_1 = require("ts-poet");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
6
|
const options_1 = require("./options");
|
|
7
|
+
const utils_1 = require("./utils");
|
|
7
8
|
function generateEncoder(ctx, typeName) {
|
|
8
9
|
const name = types_1.wrapperTypeName(typeName);
|
|
9
10
|
if (!name) {
|
|
10
11
|
return ts_poet_1.code `${types_1.messageToTypeName(ctx, typeName, { keepValueType: true })}.encode(value).finish()`;
|
|
11
12
|
}
|
|
12
13
|
if (name == 'Timestamp') {
|
|
13
|
-
const TimestampValue =
|
|
14
|
+
const TimestampValue = utils_1.impProto(ctx.options, 'google/protobuf/timestamp', name);
|
|
14
15
|
return ts_poet_1.code `${TimestampValue}.encode(${ctx.utils.toTimestamp}(value)).finish()`;
|
|
15
16
|
}
|
|
16
17
|
if (name == 'Struct') {
|
|
17
|
-
const StructType =
|
|
18
|
+
const StructType = utils_1.impProto(ctx.options, 'google/protobuf/struct', name);
|
|
18
19
|
return ts_poet_1.code `${StructType}.encode(${StructType}.wrap(value)).finish()`;
|
|
19
20
|
}
|
|
20
21
|
if (name == 'ListValue') {
|
|
21
|
-
const ListValueType =
|
|
22
|
+
const ListValueType = utils_1.impProto(ctx.options, 'google/protobuf/struct', name);
|
|
22
23
|
return ts_poet_1.code `${ListValueType}.encode({values: value ?? []}).finish()`;
|
|
23
24
|
}
|
|
24
|
-
const TypeValue =
|
|
25
|
+
const TypeValue = utils_1.impProto(ctx.options, 'google/protobuf/wrappers', name);
|
|
25
26
|
switch (name) {
|
|
26
27
|
case 'StringValue':
|
|
27
28
|
return ts_poet_1.code `${TypeValue}.encode({value: value ?? ""}).finish()`;
|
|
@@ -45,20 +46,21 @@ function generateEncoder(ctx, typeName) {
|
|
|
45
46
|
}
|
|
46
47
|
exports.generateEncoder = generateEncoder;
|
|
47
48
|
function generateDecoder(ctx, typeName) {
|
|
49
|
+
const { options } = ctx;
|
|
48
50
|
let name = types_1.wrapperTypeName(typeName);
|
|
49
51
|
if (!name) {
|
|
50
52
|
return ts_poet_1.code `${types_1.messageToTypeName(ctx, typeName, { keepValueType: true })}.decode(value)`;
|
|
51
53
|
}
|
|
52
54
|
let TypeValue;
|
|
53
55
|
if (name == 'Timestamp') {
|
|
54
|
-
TypeValue =
|
|
56
|
+
TypeValue = utils_1.impProto(ctx.options, 'google/protobuf/timestamp', name);
|
|
55
57
|
return ts_poet_1.code `${TypeValue}.decode(value)`;
|
|
56
58
|
}
|
|
57
59
|
if (name == 'Struct' || name == 'ListValue') {
|
|
58
|
-
TypeValue =
|
|
60
|
+
TypeValue = utils_1.impProto(ctx.options, 'google/protobuf/struct', name);
|
|
59
61
|
return ts_poet_1.code `${TypeValue}.unwrap(${TypeValue}.decode(value))`;
|
|
60
62
|
}
|
|
61
|
-
TypeValue =
|
|
63
|
+
TypeValue = utils_1.impProto(ctx.options, 'google/protobuf/wrappers', name);
|
|
62
64
|
return ts_poet_1.code `${TypeValue}.decode(value).value`;
|
|
63
65
|
}
|
|
64
66
|
exports.generateDecoder = generateDecoder;
|
package/build/main.js
CHANGED
|
@@ -30,7 +30,8 @@ function generateFile(ctx, fileDesc) {
|
|
|
30
30
|
//
|
|
31
31
|
// We'll also assume that the fileDesc.name is already the `company/foo.proto` path, with
|
|
32
32
|
// the package already implicitly in it, so we won't re-append/strip/etc. it out/back in.
|
|
33
|
-
const
|
|
33
|
+
const suffix = `${options.fileSuffix}.ts`;
|
|
34
|
+
const moduleName = fileDesc.name.replace('.proto', suffix);
|
|
34
35
|
const chunks = [];
|
|
35
36
|
// Indicate this file's source protobuf package for reflective use with google.protobuf.Any
|
|
36
37
|
if (options.exportCommonSymbols) {
|
|
@@ -316,7 +317,7 @@ function makeDeepPartial(options, longs) {
|
|
|
316
317
|
return { Builtin, DeepPartial, Exact };
|
|
317
318
|
}
|
|
318
319
|
function makeTimestampMethods(options, longs) {
|
|
319
|
-
const Timestamp =
|
|
320
|
+
const Timestamp = utils_1.impProto(options, 'google/protobuf/timestamp', 'Timestamp');
|
|
320
321
|
let seconds = 'date.getTime() / 1_000';
|
|
321
322
|
let toNumberCode = 't.seconds';
|
|
322
323
|
if (options.forceLong === options_1.LongOption.LONG) {
|
|
@@ -530,7 +531,7 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
530
531
|
}
|
|
531
532
|
else if (types_1.isEnum(field)) {
|
|
532
533
|
if (options.stringEnums) {
|
|
533
|
-
const fromJson = types_1.getEnumMethod(
|
|
534
|
+
const fromJson = types_1.getEnumMethod(ctx, field.typeName, 'FromJSON');
|
|
534
535
|
readSnippet = ts_poet_1.code `${fromJson}(${readSnippet})`;
|
|
535
536
|
}
|
|
536
537
|
else {
|
|
@@ -629,7 +630,7 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
629
630
|
let writeSnippet;
|
|
630
631
|
if (types_1.isEnum(field) && options.stringEnums) {
|
|
631
632
|
const tag = ((field.number << 3) | types_1.basicWireType(field.type)) >>> 0;
|
|
632
|
-
const toNumber = types_1.getEnumMethod(
|
|
633
|
+
const toNumber = types_1.getEnumMethod(ctx, field.typeName, 'ToNumber');
|
|
633
634
|
writeSnippet = (place) => ts_poet_1.code `writer.uint32(${tag}).${types_1.toReaderCall(field)}(${toNumber}(${place}))`;
|
|
634
635
|
}
|
|
635
636
|
else if (types_1.isScalar(field) || types_1.isEnum(field)) {
|
|
@@ -691,7 +692,7 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
691
692
|
// embedded inside of it, and we want to drop that so that we can encode it packed
|
|
692
693
|
// (i.e. just one tag and multiple values).
|
|
693
694
|
const tag = ((field.number << 3) | 2) >>> 0;
|
|
694
|
-
const toNumber = types_1.getEnumMethod(
|
|
695
|
+
const toNumber = types_1.getEnumMethod(ctx, field.typeName, 'ToNumber');
|
|
695
696
|
chunks.push(ts_poet_1.code `
|
|
696
697
|
writer.uint32(${tag}).fork();
|
|
697
698
|
for (const v of message.${fieldName}) {
|
|
@@ -771,7 +772,7 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
771
772
|
// get a generic 'reader.doSomething' bit that is specific to the basic type
|
|
772
773
|
const readSnippet = (from) => {
|
|
773
774
|
if (types_1.isEnum(field)) {
|
|
774
|
-
const fromJson = types_1.getEnumMethod(
|
|
775
|
+
const fromJson = types_1.getEnumMethod(ctx, field.typeName, 'FromJSON');
|
|
775
776
|
return ts_poet_1.code `${fromJson}(${from})`;
|
|
776
777
|
}
|
|
777
778
|
else if (types_1.isPrimitive(field)) {
|
|
@@ -943,7 +944,7 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
943
944
|
const jsonName = utils_1.determineFieldJsonName(field, options);
|
|
944
945
|
const readSnippet = (from) => {
|
|
945
946
|
if (types_1.isEnum(field)) {
|
|
946
|
-
const toJson = types_1.getEnumMethod(
|
|
947
|
+
const toJson = types_1.getEnumMethod(ctx, field.typeName, 'ToJSON');
|
|
947
948
|
return types_1.isWithinOneOf(field)
|
|
948
949
|
? ts_poet_1.code `${from} !== undefined ? ${toJson}(${from}) : undefined`
|
|
949
950
|
: ts_poet_1.code `${toJson}(${from})`;
|
|
@@ -961,7 +962,7 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
961
962
|
// For map types, drill-in and then admittedly re-hard-code our per-value-type logic
|
|
962
963
|
const valueType = typeMap.get(field.typeName)[2].field[1];
|
|
963
964
|
if (types_1.isEnum(valueType)) {
|
|
964
|
-
const toJson = types_1.getEnumMethod(
|
|
965
|
+
const toJson = types_1.getEnumMethod(ctx, valueType.typeName, 'ToJSON');
|
|
965
966
|
return ts_poet_1.code `${toJson}(${from})`;
|
|
966
967
|
}
|
|
967
968
|
else if (types_1.isBytes(valueType)) {
|
|
@@ -1052,7 +1053,7 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
1052
1053
|
function generateFromPartial(ctx, fullName, messageDesc) {
|
|
1053
1054
|
const { options, utils, typeMap } = ctx;
|
|
1054
1055
|
const chunks = [];
|
|
1055
|
-
const Timestamp =
|
|
1056
|
+
const Timestamp = utils_1.impProto(options, 'google/protobuf/timestamp', 'Timestamp');
|
|
1056
1057
|
// create the basic function declaration
|
|
1057
1058
|
const paramName = messageDesc.field.length > 0 ? 'object' : '_';
|
|
1058
1059
|
chunks.push(ts_poet_1.code `
|
|
@@ -1222,19 +1223,20 @@ function generateUnwrap(fullProtoTypeName) {
|
|
|
1222
1223
|
}
|
|
1223
1224
|
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1224
1225
|
chunks.push(ts_poet_1.code `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
1225
|
-
if (message
|
|
1226
|
+
if (message?.stringValue !== undefined) {
|
|
1226
1227
|
return message.stringValue;
|
|
1227
|
-
} else if (message
|
|
1228
|
+
} else if (message?.numberValue !== undefined) {
|
|
1228
1229
|
return message.numberValue;
|
|
1229
|
-
} else if (message
|
|
1230
|
+
} else if (message?.boolValue !== undefined) {
|
|
1230
1231
|
return message.boolValue;
|
|
1231
|
-
} else if (message
|
|
1232
|
+
} else if (message?.structValue !== undefined) {
|
|
1232
1233
|
return message.structValue;
|
|
1233
|
-
} else if (message
|
|
1234
|
+
} else if (message?.listValue !== undefined) {
|
|
1234
1235
|
return message.listValue;
|
|
1235
|
-
} else if (message
|
|
1236
|
+
} else if (message?.nullValue !== undefined) {
|
|
1236
1237
|
return null;
|
|
1237
1238
|
}
|
|
1239
|
+
return undefined;
|
|
1238
1240
|
}`);
|
|
1239
1241
|
}
|
|
1240
1242
|
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
package/build/options.js
CHANGED
package/build/types.js
CHANGED
|
@@ -411,7 +411,7 @@ function valueTypeName(ctx, typeName) {
|
|
|
411
411
|
case '.google.protobuf.BoolValue':
|
|
412
412
|
return ts_poet_1.code `boolean`;
|
|
413
413
|
case '.google.protobuf.BytesValue':
|
|
414
|
-
return ts_poet_1.code `Uint8Array`;
|
|
414
|
+
return ctx.options.env === options_1.EnvOption.NODE ? ts_poet_1.code `Buffer` : ts_poet_1.code `Uint8Array`;
|
|
415
415
|
case '.google.protobuf.ListValue':
|
|
416
416
|
return ts_poet_1.code `Array<any>`;
|
|
417
417
|
case '.google.protobuf.Value':
|
|
@@ -481,16 +481,16 @@ function messageToTypeName(ctx, protoType, typeOptions = {}) {
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
const [module, type] = toModuleAndType(typeMap, protoType);
|
|
484
|
-
return ts_poet_1.code `${
|
|
484
|
+
return ts_poet_1.code `${utils_1.impProto(options, module, type)}`;
|
|
485
485
|
}
|
|
486
486
|
exports.messageToTypeName = messageToTypeName;
|
|
487
487
|
/** Breaks `.some_proto_namespace.Some.Message` into `['some_proto_namespace', 'Some_Message', Descriptor]. */
|
|
488
488
|
function toModuleAndType(typeMap, protoType) {
|
|
489
489
|
return typeMap.get(protoType) || utils_1.fail(`No type found for ${protoType}`);
|
|
490
490
|
}
|
|
491
|
-
function getEnumMethod(
|
|
492
|
-
const [module, type] = toModuleAndType(typeMap, enumProtoType);
|
|
493
|
-
return
|
|
491
|
+
function getEnumMethod(ctx, enumProtoType, methodSuffix) {
|
|
492
|
+
const [module, type] = toModuleAndType(ctx.typeMap, enumProtoType);
|
|
493
|
+
return utils_1.impProto(ctx.options, module, `${case_1.camelCase(type)}${methodSuffix}`);
|
|
494
494
|
}
|
|
495
495
|
exports.getEnumMethod = getEnumMethod;
|
|
496
496
|
/** Return the TypeName for any field (primitive/message/etc.) as exposed in the interface. */
|
package/build/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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;
|
|
3
|
+
exports.impProto = 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");
|
|
@@ -153,3 +153,7 @@ function determineFieldJsonName(field, options) {
|
|
|
153
153
|
return case_1.maybeSnakeToCamel(field.name, options);
|
|
154
154
|
}
|
|
155
155
|
exports.determineFieldJsonName = determineFieldJsonName;
|
|
156
|
+
function impProto(options, module, type) {
|
|
157
|
+
return ts_poet_1.imp(`${type}@./${module}${options.fileSuffix}`);
|
|
158
|
+
}
|
|
159
|
+
exports.impProto = impProto;
|