ts-proto 2.13.2 → 2.14.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 +4 -0
- package/build/src/generate-type-registry.js +3 -1
- package/build/src/main.d.ts +5 -1
- package/build/src/main.js +134 -3
- package/build/src/options.d.ts +6 -0
- package/build/src/options.js +8 -1
- package/build/src/schema.js +48 -27
- package/build/src/types.d.ts +2 -0
- package/build/src/types.js +8 -0
- package/package.json +1 -1
package/README.markdown
CHANGED
|
@@ -662,6 +662,10 @@ This option allows the library to act in a compatible way with the [Wire impleme
|
|
|
662
662
|
|
|
663
663
|
- With `--ts_proto_opt=useDuration=string`, the generated code will use the `string` type for `google.protobuf.Duration` instead of `{seconds: number, nano: number}`.
|
|
664
664
|
|
|
665
|
+
- With `--ts_proto_opt=anyType=@type` (the default), `google.protobuf.Any` uses its canonical JSON form in `toJSON`/`fromJSON`: the JSON of the packed message with an added `"@type"` key, or `{"@type": ..., "value": ...}` when the packed message is a well-known type with its own JSON form, such as `google.protobuf.Duration`. The packed message type is looked up by name in the type registry, so this needs `outputTypeRegistry=true` (and the default `outputEncodeMethods=true`), and the type must be registered; otherwise `toJSON`/`fromJSON` throw. Without the type registry, `Any` keeps the `{"typeUrl": ..., "value": ...}` form, with `value` base64 encoded.
|
|
666
|
+
|
|
667
|
+
`--ts_proto_opt=anyType=typeUrl` keeps the `{"typeUrl": ..., "value": ...}` form even with the type registry. It is deprecated and may be removed in a future release.
|
|
668
|
+
|
|
665
669
|
### NestJS Support
|
|
666
670
|
|
|
667
671
|
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).
|
|
@@ -7,8 +7,10 @@ function generateTypeRegistry(ctx) {
|
|
|
7
7
|
const chunks = [];
|
|
8
8
|
chunks.push(generateMessageType(ctx));
|
|
9
9
|
if ((0, options_1.addTypeToMessages)(ctx.options)) {
|
|
10
|
+
// With outputTypeAnnotations=optional, messages declare `$type?`, so the registry has to accept them.
|
|
11
|
+
const optional = ctx.options.outputTypeAnnotations === "optional" ? "?" : "";
|
|
10
12
|
chunks.push((0, ts_poet_1.code) `
|
|
11
|
-
export type UnknownMessage = {$type: string};
|
|
13
|
+
export type UnknownMessage = {$type${optional}: string};
|
|
12
14
|
`);
|
|
13
15
|
}
|
|
14
16
|
else {
|
package/build/src/main.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { FileDescriptorProto } from "ts-proto-descriptors";
|
|
|
4
4
|
import { Context } from "./context";
|
|
5
5
|
import { Options } from "./options";
|
|
6
6
|
export declare function generateFile(ctx: Context, fileDesc: FileDescriptorProto): [string, Code];
|
|
7
|
-
export type Utils = ReturnType<typeof makeDeepPartial> & ReturnType<typeof makeObjectIdMethods> & ReturnType<typeof makeTimestampMethods> & ReturnType<typeof makeByteUtils> & ReturnType<typeof makeLongUtils> & ReturnType<typeof makeComparisonUtils> & ReturnType<typeof makeNiceGrpcServerStreamingMethodResult> & ReturnType<typeof makeGrpcWebErrorClass> & ReturnType<typeof makeExtensionClass> & ReturnType<typeof makeAssertionUtils> & ReturnType<typeof makeMessageFns>;
|
|
7
|
+
export type Utils = ReturnType<typeof makeDeepPartial> & ReturnType<typeof makeObjectIdMethods> & ReturnType<typeof makeTimestampMethods> & ReturnType<typeof makeByteUtils> & ReturnType<typeof makeLongUtils> & ReturnType<typeof makeComparisonUtils> & ReturnType<typeof makeNiceGrpcServerStreamingMethodResult> & ReturnType<typeof makeGrpcWebErrorClass> & ReturnType<typeof makeExtensionClass> & ReturnType<typeof makeAssertionUtils> & ReturnType<typeof makeMessageFns> & ReturnType<typeof makeAnyJsonUtils>;
|
|
8
8
|
/** These are runtime utility methods used by the generated code. */
|
|
9
9
|
export declare function makeUtils(options: Options): Utils;
|
|
10
10
|
declare function makeLongUtils(options: Options, bytes: ReturnType<typeof makeByteUtils>): {
|
|
@@ -16,6 +16,7 @@ declare function makeByteUtils(options: Options): {
|
|
|
16
16
|
globalThis: ConditionalOutput;
|
|
17
17
|
bytesFromBase64: ConditionalOutput;
|
|
18
18
|
base64FromBytes: ConditionalOutput;
|
|
19
|
+
floatToJson: ConditionalOutput;
|
|
19
20
|
};
|
|
20
21
|
declare function makeDeepPartial(options: Options, longs: ReturnType<typeof makeLongUtils>): {
|
|
21
22
|
Builtin: ConditionalOutput;
|
|
@@ -42,6 +43,9 @@ declare function makeTimestampMethods(options: Options, longs: ReturnType<typeof
|
|
|
42
43
|
timestampFractionRegex: ConditionalOutput;
|
|
43
44
|
fromJsonTimestamp: ConditionalOutput;
|
|
44
45
|
};
|
|
46
|
+
declare function makeAnyJsonUtils(): {
|
|
47
|
+
anyJsonValueTypes: ConditionalOutput;
|
|
48
|
+
};
|
|
45
49
|
declare function makeComparisonUtils(): {
|
|
46
50
|
isObject: ConditionalOutput;
|
|
47
51
|
isSet: ConditionalOutput;
|
package/build/src/main.js
CHANGED
|
@@ -340,6 +340,7 @@ function makeUtils(options) {
|
|
|
340
340
|
...extension,
|
|
341
341
|
...makeAssertionUtils(bytes),
|
|
342
342
|
...makeMessageFns(options, deepPartial, extension),
|
|
343
|
+
...makeAnyJsonUtils(),
|
|
343
344
|
};
|
|
344
345
|
}
|
|
345
346
|
function makeProtobufTimestampWrapper() {
|
|
@@ -473,7 +474,14 @@ function makeByteUtils(options) {
|
|
|
473
474
|
${getBase64FromBytesSnippet()}
|
|
474
475
|
}
|
|
475
476
|
`);
|
|
476
|
-
|
|
477
|
+
// JSON numbers can't represent NaN or +/-Infinity, so the proto3 JSON mapping
|
|
478
|
+
// writes them as the strings "NaN", "Infinity" and "-Infinity".
|
|
479
|
+
const floatToJson = (0, ts_poet_1.conditionalOutput)("floatToJson", (0, ts_poet_1.code) `
|
|
480
|
+
function floatToJson(value: number | null | undefined): number | string | null | undefined {
|
|
481
|
+
return typeof value === "number" && !${globalThis}.Number.isFinite(value) ? ${globalThis}.String(value) : value;
|
|
482
|
+
}
|
|
483
|
+
`);
|
|
484
|
+
return { globalThis, bytesFromBase64, base64FromBytes, floatToJson };
|
|
477
485
|
}
|
|
478
486
|
function makeDeepPartial(options, longs) {
|
|
479
487
|
let oneofCase = "";
|
|
@@ -823,6 +831,31 @@ function makeTimestampMethods(options, longs, bytes) {
|
|
|
823
831
|
`);
|
|
824
832
|
return { toTimestamp, fromTimestamp, timestampFractionRegex, fromJsonTimestamp };
|
|
825
833
|
}
|
|
834
|
+
function makeAnyJsonUtils() {
|
|
835
|
+
// Well-known types whose JSON is not an object of their fields. Packed in an Any, that
|
|
836
|
+
// JSON goes under "value" rather than next to "@type".
|
|
837
|
+
const anyJsonValueTypes = (0, ts_poet_1.conditionalOutput)("anyJsonValueTypes", (0, ts_poet_1.code) `
|
|
838
|
+
const anyJsonValueTypes: readonly string[] = [
|
|
839
|
+
"google.protobuf.Any",
|
|
840
|
+
"google.protobuf.BoolValue",
|
|
841
|
+
"google.protobuf.BytesValue",
|
|
842
|
+
"google.protobuf.DoubleValue",
|
|
843
|
+
"google.protobuf.Duration",
|
|
844
|
+
"google.protobuf.FieldMask",
|
|
845
|
+
"google.protobuf.FloatValue",
|
|
846
|
+
"google.protobuf.Int32Value",
|
|
847
|
+
"google.protobuf.Int64Value",
|
|
848
|
+
"google.protobuf.ListValue",
|
|
849
|
+
"google.protobuf.StringValue",
|
|
850
|
+
"google.protobuf.Struct",
|
|
851
|
+
"google.protobuf.Timestamp",
|
|
852
|
+
"google.protobuf.UInt32Value",
|
|
853
|
+
"google.protobuf.UInt64Value",
|
|
854
|
+
"google.protobuf.Value",
|
|
855
|
+
];
|
|
856
|
+
`);
|
|
857
|
+
return { anyJsonValueTypes };
|
|
858
|
+
}
|
|
826
859
|
function makeComparisonUtils() {
|
|
827
860
|
const isObject = (0, ts_poet_1.conditionalOutput)("isObject", (0, ts_poet_1.code) `
|
|
828
861
|
function isObject(value: any): boolean {
|
|
@@ -1455,7 +1488,12 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
1455
1488
|
`);
|
|
1456
1489
|
}
|
|
1457
1490
|
else {
|
|
1458
|
-
|
|
1491
|
+
// A packed field with no elements must not be written, not even its tag and length.
|
|
1492
|
+
chunks.push((0, ts_poet_1.code) `
|
|
1493
|
+
if (${messageProperty}.length !== 0) {
|
|
1494
|
+
${listWriteSnippet}
|
|
1495
|
+
}
|
|
1496
|
+
`);
|
|
1459
1497
|
}
|
|
1460
1498
|
}
|
|
1461
1499
|
else {
|
|
@@ -1511,7 +1549,12 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
1511
1549
|
`);
|
|
1512
1550
|
}
|
|
1513
1551
|
else {
|
|
1514
|
-
|
|
1552
|
+
// A packed field with no elements must not be written, not even its tag and length.
|
|
1553
|
+
chunks.push((0, ts_poet_1.code) `
|
|
1554
|
+
if (${messageProperty}.length !== 0) {
|
|
1555
|
+
${listWriteSnippet}
|
|
1556
|
+
}
|
|
1557
|
+
`);
|
|
1515
1558
|
}
|
|
1516
1559
|
}
|
|
1517
1560
|
}
|
|
@@ -1822,6 +1865,9 @@ function generateExtension(ctx, message, extension) {
|
|
|
1822
1865
|
function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
1823
1866
|
const { options, utils, currentFile } = ctx;
|
|
1824
1867
|
const chunks = [];
|
|
1868
|
+
if (fullTypeName === "google.protobuf.Any" && useCanonicalAnyJson(options)) {
|
|
1869
|
+
return generateCanonicalAnyFromJson(ctx, fullName, messageDesc);
|
|
1870
|
+
}
|
|
1825
1871
|
// Handle Duration string format as a special case
|
|
1826
1872
|
if (fullTypeName === "google.protobuf.Duration" && ctx.options.useDuration === options_1.DurationOption.STRING) {
|
|
1827
1873
|
let parseSeconds;
|
|
@@ -2225,9 +2271,83 @@ function generateCanonicalToJson(fullName, fullProtobufTypeName, { useOptionals,
|
|
|
2225
2271
|
}
|
|
2226
2272
|
return undefined;
|
|
2227
2273
|
}
|
|
2274
|
+
/** Whether `google.protobuf.Any` gets its canonical `@type` JSON form, see the `anyType` option. */
|
|
2275
|
+
function useCanonicalAnyJson(options) {
|
|
2276
|
+
// Converting the packed message needs the type registry and its encode/decode methods. Without
|
|
2277
|
+
// them, Any keeps the `{ typeUrl, value }` form even though `@type` is the default.
|
|
2278
|
+
return (options.anyType === options_1.AnyTypeOption.AT_TYPE && options.outputTypeRegistry && options.outputEncodeMethods === true);
|
|
2279
|
+
}
|
|
2280
|
+
/** The `type_url` and `value` fields of `google.protobuf.Any`. */
|
|
2281
|
+
function anyFields(messageDesc) {
|
|
2282
|
+
const typeUrl = messageDesc.field.find((field) => field.number === 1);
|
|
2283
|
+
const value = messageDesc.field.find((field) => field.number === 2);
|
|
2284
|
+
return [typeUrl, value];
|
|
2285
|
+
}
|
|
2286
|
+
/**
|
|
2287
|
+
* The canonical JSON of an `Any` is the JSON of the packed message with an added
|
|
2288
|
+
* `"@type"`, or `{"@type", "value"}` for well-known types with their own JSON form.
|
|
2289
|
+
*/
|
|
2290
|
+
function generateCanonicalAnyToJson(ctx, fullName, messageDesc) {
|
|
2291
|
+
const { options, utils } = ctx;
|
|
2292
|
+
const messageTypeRegistry = (0, utils_1.impFile)(options, "messageTypeRegistry@./typeRegistry");
|
|
2293
|
+
const [typeUrlField, valueField] = anyFields(messageDesc);
|
|
2294
|
+
const typeUrl = (0, utils_1.getPropertyAccessor)("message", (0, utils_1.getFieldName)(typeUrlField, options));
|
|
2295
|
+
const value = (0, utils_1.getPropertyAccessor)("message", (0, utils_1.getFieldName)(valueField, options));
|
|
2296
|
+
return (0, ts_poet_1.code) `
|
|
2297
|
+
toJSON(message: ${fullName}): unknown {
|
|
2298
|
+
const typeUrl = ${typeUrl} ?? "";
|
|
2299
|
+
if (typeUrl === "") {
|
|
2300
|
+
return {};
|
|
2301
|
+
}
|
|
2302
|
+
const typeName = typeUrl.slice(typeUrl.lastIndexOf("/") + 1);
|
|
2303
|
+
const type = ${messageTypeRegistry}.get(typeName);
|
|
2304
|
+
if (type === undefined) {
|
|
2305
|
+
throw new ${utils.globalThis}.Error(\`Cannot convert google.protobuf.Any to JSON: unknown type \${typeName}\`);
|
|
2306
|
+
}
|
|
2307
|
+
const json = type.toJSON(type.decode(${value} ?? new Uint8Array(0)));
|
|
2308
|
+
return ${utils.anyJsonValueTypes}.includes(typeName)
|
|
2309
|
+
? { "@type": typeUrl, value: json }
|
|
2310
|
+
: { "@type": typeUrl, ...(json as object) };
|
|
2311
|
+
}
|
|
2312
|
+
`;
|
|
2313
|
+
}
|
|
2314
|
+
/** The inverse of {@link generateCanonicalAnyToJson}. */
|
|
2315
|
+
function generateCanonicalAnyFromJson(ctx, fullName, messageDesc) {
|
|
2316
|
+
const { options, utils } = ctx;
|
|
2317
|
+
const messageTypeRegistry = (0, utils_1.impFile)(options, "messageTypeRegistry@./typeRegistry");
|
|
2318
|
+
const [typeUrlField, valueField] = anyFields(messageDesc);
|
|
2319
|
+
const typeUrlKey = (0, utils_1.safeAccessor)((0, utils_1.getFieldName)(typeUrlField, options));
|
|
2320
|
+
const valueKey = (0, utils_1.safeAccessor)((0, utils_1.getFieldName)(valueField, options));
|
|
2321
|
+
const typeField = (0, options_1.addTypeToMessages)(options) ? (0, ts_poet_1.code) `$type: ${fullName}.$type,` : "";
|
|
2322
|
+
const bytes = options.env === options_1.EnvOption.NODE ? (0, ts_poet_1.code) `Buffer.from(bytes)` : (0, ts_poet_1.code) `bytes`;
|
|
2323
|
+
return (0, ts_poet_1.code) `
|
|
2324
|
+
fromJSON(object: any): ${fullName} {
|
|
2325
|
+
const typeUrl = ${utils.isSet}(object?.["@type"]) ? ${utils.globalThis}.String(object["@type"]) : "";
|
|
2326
|
+
if (typeUrl === "") {
|
|
2327
|
+
return { ${typeField} ${typeUrlKey}: ${(0, types_1.defaultValue)(ctx, typeUrlField)}, ${valueKey}: ${(0, types_1.defaultValue)(ctx, valueField)} };
|
|
2328
|
+
}
|
|
2329
|
+
const typeName = typeUrl.slice(typeUrl.lastIndexOf("/") + 1);
|
|
2330
|
+
const type = ${messageTypeRegistry}.get(typeName);
|
|
2331
|
+
if (type === undefined) {
|
|
2332
|
+
throw new ${utils.globalThis}.Error(\`Cannot convert JSON to google.protobuf.Any: unknown type \${typeName}\`);
|
|
2333
|
+
}
|
|
2334
|
+
let json = object.value;
|
|
2335
|
+
if (!${utils.anyJsonValueTypes}.includes(typeName)) {
|
|
2336
|
+
json = { ...object };
|
|
2337
|
+
delete json["@type"];
|
|
2338
|
+
}
|
|
2339
|
+
const bytes = type.encode(type.fromJSON(json)).finish();
|
|
2340
|
+
return { ${typeField} ${typeUrlKey}: typeUrl, ${valueKey}: ${bytes} };
|
|
2341
|
+
}
|
|
2342
|
+
`;
|
|
2343
|
+
}
|
|
2228
2344
|
function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
2229
2345
|
const { options, utils, typeMap } = ctx;
|
|
2230
2346
|
const chunks = [];
|
|
2347
|
+
if (fullProtobufTypeName === "google.protobuf.Any" && useCanonicalAnyJson(options)) {
|
|
2348
|
+
chunks.push(generateCanonicalAnyToJson(ctx, fullName, messageDesc));
|
|
2349
|
+
return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
|
|
2350
|
+
}
|
|
2231
2351
|
const canonicalToJson = generateCanonicalToJson(fullName, fullProtobufTypeName, options);
|
|
2232
2352
|
if (canonicalToJson) {
|
|
2233
2353
|
chunks.push(canonicalToJson);
|
|
@@ -2307,6 +2427,9 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
|
2307
2427
|
else if ((0, types_1.isWholeNumber)(valueType) && !((0, types_1.isLong)(valueType) && options.forceLong === options_1.LongOption.STRING)) {
|
|
2308
2428
|
return (0, ts_poet_1.code) `Math.round(${from})`;
|
|
2309
2429
|
}
|
|
2430
|
+
else if ((0, types_1.isFloatingPoint)(valueType)) {
|
|
2431
|
+
return (0, ts_poet_1.code) `${utils.floatToJson}(${from})`;
|
|
2432
|
+
}
|
|
2310
2433
|
else if ((0, types_1.isScalar)(valueType) || (0, types_1.isValueType)(ctx, valueType)) {
|
|
2311
2434
|
return (0, ts_poet_1.code) `${from}`;
|
|
2312
2435
|
}
|
|
@@ -2349,6 +2472,9 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
|
2349
2472
|
else if ((0, types_1.isWholeNumber)(field) && !((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.STRING)) {
|
|
2350
2473
|
return (0, ts_poet_1.code) `Math.round(${from})`;
|
|
2351
2474
|
}
|
|
2475
|
+
else if ((0, types_1.isFloatingPoint)(field)) {
|
|
2476
|
+
return (0, ts_poet_1.code) `${utils.floatToJson}(${from})`;
|
|
2477
|
+
}
|
|
2352
2478
|
else {
|
|
2353
2479
|
return (0, ts_poet_1.code) `${from}`;
|
|
2354
2480
|
}
|
|
@@ -2610,6 +2736,11 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
2610
2736
|
`);
|
|
2611
2737
|
currentSwitchTarget = oneofNameWithObject;
|
|
2612
2738
|
}
|
|
2739
|
+
else if ((0, types_1.isAnyValueType)(field)) {
|
|
2740
|
+
// null is a valid google.protobuf.Value (NullValue), so only an absent value gets the fallback.
|
|
2741
|
+
const fallback = (0, types_1.isWithinOneOf)(field) || noDefaultValue ? "undefined" : (0, types_1.defaultValue)(ctx, field);
|
|
2742
|
+
chunks.push((0, ts_poet_1.code) `${messageProperty} = ${objectProperty} === undefined ? ${fallback} : ${objectProperty};`);
|
|
2743
|
+
}
|
|
2613
2744
|
else if (readSnippet(`x`).toCodeString([]) == "x") {
|
|
2614
2745
|
// An optimized case of the else below that works when `readSnippet` returns the plain input
|
|
2615
2746
|
const fallback = (0, types_1.isWithinOneOf)(field) || noDefaultValue ? "undefined" : (0, types_1.defaultValue)(ctx, field);
|
package/build/src/options.d.ts
CHANGED
|
@@ -20,6 +20,11 @@ export declare enum DurationOption {
|
|
|
20
20
|
DURATION = "duration",
|
|
21
21
|
STRING = "string"
|
|
22
22
|
}
|
|
23
|
+
export declare enum AnyTypeOption {
|
|
24
|
+
/** @deprecated Kept for existing users of the `{ typeUrl, value }` JSON form; may be removed in the future. */
|
|
25
|
+
TYPE_URL = "typeUrl",
|
|
26
|
+
AT_TYPE = "@type"
|
|
27
|
+
}
|
|
23
28
|
export declare enum EnvOption {
|
|
24
29
|
NODE = "node",
|
|
25
30
|
BROWSER = "browser",
|
|
@@ -116,6 +121,7 @@ export type Options = {
|
|
|
116
121
|
typePrefix: string;
|
|
117
122
|
typeSuffix: string;
|
|
118
123
|
useDuration: DurationOption;
|
|
124
|
+
anyType: AnyTypeOption;
|
|
119
125
|
};
|
|
120
126
|
export declare function defaultOptions(): Options;
|
|
121
127
|
export declare function optionsFromParameter(parameter: string | undefined): Options;
|
package/build/src/options.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OutputSchemaOption = exports.ServiceOption = exports.OneofOption = exports.EnvOption = exports.DurationOption = exports.JsonTimestampOption = exports.DateOption = exports.LongOption = void 0;
|
|
3
|
+
exports.OutputSchemaOption = exports.ServiceOption = exports.OneofOption = exports.EnvOption = exports.AnyTypeOption = exports.DurationOption = exports.JsonTimestampOption = exports.DateOption = exports.LongOption = void 0;
|
|
4
4
|
exports.defaultOptions = defaultOptions;
|
|
5
5
|
exports.optionsFromParameter = optionsFromParameter;
|
|
6
6
|
exports.getTsPoetOpts = getTsPoetOpts;
|
|
@@ -30,6 +30,12 @@ var DurationOption;
|
|
|
30
30
|
DurationOption["DURATION"] = "duration";
|
|
31
31
|
DurationOption["STRING"] = "string";
|
|
32
32
|
})(DurationOption || (exports.DurationOption = DurationOption = {}));
|
|
33
|
+
var AnyTypeOption;
|
|
34
|
+
(function (AnyTypeOption) {
|
|
35
|
+
/** @deprecated Kept for existing users of the `{ typeUrl, value }` JSON form; may be removed in the future. */
|
|
36
|
+
AnyTypeOption["TYPE_URL"] = "typeUrl";
|
|
37
|
+
AnyTypeOption["AT_TYPE"] = "@type";
|
|
38
|
+
})(AnyTypeOption || (exports.AnyTypeOption = AnyTypeOption = {}));
|
|
33
39
|
var EnvOption;
|
|
34
40
|
(function (EnvOption) {
|
|
35
41
|
EnvOption["NODE"] = "node";
|
|
@@ -129,6 +135,7 @@ function defaultOptions() {
|
|
|
129
135
|
typePrefix: "",
|
|
130
136
|
typeSuffix: "",
|
|
131
137
|
useDuration: DurationOption.DURATION,
|
|
138
|
+
anyType: AnyTypeOption.AT_TYPE,
|
|
132
139
|
};
|
|
133
140
|
}
|
|
134
141
|
const nestJsOptions = {
|
package/build/src/schema.js
CHANGED
|
@@ -23,11 +23,17 @@ function generateSchema(ctx, fileDesc, sourceInfo) {
|
|
|
23
23
|
const outputFileDescriptor = !outputSchemaOptions.includes(options_1.OutputSchemaOption.NO_FILE_DESCRIPTOR);
|
|
24
24
|
const outputAsConst = outputSchemaOptions.includes(options_1.OutputSchemaOption.CONST);
|
|
25
25
|
chunks.push((0, ts_poet_1.code) `
|
|
26
|
+
type ProtoMetaEnumOptions = {
|
|
27
|
+
options?: { [key: string]: any };
|
|
28
|
+
values?: { [key: string]: { [key: string]: any } };
|
|
29
|
+
};
|
|
30
|
+
|
|
26
31
|
type ProtoMetaMessageOptions = {
|
|
27
32
|
options?: { [key: string]: any };
|
|
28
33
|
fields?: { [key: string]: { [key: string]: any } };
|
|
29
34
|
oneof?: { [key: string]: { [key: string]: any } };
|
|
30
35
|
nested?: { [key: string]: ProtoMetaMessageOptions };
|
|
36
|
+
enums?: { [key: string]: ProtoMetaEnumOptions };
|
|
31
37
|
};
|
|
32
38
|
|
|
33
39
|
export interface ProtoMetadata {
|
|
@@ -45,10 +51,7 @@ function generateSchema(ctx, fileDesc, sourceInfo) {
|
|
|
45
51
|
[key: string]: ProtoMetaMessageOptions;
|
|
46
52
|
};
|
|
47
53
|
enums?: {
|
|
48
|
-
[key: string]:
|
|
49
|
-
options?: { [key: string]: any };
|
|
50
|
-
values?: { [key: string]: { [key: string]: any } };
|
|
51
|
-
};
|
|
54
|
+
[key: string]: ProtoMetaEnumOptions;
|
|
52
55
|
};
|
|
53
56
|
};
|
|
54
57
|
}
|
|
@@ -119,28 +122,9 @@ function generateSchema(ctx, fileDesc, sourceInfo) {
|
|
|
119
122
|
});
|
|
120
123
|
const enumsOptions = [];
|
|
121
124
|
(fileDesc.enumType || []).forEach((Enum) => {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const valueOptions = encodedOptionsToOptions(ctx, ".google.protobuf.EnumValueOptions", value.options._unknownFields);
|
|
126
|
-
delete value.options._unknownFields;
|
|
127
|
-
if (valueOptions) {
|
|
128
|
-
valuesOptions.push((0, ts_poet_1.code) `'${value.name}': ${valueOptions}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
let enumOptions;
|
|
133
|
-
if (Enum.options) {
|
|
134
|
-
enumOptions = encodedOptionsToOptions(ctx, ".google.protobuf.EnumOptions", Enum.options._unknownFields);
|
|
135
|
-
delete Enum.options._unknownFields;
|
|
136
|
-
}
|
|
137
|
-
if (valuesOptions.length > 0 || enumOptions) {
|
|
138
|
-
enumsOptions.push((0, ts_poet_1.code) `
|
|
139
|
-
'${Enum.name}': {
|
|
140
|
-
${enumOptions ? (0, ts_poet_1.code) `options: ${enumOptions},` : ""}
|
|
141
|
-
values: {${(0, ts_poet_1.joinCode)(valuesOptions, { on: "," })}}
|
|
142
|
-
}
|
|
143
|
-
`);
|
|
125
|
+
const resolvedEnum = resolveEnumOptions(ctx, Enum);
|
|
126
|
+
if (resolvedEnum) {
|
|
127
|
+
enumsOptions.push(resolvedEnum);
|
|
144
128
|
}
|
|
145
129
|
});
|
|
146
130
|
chunks.push((0, ts_poet_1.code) `
|
|
@@ -247,18 +231,55 @@ function resolveMessageOptions(ctx, message) {
|
|
|
247
231
|
}
|
|
248
232
|
});
|
|
249
233
|
}
|
|
234
|
+
const enumsOptions = [];
|
|
235
|
+
(message.enumType || []).forEach((Enum) => {
|
|
236
|
+
const resolvedEnum = resolveEnumOptions(ctx, Enum);
|
|
237
|
+
if (resolvedEnum) {
|
|
238
|
+
enumsOptions.push(resolvedEnum);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
250
241
|
let messageOptions;
|
|
251
242
|
if (message.options) {
|
|
252
243
|
messageOptions = encodedOptionsToOptions(ctx, ".google.protobuf.MessageOptions", message.options._unknownFields);
|
|
253
244
|
delete message.options._unknownFields;
|
|
254
245
|
}
|
|
255
|
-
if (fieldsOptions.length > 0 ||
|
|
246
|
+
if (fieldsOptions.length > 0 ||
|
|
247
|
+
oneOfsOptions.length > 0 ||
|
|
248
|
+
nestedOptions.length > 0 ||
|
|
249
|
+
enumsOptions.length > 0 ||
|
|
250
|
+
messageOptions) {
|
|
256
251
|
return (0, ts_poet_1.code) `
|
|
257
252
|
'${message.name}': {
|
|
258
253
|
${messageOptions ? (0, ts_poet_1.code) `options: ${messageOptions},` : ""}
|
|
259
254
|
${fieldsOptions.length > 0 ? (0, ts_poet_1.code) `fields: {${(0, ts_poet_1.joinCode)(fieldsOptions, { on: "," })}},` : ""}
|
|
260
255
|
${oneOfsOptions.length > 0 ? (0, ts_poet_1.code) `oneof: {${(0, ts_poet_1.joinCode)(oneOfsOptions, { on: "," })}},` : ""}
|
|
261
256
|
${nestedOptions.length > 0 ? (0, ts_poet_1.code) `nested: {${(0, ts_poet_1.joinCode)(nestedOptions, { on: "," })}},` : ""}
|
|
257
|
+
${enumsOptions.length > 0 ? (0, ts_poet_1.code) `enums: {${(0, ts_poet_1.joinCode)(enumsOptions, { on: "," })}},` : ""}
|
|
258
|
+
}
|
|
259
|
+
`;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function resolveEnumOptions(ctx, Enum) {
|
|
263
|
+
const valuesOptions = [];
|
|
264
|
+
Enum.value.forEach((value) => {
|
|
265
|
+
if (value.options) {
|
|
266
|
+
const valueOptions = encodedOptionsToOptions(ctx, ".google.protobuf.EnumValueOptions", value.options._unknownFields);
|
|
267
|
+
delete value.options._unknownFields;
|
|
268
|
+
if (valueOptions) {
|
|
269
|
+
valuesOptions.push((0, ts_poet_1.code) `'${value.name}': ${valueOptions}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
let enumOptions;
|
|
274
|
+
if (Enum.options) {
|
|
275
|
+
enumOptions = encodedOptionsToOptions(ctx, ".google.protobuf.EnumOptions", Enum.options._unknownFields);
|
|
276
|
+
delete Enum.options._unknownFields;
|
|
277
|
+
}
|
|
278
|
+
if (valuesOptions.length > 0 || enumOptions) {
|
|
279
|
+
return (0, ts_poet_1.code) `
|
|
280
|
+
'${Enum.name}': {
|
|
281
|
+
${enumOptions ? (0, ts_poet_1.code) `options: ${enumOptions},` : ""}
|
|
282
|
+
values: {${(0, ts_poet_1.joinCode)(valuesOptions, { on: "," })}}
|
|
262
283
|
}
|
|
263
284
|
`;
|
|
264
285
|
}
|
package/build/src/types.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ export declare function isWithinOneOfThatShouldBeUnion(options: Options, field:
|
|
|
34
34
|
export declare function isRepeated(field: FieldDescriptorProto): boolean;
|
|
35
35
|
export declare function isLong(field: FieldDescriptorProto): boolean;
|
|
36
36
|
export declare function isWholeNumber(field: FieldDescriptorProto): boolean;
|
|
37
|
+
/** Whether `field` holds a JS number that may be non-finite: a double/float or its wrapper type. */
|
|
38
|
+
export declare function isFloatingPoint(field: FieldDescriptorProto): boolean;
|
|
37
39
|
export declare function isMapType(ctx: Context, messageDesc: DescriptorProto, field: FieldDescriptorProto): boolean;
|
|
38
40
|
export declare function isObjectId(field: FieldDescriptorProto): boolean;
|
|
39
41
|
export declare function isTimestamp(field: FieldDescriptorProto): boolean;
|
package/build/src/types.js
CHANGED
|
@@ -21,6 +21,7 @@ exports.isWithinOneOfThatShouldBeUnion = isWithinOneOfThatShouldBeUnion;
|
|
|
21
21
|
exports.isRepeated = isRepeated;
|
|
22
22
|
exports.isLong = isLong;
|
|
23
23
|
exports.isWholeNumber = isWholeNumber;
|
|
24
|
+
exports.isFloatingPoint = isFloatingPoint;
|
|
24
25
|
exports.isMapType = isMapType;
|
|
25
26
|
exports.isObjectId = isObjectId;
|
|
26
27
|
exports.isTimestamp = isTimestamp;
|
|
@@ -467,6 +468,13 @@ function isWholeNumber(field) {
|
|
|
467
468
|
field.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED32 ||
|
|
468
469
|
field.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED64);
|
|
469
470
|
}
|
|
471
|
+
/** Whether `field` holds a JS number that may be non-finite: a double/float or its wrapper type. */
|
|
472
|
+
function isFloatingPoint(field) {
|
|
473
|
+
return (field.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_DOUBLE ||
|
|
474
|
+
field.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FLOAT ||
|
|
475
|
+
field.typeName === ".google.protobuf.DoubleValue" ||
|
|
476
|
+
field.typeName === ".google.protobuf.FloatValue");
|
|
477
|
+
}
|
|
470
478
|
function isMapType(ctx, messageDesc, field) {
|
|
471
479
|
return detectMapType(ctx, messageDesc, field) !== undefined;
|
|
472
480
|
}
|