@bufbuild/protoc-gen-es 1.7.1 → 1.8.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.md +11 -1
- package/dist/cjs/package.json +4 -4
- package/dist/cjs/src/declaration.js +9 -9
- package/dist/cjs/src/javascript.js +17 -12
- package/dist/cjs/src/typescript.js +20 -14
- package/dist/cjs/src/util.js +260 -0
- package/package.json +4 -4
- package/src/declaration.ts +15 -19
- package/src/javascript.ts +9 -9
- package/src/typescript.ts +20 -21
- package/src/util.ts +315 -0
package/README.md
CHANGED
|
@@ -118,7 +118,6 @@ Possible values:
|
|
|
118
118
|
the default behavior.
|
|
119
119
|
- `js_import_style=legacy_commonjs` generate CommonJS `require()` calls.
|
|
120
120
|
|
|
121
|
-
|
|
122
121
|
### `keep_empty_files=true`
|
|
123
122
|
|
|
124
123
|
By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es)
|
|
@@ -127,3 +126,14 @@ omit empty files from the plugin output. This option disables pruning of
|
|
|
127
126
|
empty files, to allow for smooth interoperation with Bazel and similar
|
|
128
127
|
tooling that requires all output files to be declared ahead of time.
|
|
129
128
|
Unless you use Bazel, it is very unlikely that you need this option.
|
|
129
|
+
|
|
130
|
+
### `ts_nocheck=false`
|
|
131
|
+
|
|
132
|
+
By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es)
|
|
133
|
+
(and all other plugins based on [@bufbuild/protoplugin](https://www.npmjs.com/package/@bufbuild/protoplugin))
|
|
134
|
+
generate an annotation at the top of each file: `// @ts-nocheck`.
|
|
135
|
+
|
|
136
|
+
We generate the annotation to support a wide range of compiler configurations and
|
|
137
|
+
future changes to the language. But there can be situations where the annotation
|
|
138
|
+
shadows an underlying problem, for example an unresolvable import. To remove
|
|
139
|
+
the annotation and to enable type checks, set the plugin option `ts_nocheck=false`.
|
package/dist/cjs/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bufbuild/protoc-gen-es",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Protocol Buffers code generator for ECMAScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
},
|
|
21
21
|
"preferUnplugged": true,
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@bufbuild/protobuf": "^1.
|
|
24
|
-
"@bufbuild/protoplugin": "1.
|
|
23
|
+
"@bufbuild/protobuf": "^1.8.0",
|
|
24
|
+
"@bufbuild/protoplugin": "1.8.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@bufbuild/protobuf": "1.
|
|
27
|
+
"@bufbuild/protobuf": "1.8.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependenciesMeta": {
|
|
30
30
|
"@bufbuild/protobuf": {
|
|
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
16
16
|
exports.generateDts = void 0;
|
|
17
17
|
const ecmascript_1 = require("@bufbuild/protoplugin/ecmascript");
|
|
18
18
|
const editions_js_1 = require("./editions.js");
|
|
19
|
+
const util_js_1 = require("./util.js");
|
|
19
20
|
function generateDts(schema) {
|
|
20
21
|
for (const file of schema.files) {
|
|
21
22
|
const f = schema.generateFile(file.name + "_pb.d.ts");
|
|
@@ -102,29 +103,28 @@ function generateOneof(schema, f, oneof) {
|
|
|
102
103
|
f.print(` } | {`);
|
|
103
104
|
}
|
|
104
105
|
f.print(f.jsDoc(field, " "));
|
|
105
|
-
const { typing } = (0,
|
|
106
|
+
const { typing } = (0, util_js_1.getFieldTypeInfo)(field);
|
|
106
107
|
f.print(` value: `, typing, `;`);
|
|
107
108
|
f.print(` case: "`, (0, ecmascript_1.localName)(field), `";`);
|
|
108
109
|
}
|
|
109
110
|
f.print(` } | { case: undefined; value?: undefined };`);
|
|
110
111
|
}
|
|
112
|
+
// prettier-ignore
|
|
111
113
|
function generateField(schema, f, field) {
|
|
112
114
|
f.print(f.jsDoc(field, " "));
|
|
113
115
|
const e = [];
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
e.push("?: ", typing);
|
|
116
|
+
const { typing, optional } = (0, util_js_1.getFieldTypeInfo)(field);
|
|
117
|
+
if (!optional) {
|
|
118
|
+
e.push(" ", (0, ecmascript_1.localName)(field), ": ", typing, ";");
|
|
118
119
|
}
|
|
119
120
|
else {
|
|
120
|
-
e.push("
|
|
121
|
+
e.push(" ", (0, ecmascript_1.localName)(field), "?: ", typing, ";");
|
|
121
122
|
}
|
|
122
|
-
e.push(";");
|
|
123
123
|
f.print(e);
|
|
124
124
|
}
|
|
125
125
|
// prettier-ignore
|
|
126
126
|
function generateExtension(schema, f, ext) {
|
|
127
|
-
const { typing } = (0,
|
|
127
|
+
const { typing } = (0, util_js_1.getFieldTypeInfo)(ext);
|
|
128
128
|
f.print(f.jsDoc(ext));
|
|
129
129
|
f.print(f.exportDecl("declare const", ext), ": ", schema.runtime.Extension, "<", ext.extendee, ", ", typing, ">;");
|
|
130
130
|
f.print();
|
|
@@ -198,7 +198,7 @@ function generateWktStaticMethods(schema, f, message) {
|
|
|
198
198
|
case "google.protobuf.BoolValue":
|
|
199
199
|
case "google.protobuf.StringValue":
|
|
200
200
|
case "google.protobuf.BytesValue": {
|
|
201
|
-
const { typing } = (0,
|
|
201
|
+
const { typing } = (0, util_js_1.getFieldTypeInfo)(ref.value);
|
|
202
202
|
f.print(" static readonly fieldWrapper: {");
|
|
203
203
|
f.print(" wrapField(value: ", typing, "): ", message, ",");
|
|
204
204
|
f.print(" unwrapField(value: ", message, "): ", typing, ",");
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.getFieldInfoLiteral = exports.generateFieldInfo = exports.generateJs = void 0;
|
|
17
17
|
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
|
+
const protobuf_2 = require("@bufbuild/protobuf");
|
|
18
19
|
const ecmascript_1 = require("@bufbuild/protoplugin/ecmascript");
|
|
19
20
|
const editions_js_1 = require("./editions.js");
|
|
21
|
+
const util_js_1 = require("./util.js");
|
|
20
22
|
function generateJs(schema) {
|
|
21
23
|
for (const file of schema.files) {
|
|
22
24
|
const f = schema.generateFile(file.name + "_pb.js");
|
|
@@ -38,7 +40,7 @@ exports.generateJs = generateJs;
|
|
|
38
40
|
function generateEnum(schema, f, enumeration) {
|
|
39
41
|
const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, enumeration.file);
|
|
40
42
|
f.print(f.jsDoc(enumeration));
|
|
41
|
-
f.print(f.exportDecl("const", enumeration), " = ", protoN, ".makeEnum(");
|
|
43
|
+
f.print(f.exportDecl("const", enumeration), " = /*@__PURE__*/ ", protoN, ".makeEnum(");
|
|
42
44
|
f.print(` "`, enumeration.typeName, `",`);
|
|
43
45
|
f.print(` [`);
|
|
44
46
|
if (enumeration.sharedPrefix === undefined) {
|
|
@@ -60,7 +62,7 @@ function generateEnum(schema, f, enumeration) {
|
|
|
60
62
|
function generateMessage(schema, f, message) {
|
|
61
63
|
const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, message.file);
|
|
62
64
|
f.print(f.jsDoc(message));
|
|
63
|
-
f.print(f.exportDecl("const", message), " = ", protoN, ".makeMessageType(");
|
|
65
|
+
f.print(f.exportDecl("const", message), " = /*@__PURE__*/ ", protoN, ".makeMessageType(");
|
|
64
66
|
f.print(` `, f.string(message.typeName), `,`);
|
|
65
67
|
if (message.fields.length == 0) {
|
|
66
68
|
f.print(" [],");
|
|
@@ -73,7 +75,7 @@ function generateMessage(schema, f, message) {
|
|
|
73
75
|
f.print(" ],");
|
|
74
76
|
}
|
|
75
77
|
const needsLocalName = (0, ecmascript_1.localName)(message) !==
|
|
76
|
-
(message.file.syntax == "proto3" ?
|
|
78
|
+
(message.file.syntax == "proto3" ? protobuf_2.proto2 : protobuf_2.proto3)
|
|
77
79
|
.makeMessageType(message.typeName, []).name;
|
|
78
80
|
if (needsLocalName) {
|
|
79
81
|
// local name is not inferrable from the type name, we need to provide it
|
|
@@ -111,16 +113,16 @@ function getFieldInfoLiteral(schema, field) {
|
|
|
111
113
|
}
|
|
112
114
|
switch (field.fieldKind) {
|
|
113
115
|
case "scalar":
|
|
114
|
-
e.push(`kind: "scalar", T: `, field.scalar, ` /* ScalarType.`,
|
|
115
|
-
if (field.longType !=
|
|
116
|
-
e.push(`L: `, field.longType, ` /* LongType.`,
|
|
116
|
+
e.push(`kind: "scalar", T: `, field.scalar, ` /* ScalarType.`, protobuf_2.ScalarType[field.scalar], ` */, `);
|
|
117
|
+
if (field.longType != protobuf_2.LongType.BIGINT) {
|
|
118
|
+
e.push(`L: `, field.longType, ` /* LongType.`, protobuf_2.LongType[field.longType], ` */, `);
|
|
117
119
|
}
|
|
118
120
|
break;
|
|
119
121
|
case "map":
|
|
120
|
-
e.push(`kind: "map", K: `, field.mapKey, ` /* ScalarType.`,
|
|
122
|
+
e.push(`kind: "map", K: `, field.mapKey, ` /* ScalarType.`, protobuf_2.ScalarType[field.mapKey], ` */, `);
|
|
121
123
|
switch (field.mapValue.kind) {
|
|
122
124
|
case "scalar":
|
|
123
|
-
e.push(`V: {kind: "scalar", T: `, field.mapValue.scalar, ` /* ScalarType.`,
|
|
125
|
+
e.push(`V: {kind: "scalar", T: `, field.mapValue.scalar, ` /* ScalarType.`, protobuf_2.ScalarType[field.mapValue.scalar], ` */}, `);
|
|
124
126
|
break;
|
|
125
127
|
case "message":
|
|
126
128
|
e.push(`V: {kind: "message", T: `, field.mapValue.message, `}, `);
|
|
@@ -132,7 +134,7 @@ function getFieldInfoLiteral(schema, field) {
|
|
|
132
134
|
break;
|
|
133
135
|
case "message":
|
|
134
136
|
e.push(`kind: "message", T: `, field.message, `, `);
|
|
135
|
-
if (field.proto.type ===
|
|
137
|
+
if (field.proto.type === protobuf_2.FieldDescriptorProto_Type.GROUP) {
|
|
136
138
|
e.push(`delimited: true, `);
|
|
137
139
|
}
|
|
138
140
|
break;
|
|
@@ -149,7 +151,10 @@ function getFieldInfoLiteral(schema, field) {
|
|
|
149
151
|
if (field.optional) {
|
|
150
152
|
e.push(`opt: true, `);
|
|
151
153
|
}
|
|
152
|
-
|
|
154
|
+
else if (field.proto.label === protobuf_1.FieldDescriptorProto_Label.REQUIRED) {
|
|
155
|
+
e.push(`req: true, `);
|
|
156
|
+
}
|
|
157
|
+
const defaultValue = (0, util_js_1.getFieldDefaultValueExpression)(field);
|
|
153
158
|
if (defaultValue !== undefined) {
|
|
154
159
|
e.push(`default: `, defaultValue, `, `);
|
|
155
160
|
}
|
|
@@ -544,12 +549,12 @@ function generateWktMethods(schema, f, message) {
|
|
|
544
549
|
case "google.protobuf.StringValue":
|
|
545
550
|
case "google.protobuf.BytesValue":
|
|
546
551
|
f.print(message, ".prototype.toJson = function toJson(options) {");
|
|
547
|
-
f.print(" return proto3.json.writeScalar(", rtScalarType, ".",
|
|
552
|
+
f.print(" return proto3.json.writeScalar(", rtScalarType, ".", protobuf_2.ScalarType[ref.value.scalar], ", this.value, true);");
|
|
548
553
|
f.print("}");
|
|
549
554
|
f.print();
|
|
550
555
|
f.print(message, ".prototype.fromJson = function fromJson(json, options) {");
|
|
551
556
|
f.print(" try {");
|
|
552
|
-
f.print(" this.value = ", protoN, ".json.readScalar(", rtScalarType, ".",
|
|
557
|
+
f.print(" this.value = ", protoN, ".json.readScalar(", rtScalarType, ".", protobuf_2.ScalarType[ref.value.scalar], ", json);");
|
|
553
558
|
f.print(" } catch (e) {");
|
|
554
559
|
f.print(" let m = `cannot decode message ", message.typeName, " from JSON\"`;");
|
|
555
560
|
f.print(" if (e instanceof Error && e.message.length > 0) {");
|
|
@@ -18,6 +18,7 @@ const protobuf_1 = require("@bufbuild/protobuf");
|
|
|
18
18
|
const ecmascript_1 = require("@bufbuild/protoplugin/ecmascript");
|
|
19
19
|
const javascript_js_1 = require("./javascript.js");
|
|
20
20
|
const editions_js_1 = require("./editions.js");
|
|
21
|
+
const util_js_1 = require("./util.js");
|
|
21
22
|
function generateTs(schema) {
|
|
22
23
|
for (const file of schema.files) {
|
|
23
24
|
const f = schema.generateFile(file.name + "_pb.ts");
|
|
@@ -126,34 +127,39 @@ function generateOneof(schema, f, oneof) {
|
|
|
126
127
|
f.print(` } | {`);
|
|
127
128
|
}
|
|
128
129
|
f.print(f.jsDoc(field, " "));
|
|
129
|
-
const { typing } = (0,
|
|
130
|
+
const { typing } = (0, util_js_1.getFieldTypeInfo)(field);
|
|
130
131
|
f.print(` value: `, typing, `;`);
|
|
131
132
|
f.print(` case: "`, (0, ecmascript_1.localName)(field), `";`);
|
|
132
133
|
}
|
|
133
134
|
f.print(` } | { case: undefined; value?: undefined } = { case: undefined };`);
|
|
134
135
|
}
|
|
136
|
+
// prettier-ignore
|
|
135
137
|
function generateField(schema, f, field) {
|
|
136
138
|
f.print(f.jsDoc(field, " "));
|
|
137
139
|
const e = [];
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (optional || defaultValue === undefined) {
|
|
142
|
-
e.push("?: ", typing);
|
|
143
|
-
}
|
|
144
|
-
else if (!typingInferrable) {
|
|
145
|
-
e.push(": ", typing);
|
|
140
|
+
const { typing, optional, typingInferrableFromZeroValue } = (0, util_js_1.getFieldTypeInfo)(field);
|
|
141
|
+
if (optional) {
|
|
142
|
+
e.push(" ", (0, ecmascript_1.localName)(field), "?: ", typing, ";");
|
|
146
143
|
}
|
|
147
|
-
|
|
148
|
-
|
|
144
|
+
else {
|
|
145
|
+
if (typingInferrableFromZeroValue) {
|
|
146
|
+
e.push(" ", (0, ecmascript_1.localName)(field));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
e.push(" ", (0, ecmascript_1.localName)(field), ": ", typing);
|
|
150
|
+
}
|
|
151
|
+
const zeroValue = (0, util_js_1.getFieldZeroValueExpression)(field);
|
|
152
|
+
if (zeroValue !== undefined) {
|
|
153
|
+
e.push(" = ", zeroValue);
|
|
154
|
+
}
|
|
155
|
+
e.push(";");
|
|
149
156
|
}
|
|
150
|
-
e.push(";");
|
|
151
157
|
f.print(e);
|
|
152
158
|
}
|
|
153
159
|
// prettier-ignore
|
|
154
160
|
function generateExtension(schema, f, ext) {
|
|
155
161
|
const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, ext.file);
|
|
156
|
-
const { typing } = (0,
|
|
162
|
+
const { typing } = (0, util_js_1.getFieldTypeInfo)(ext);
|
|
157
163
|
f.print(f.jsDoc(ext));
|
|
158
164
|
f.print(f.exportDecl("const", ext), " = ", protoN, ".makeExtension<", ext.extendee, ", ", typing, ">(");
|
|
159
165
|
f.print(" ", f.string(ext.typeName), ", ");
|
|
@@ -611,7 +617,7 @@ function generateWktStaticMethods(schema, f, message) {
|
|
|
611
617
|
case "google.protobuf.BoolValue":
|
|
612
618
|
case "google.protobuf.StringValue":
|
|
613
619
|
case "google.protobuf.BytesValue": {
|
|
614
|
-
const { typing } = (0,
|
|
620
|
+
const { typing } = (0, util_js_1.getFieldTypeInfo)(ref.value);
|
|
615
621
|
f.print(" static readonly fieldWrapper = {");
|
|
616
622
|
f.print(" wrapField(value: ", typing, "): ", message, " {");
|
|
617
623
|
f.print(" return new ", message, "({value});");
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2021-2024 Buf Technologies, Inc.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.getFieldZeroValueExpression = exports.getFieldDefaultValueExpression = exports.getFieldTypeInfo = void 0;
|
|
17
|
+
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
|
+
const ecmascript_1 = require("@bufbuild/protoplugin/ecmascript");
|
|
19
|
+
function getFieldTypeInfo(field) {
|
|
20
|
+
const typing = [];
|
|
21
|
+
let typingInferrableFromZeroValue;
|
|
22
|
+
let optional = false;
|
|
23
|
+
switch (field.fieldKind) {
|
|
24
|
+
case "scalar":
|
|
25
|
+
typing.push(scalarTypeScriptType(field.scalar, field.longType));
|
|
26
|
+
optional =
|
|
27
|
+
field.optional ||
|
|
28
|
+
field.proto.label === protobuf_1.FieldDescriptorProto_Label.REQUIRED;
|
|
29
|
+
typingInferrableFromZeroValue = true;
|
|
30
|
+
break;
|
|
31
|
+
case "message": {
|
|
32
|
+
const baseType = protobuf_1.codegenInfo.getUnwrappedFieldType(field);
|
|
33
|
+
if (baseType !== undefined) {
|
|
34
|
+
typing.push(scalarTypeScriptType(baseType, protobuf_1.LongType.BIGINT));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
typing.push({
|
|
38
|
+
kind: "es_ref_message",
|
|
39
|
+
type: field.message,
|
|
40
|
+
typeOnly: true,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
optional = true;
|
|
44
|
+
typingInferrableFromZeroValue = true;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case "enum":
|
|
48
|
+
typing.push({
|
|
49
|
+
kind: "es_ref_enum",
|
|
50
|
+
type: field.enum,
|
|
51
|
+
typeOnly: true,
|
|
52
|
+
});
|
|
53
|
+
optional =
|
|
54
|
+
field.optional ||
|
|
55
|
+
field.proto.label === protobuf_1.FieldDescriptorProto_Label.REQUIRED;
|
|
56
|
+
typingInferrableFromZeroValue = true;
|
|
57
|
+
break;
|
|
58
|
+
case "map": {
|
|
59
|
+
let keyType;
|
|
60
|
+
switch (field.mapKey) {
|
|
61
|
+
case protobuf_1.ScalarType.INT32:
|
|
62
|
+
case protobuf_1.ScalarType.FIXED32:
|
|
63
|
+
case protobuf_1.ScalarType.UINT32:
|
|
64
|
+
case protobuf_1.ScalarType.SFIXED32:
|
|
65
|
+
case protobuf_1.ScalarType.SINT32:
|
|
66
|
+
keyType = "number";
|
|
67
|
+
break;
|
|
68
|
+
default:
|
|
69
|
+
keyType = "string";
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
let valueType;
|
|
73
|
+
switch (field.mapValue.kind) {
|
|
74
|
+
case "scalar":
|
|
75
|
+
valueType = scalarTypeScriptType(field.mapValue.scalar, protobuf_1.LongType.BIGINT);
|
|
76
|
+
break;
|
|
77
|
+
case "message":
|
|
78
|
+
valueType = {
|
|
79
|
+
kind: "es_ref_message",
|
|
80
|
+
type: field.mapValue.message,
|
|
81
|
+
typeOnly: true,
|
|
82
|
+
};
|
|
83
|
+
break;
|
|
84
|
+
case "enum":
|
|
85
|
+
valueType = {
|
|
86
|
+
kind: "es_ref_enum",
|
|
87
|
+
type: field.mapValue.enum,
|
|
88
|
+
typeOnly: true,
|
|
89
|
+
};
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
typing.push("{ [key: ", keyType, "]: ", valueType, " }");
|
|
93
|
+
typingInferrableFromZeroValue = false;
|
|
94
|
+
optional = false;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (field.repeated) {
|
|
99
|
+
typing.push("[]");
|
|
100
|
+
optional = false;
|
|
101
|
+
typingInferrableFromZeroValue = false;
|
|
102
|
+
}
|
|
103
|
+
return { typing, optional, typingInferrableFromZeroValue };
|
|
104
|
+
}
|
|
105
|
+
exports.getFieldTypeInfo = getFieldTypeInfo;
|
|
106
|
+
/**
|
|
107
|
+
* Return a printable expression for the default value of a field.
|
|
108
|
+
* Only applicable for singular scalar and enum fields.
|
|
109
|
+
*/
|
|
110
|
+
function getFieldDefaultValueExpression(field, enumAs = "enum_value_as_is") {
|
|
111
|
+
if (field.repeated) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
if (field.fieldKind !== "enum" && field.fieldKind !== "scalar") {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
const defaultValue = field.getDefaultValue();
|
|
118
|
+
if (defaultValue === undefined) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
switch (field.fieldKind) {
|
|
122
|
+
case "enum": {
|
|
123
|
+
const enumValue = field.enum.values.find((value) => value.number === defaultValue);
|
|
124
|
+
if (enumValue === undefined) {
|
|
125
|
+
throw new Error(`invalid enum default value: ${String(defaultValue)} for ${enumValue}`);
|
|
126
|
+
}
|
|
127
|
+
return literalEnumValue(enumValue, enumAs);
|
|
128
|
+
}
|
|
129
|
+
case "scalar":
|
|
130
|
+
return literalScalarValue(defaultValue, field);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.getFieldDefaultValueExpression = getFieldDefaultValueExpression;
|
|
134
|
+
/**
|
|
135
|
+
* Return a printable expression for the zero value of a field.
|
|
136
|
+
*
|
|
137
|
+
* Returns either:
|
|
138
|
+
* - empty array literal for repeated fields
|
|
139
|
+
* - empty object literal for maps
|
|
140
|
+
* - undefined for message fields
|
|
141
|
+
* - an enums first value
|
|
142
|
+
* - scalar zero value
|
|
143
|
+
*/
|
|
144
|
+
function getFieldZeroValueExpression(field, enumAs = "enum_value_as_is") {
|
|
145
|
+
if (field.repeated) {
|
|
146
|
+
return "[]";
|
|
147
|
+
}
|
|
148
|
+
switch (field.fieldKind) {
|
|
149
|
+
case "message":
|
|
150
|
+
return undefined;
|
|
151
|
+
case "map":
|
|
152
|
+
return "{}";
|
|
153
|
+
case "enum": {
|
|
154
|
+
// In proto3, the first enum value must be zero.
|
|
155
|
+
// In proto2, protobuf-go returns the first value as the default.
|
|
156
|
+
if (field.enum.values.length < 1) {
|
|
157
|
+
throw new Error("invalid enum: missing at least one value");
|
|
158
|
+
}
|
|
159
|
+
const zeroValue = field.enum.values[0];
|
|
160
|
+
return literalEnumValue(zeroValue, enumAs);
|
|
161
|
+
}
|
|
162
|
+
case "scalar": {
|
|
163
|
+
const defaultValue = protobuf_1.codegenInfo.scalarZeroValue(field.scalar, field.longType);
|
|
164
|
+
return literalScalarValue(defaultValue, field);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.getFieldZeroValueExpression = getFieldZeroValueExpression;
|
|
169
|
+
function literalScalarValue(value, field) {
|
|
170
|
+
switch (field.scalar) {
|
|
171
|
+
case protobuf_1.ScalarType.DOUBLE:
|
|
172
|
+
case protobuf_1.ScalarType.FLOAT:
|
|
173
|
+
case protobuf_1.ScalarType.INT32:
|
|
174
|
+
case protobuf_1.ScalarType.FIXED32:
|
|
175
|
+
case protobuf_1.ScalarType.UINT32:
|
|
176
|
+
case protobuf_1.ScalarType.SFIXED32:
|
|
177
|
+
case protobuf_1.ScalarType.SINT32:
|
|
178
|
+
if (typeof value != "number") {
|
|
179
|
+
throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
|
|
180
|
+
}
|
|
181
|
+
return value;
|
|
182
|
+
case protobuf_1.ScalarType.BOOL:
|
|
183
|
+
if (typeof value != "boolean") {
|
|
184
|
+
throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
|
|
185
|
+
}
|
|
186
|
+
return value;
|
|
187
|
+
case protobuf_1.ScalarType.STRING:
|
|
188
|
+
if (typeof value != "string") {
|
|
189
|
+
throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
|
|
190
|
+
}
|
|
191
|
+
return { kind: "es_string", value };
|
|
192
|
+
case protobuf_1.ScalarType.BYTES:
|
|
193
|
+
if (!(value instanceof Uint8Array)) {
|
|
194
|
+
throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
case protobuf_1.ScalarType.INT64:
|
|
198
|
+
case protobuf_1.ScalarType.SINT64:
|
|
199
|
+
case protobuf_1.ScalarType.SFIXED64:
|
|
200
|
+
case protobuf_1.ScalarType.UINT64:
|
|
201
|
+
case protobuf_1.ScalarType.FIXED64:
|
|
202
|
+
if (typeof value != "bigint" && typeof value != "string") {
|
|
203
|
+
throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
kind: "es_proto_int64",
|
|
207
|
+
type: field.scalar,
|
|
208
|
+
longType: field.longType,
|
|
209
|
+
value,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function literalEnumValue(value, enumAs) {
|
|
214
|
+
switch (enumAs) {
|
|
215
|
+
case "enum_value_as_is":
|
|
216
|
+
return [
|
|
217
|
+
{ kind: "es_ref_enum", type: value.parent, typeOnly: false },
|
|
218
|
+
".",
|
|
219
|
+
(0, ecmascript_1.localName)(value),
|
|
220
|
+
];
|
|
221
|
+
case "enum_value_as_integer":
|
|
222
|
+
return [
|
|
223
|
+
value.number,
|
|
224
|
+
" /* ",
|
|
225
|
+
value.parent.typeName,
|
|
226
|
+
".",
|
|
227
|
+
value.name,
|
|
228
|
+
" */",
|
|
229
|
+
];
|
|
230
|
+
case "enum_value_as_cast_integer":
|
|
231
|
+
return [
|
|
232
|
+
value.number,
|
|
233
|
+
" as ",
|
|
234
|
+
{ kind: "es_ref_enum", type: value.parent, typeOnly: true },
|
|
235
|
+
".",
|
|
236
|
+
(0, ecmascript_1.localName)(value),
|
|
237
|
+
];
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function scalarTypeScriptType(type, longType) {
|
|
241
|
+
switch (type) {
|
|
242
|
+
case protobuf_1.ScalarType.STRING:
|
|
243
|
+
return "string";
|
|
244
|
+
case protobuf_1.ScalarType.BOOL:
|
|
245
|
+
return "boolean";
|
|
246
|
+
case protobuf_1.ScalarType.UINT64:
|
|
247
|
+
case protobuf_1.ScalarType.SFIXED64:
|
|
248
|
+
case protobuf_1.ScalarType.FIXED64:
|
|
249
|
+
case protobuf_1.ScalarType.SINT64:
|
|
250
|
+
case protobuf_1.ScalarType.INT64:
|
|
251
|
+
if (longType === protobuf_1.LongType.STRING) {
|
|
252
|
+
return "string";
|
|
253
|
+
}
|
|
254
|
+
return "bigint";
|
|
255
|
+
case protobuf_1.ScalarType.BYTES:
|
|
256
|
+
return "Uint8Array";
|
|
257
|
+
default:
|
|
258
|
+
return "number";
|
|
259
|
+
}
|
|
260
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bufbuild/protoc-gen-es",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Protocol Buffers code generator for ECMAScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
},
|
|
21
21
|
"preferUnplugged": true,
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@bufbuild/protobuf": "^1.
|
|
24
|
-
"@bufbuild/protoplugin": "1.
|
|
23
|
+
"@bufbuild/protobuf": "^1.8.0",
|
|
24
|
+
"@bufbuild/protoplugin": "1.8.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@bufbuild/protobuf": "1.
|
|
27
|
+
"@bufbuild/protobuf": "1.8.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependenciesMeta": {
|
|
30
30
|
"@bufbuild/protobuf": {
|
package/src/declaration.ts
CHANGED
|
@@ -24,12 +24,9 @@ import type {
|
|
|
24
24
|
Printable,
|
|
25
25
|
Schema,
|
|
26
26
|
} from "@bufbuild/protoplugin/ecmascript";
|
|
27
|
-
import {
|
|
28
|
-
getFieldTyping,
|
|
29
|
-
localName,
|
|
30
|
-
reifyWkt,
|
|
31
|
-
} from "@bufbuild/protoplugin/ecmascript";
|
|
27
|
+
import { localName, reifyWkt } from "@bufbuild/protoplugin/ecmascript";
|
|
32
28
|
import { getNonEditionRuntime } from "./editions.js";
|
|
29
|
+
import { getFieldTypeInfo } from "./util.js";
|
|
33
30
|
|
|
34
31
|
export function generateDts(schema: Schema) {
|
|
35
32
|
for (const file of schema.files) {
|
|
@@ -127,25 +124,24 @@ function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) {
|
|
|
127
124
|
f.print(` } | {`);
|
|
128
125
|
}
|
|
129
126
|
f.print(f.jsDoc(field, " "));
|
|
130
|
-
const { typing } =
|
|
127
|
+
const { typing } = getFieldTypeInfo(field);
|
|
131
128
|
f.print(` value: `, typing, `;`);
|
|
132
129
|
f.print(` case: "`, localName(field), `";`);
|
|
133
130
|
}
|
|
134
131
|
f.print(` } | { case: undefined; value?: undefined };`);
|
|
135
132
|
}
|
|
136
133
|
|
|
134
|
+
// prettier-ignore
|
|
137
135
|
function generateField(schema: Schema, f: GeneratedFile, field: DescField) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
e.push(";");
|
|
148
|
-
f.print(e);
|
|
136
|
+
f.print(f.jsDoc(field, " "));
|
|
137
|
+
const e: Printable = [];
|
|
138
|
+
const { typing, optional } = getFieldTypeInfo(field);
|
|
139
|
+
if (!optional) {
|
|
140
|
+
e.push(" ", localName(field), ": ", typing, ";");
|
|
141
|
+
} else {
|
|
142
|
+
e.push(" ", localName(field), "?: ", typing, ";");
|
|
143
|
+
}
|
|
144
|
+
f.print(e);
|
|
149
145
|
}
|
|
150
146
|
|
|
151
147
|
// prettier-ignore
|
|
@@ -154,7 +150,7 @@ function generateExtension(
|
|
|
154
150
|
f: GeneratedFile,
|
|
155
151
|
ext: DescExtension,
|
|
156
152
|
) {
|
|
157
|
-
const { typing } =
|
|
153
|
+
const { typing } = getFieldTypeInfo(ext);
|
|
158
154
|
f.print(f.jsDoc(ext));
|
|
159
155
|
f.print(f.exportDecl("declare const", ext), ": ", schema.runtime.Extension, "<", ext.extendee, ", ", typing, ">;");
|
|
160
156
|
f.print();
|
|
@@ -234,7 +230,7 @@ function generateWktStaticMethods(schema: Schema, f: GeneratedFile, message: Des
|
|
|
234
230
|
case "google.protobuf.BoolValue":
|
|
235
231
|
case "google.protobuf.StringValue":
|
|
236
232
|
case "google.protobuf.BytesValue": {
|
|
237
|
-
const {typing} =
|
|
233
|
+
const {typing} = getFieldTypeInfo(ref.value);
|
|
238
234
|
f.print(" static readonly fieldWrapper: {")
|
|
239
235
|
f.print(" wrapField(value: ", typing, "): ", message, ",")
|
|
240
236
|
f.print(" unwrapField(value: ", message, "): ", typing, ",")
|
package/src/javascript.ts
CHANGED
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
|
|
15
|
-
import
|
|
15
|
+
import {
|
|
16
16
|
DescEnum,
|
|
17
17
|
DescExtension,
|
|
18
18
|
DescField,
|
|
19
19
|
DescMessage,
|
|
20
|
+
FieldDescriptorProto_Label,
|
|
20
21
|
} from "@bufbuild/protobuf";
|
|
21
22
|
import {
|
|
22
23
|
FieldDescriptorProto_Type,
|
|
@@ -30,12 +31,9 @@ import type {
|
|
|
30
31
|
Printable,
|
|
31
32
|
Schema,
|
|
32
33
|
} from "@bufbuild/protoplugin/ecmascript";
|
|
33
|
-
import {
|
|
34
|
-
getFieldExplicitDefaultValue,
|
|
35
|
-
localName,
|
|
36
|
-
reifyWkt,
|
|
37
|
-
} from "@bufbuild/protoplugin/ecmascript";
|
|
34
|
+
import { localName, reifyWkt } from "@bufbuild/protoplugin/ecmascript";
|
|
38
35
|
import { getNonEditionRuntime } from "./editions.js";
|
|
36
|
+
import { getFieldDefaultValueExpression } from "./util.js";
|
|
39
37
|
|
|
40
38
|
export function generateJs(schema: Schema) {
|
|
41
39
|
for (const file of schema.files) {
|
|
@@ -58,7 +56,7 @@ export function generateJs(schema: Schema) {
|
|
|
58
56
|
function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) {
|
|
59
57
|
const protoN = getNonEditionRuntime(schema, enumeration.file);
|
|
60
58
|
f.print(f.jsDoc(enumeration));
|
|
61
|
-
f.print(f.exportDecl("const", enumeration), " = ", protoN, ".makeEnum(")
|
|
59
|
+
f.print(f.exportDecl("const", enumeration), " = /*@__PURE__*/ ", protoN, ".makeEnum(")
|
|
62
60
|
f.print(` "`, enumeration.typeName, `",`)
|
|
63
61
|
f.print(` [`)
|
|
64
62
|
if (enumeration.sharedPrefix === undefined) {
|
|
@@ -80,7 +78,7 @@ function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) {
|
|
|
80
78
|
function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage) {
|
|
81
79
|
const protoN = getNonEditionRuntime(schema, message.file);
|
|
82
80
|
f.print(f.jsDoc(message));
|
|
83
|
-
f.print(f.exportDecl("const", message), " = ", protoN, ".makeMessageType(")
|
|
81
|
+
f.print(f.exportDecl("const", message), " = /*@__PURE__*/ ", protoN, ".makeMessageType(")
|
|
84
82
|
f.print(` `, f.string(message.typeName), `,`)
|
|
85
83
|
if (message.fields.length == 0) {
|
|
86
84
|
f.print(" [],")
|
|
@@ -168,8 +166,10 @@ export function getFieldInfoLiteral(schema: Schema, field: DescField | DescExten
|
|
|
168
166
|
}
|
|
169
167
|
if (field.optional) {
|
|
170
168
|
e.push(`opt: true, `);
|
|
169
|
+
} else if (field.proto.label === FieldDescriptorProto_Label.REQUIRED) {
|
|
170
|
+
e.push(`req: true, `);
|
|
171
171
|
}
|
|
172
|
-
const defaultValue =
|
|
172
|
+
const defaultValue = getFieldDefaultValueExpression(field);
|
|
173
173
|
if (defaultValue !== undefined) {
|
|
174
174
|
e.push(`default: `, defaultValue, `, `);
|
|
175
175
|
}
|
package/src/typescript.ts
CHANGED
|
@@ -25,14 +25,10 @@ import type {
|
|
|
25
25
|
Printable,
|
|
26
26
|
Schema,
|
|
27
27
|
} from "@bufbuild/protoplugin/ecmascript";
|
|
28
|
-
import {
|
|
29
|
-
getFieldIntrinsicDefaultValue,
|
|
30
|
-
getFieldTyping,
|
|
31
|
-
localName,
|
|
32
|
-
reifyWkt,
|
|
33
|
-
} from "@bufbuild/protoplugin/ecmascript";
|
|
28
|
+
import { localName, reifyWkt } from "@bufbuild/protoplugin/ecmascript";
|
|
34
29
|
import { generateFieldInfo, getFieldInfoLiteral } from "./javascript.js";
|
|
35
30
|
import { getNonEditionRuntime } from "./editions.js";
|
|
31
|
+
import { getFieldTypeInfo, getFieldZeroValueExpression } from "./util.js";
|
|
36
32
|
|
|
37
33
|
export function generateTs(schema: Schema) {
|
|
38
34
|
for (const file of schema.files) {
|
|
@@ -152,29 +148,32 @@ function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) {
|
|
|
152
148
|
f.print(` } | {`);
|
|
153
149
|
}
|
|
154
150
|
f.print(f.jsDoc(field, " "));
|
|
155
|
-
const { typing } =
|
|
151
|
+
const { typing } = getFieldTypeInfo(field);
|
|
156
152
|
f.print(` value: `, typing, `;`);
|
|
157
153
|
f.print(` case: "`, localName(field), `";`);
|
|
158
154
|
}
|
|
159
155
|
f.print(` } | { case: undefined; value?: undefined } = { case: undefined };`);
|
|
160
156
|
}
|
|
161
157
|
|
|
158
|
+
// prettier-ignore
|
|
162
159
|
function generateField(schema: Schema, f: GeneratedFile, field: DescField) {
|
|
163
160
|
f.print(f.jsDoc(field, " "));
|
|
164
161
|
const e: Printable = [];
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
162
|
+
const { typing, optional, typingInferrableFromZeroValue } = getFieldTypeInfo(field);
|
|
163
|
+
if (optional) {
|
|
164
|
+
e.push(" ", localName(field), "?: ", typing, ";");
|
|
165
|
+
} else {
|
|
166
|
+
if (typingInferrableFromZeroValue) {
|
|
167
|
+
e.push(" ", localName(field));
|
|
168
|
+
} else {
|
|
169
|
+
e.push(" ", localName(field), ": ", typing);
|
|
170
|
+
}
|
|
171
|
+
const zeroValue = getFieldZeroValueExpression(field);
|
|
172
|
+
if (zeroValue !== undefined) {
|
|
173
|
+
e.push(" = ", zeroValue);
|
|
174
|
+
}
|
|
175
|
+
e.push(";");
|
|
176
176
|
}
|
|
177
|
-
e.push(";");
|
|
178
177
|
f.print(e);
|
|
179
178
|
}
|
|
180
179
|
|
|
@@ -185,7 +184,7 @@ function generateExtension(
|
|
|
185
184
|
ext: DescExtension,
|
|
186
185
|
) {
|
|
187
186
|
const protoN = getNonEditionRuntime(schema, ext.file);
|
|
188
|
-
const { typing } =
|
|
187
|
+
const { typing } = getFieldTypeInfo(ext);
|
|
189
188
|
f.print(f.jsDoc(ext));
|
|
190
189
|
f.print(f.exportDecl("const", ext), " = ", protoN, ".makeExtension<", ext.extendee, ", ", typing, ">(");
|
|
191
190
|
f.print(" ", f.string(ext.typeName), ", ");
|
|
@@ -652,7 +651,7 @@ function generateWktStaticMethods(schema: Schema, f: GeneratedFile, message: Des
|
|
|
652
651
|
case "google.protobuf.BoolValue":
|
|
653
652
|
case "google.protobuf.StringValue":
|
|
654
653
|
case "google.protobuf.BytesValue": {
|
|
655
|
-
const {typing} =
|
|
654
|
+
const {typing} = getFieldTypeInfo(ref.value);
|
|
656
655
|
f.print(" static readonly fieldWrapper = {")
|
|
657
656
|
f.print(" wrapField(value: ", typing, "): ", message, " {")
|
|
658
657
|
f.print(" return new ", message, "({value});")
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
// Copyright 2021-2024 Buf Technologies, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
codegenInfo,
|
|
17
|
+
DescEnumValue,
|
|
18
|
+
DescExtension,
|
|
19
|
+
DescField,
|
|
20
|
+
FieldDescriptorProto_Label,
|
|
21
|
+
LongType,
|
|
22
|
+
ScalarType,
|
|
23
|
+
ScalarValue,
|
|
24
|
+
} from "@bufbuild/protobuf";
|
|
25
|
+
import type { Printable } from "@bufbuild/protoplugin/ecmascript";
|
|
26
|
+
import { localName } from "@bufbuild/protoplugin/ecmascript";
|
|
27
|
+
|
|
28
|
+
export function getFieldTypeInfo(field: DescField | DescExtension): {
|
|
29
|
+
typing: Printable;
|
|
30
|
+
optional: boolean;
|
|
31
|
+
typingInferrableFromZeroValue: boolean;
|
|
32
|
+
} {
|
|
33
|
+
const typing: Printable = [];
|
|
34
|
+
let typingInferrableFromZeroValue: boolean;
|
|
35
|
+
let optional = false;
|
|
36
|
+
switch (field.fieldKind) {
|
|
37
|
+
case "scalar":
|
|
38
|
+
typing.push(scalarTypeScriptType(field.scalar, field.longType));
|
|
39
|
+
optional =
|
|
40
|
+
field.optional ||
|
|
41
|
+
field.proto.label === FieldDescriptorProto_Label.REQUIRED;
|
|
42
|
+
typingInferrableFromZeroValue = true;
|
|
43
|
+
break;
|
|
44
|
+
case "message": {
|
|
45
|
+
const baseType = codegenInfo.getUnwrappedFieldType(field);
|
|
46
|
+
if (baseType !== undefined) {
|
|
47
|
+
typing.push(scalarTypeScriptType(baseType, LongType.BIGINT));
|
|
48
|
+
} else {
|
|
49
|
+
typing.push({
|
|
50
|
+
kind: "es_ref_message",
|
|
51
|
+
type: field.message,
|
|
52
|
+
typeOnly: true,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
optional = true;
|
|
56
|
+
typingInferrableFromZeroValue = true;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case "enum":
|
|
60
|
+
typing.push({
|
|
61
|
+
kind: "es_ref_enum",
|
|
62
|
+
type: field.enum,
|
|
63
|
+
typeOnly: true,
|
|
64
|
+
});
|
|
65
|
+
optional =
|
|
66
|
+
field.optional ||
|
|
67
|
+
field.proto.label === FieldDescriptorProto_Label.REQUIRED;
|
|
68
|
+
typingInferrableFromZeroValue = true;
|
|
69
|
+
break;
|
|
70
|
+
case "map": {
|
|
71
|
+
let keyType: string;
|
|
72
|
+
switch (field.mapKey) {
|
|
73
|
+
case ScalarType.INT32:
|
|
74
|
+
case ScalarType.FIXED32:
|
|
75
|
+
case ScalarType.UINT32:
|
|
76
|
+
case ScalarType.SFIXED32:
|
|
77
|
+
case ScalarType.SINT32:
|
|
78
|
+
keyType = "number";
|
|
79
|
+
break;
|
|
80
|
+
default:
|
|
81
|
+
keyType = "string";
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
let valueType: Printable;
|
|
85
|
+
switch (field.mapValue.kind) {
|
|
86
|
+
case "scalar":
|
|
87
|
+
valueType = scalarTypeScriptType(
|
|
88
|
+
field.mapValue.scalar,
|
|
89
|
+
LongType.BIGINT,
|
|
90
|
+
);
|
|
91
|
+
break;
|
|
92
|
+
case "message":
|
|
93
|
+
valueType = {
|
|
94
|
+
kind: "es_ref_message",
|
|
95
|
+
type: field.mapValue.message,
|
|
96
|
+
typeOnly: true,
|
|
97
|
+
};
|
|
98
|
+
break;
|
|
99
|
+
case "enum":
|
|
100
|
+
valueType = {
|
|
101
|
+
kind: "es_ref_enum",
|
|
102
|
+
type: field.mapValue.enum,
|
|
103
|
+
typeOnly: true,
|
|
104
|
+
};
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
typing.push("{ [key: ", keyType, "]: ", valueType, " }");
|
|
108
|
+
typingInferrableFromZeroValue = false;
|
|
109
|
+
optional = false;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (field.repeated) {
|
|
114
|
+
typing.push("[]");
|
|
115
|
+
optional = false;
|
|
116
|
+
typingInferrableFromZeroValue = false;
|
|
117
|
+
}
|
|
118
|
+
return { typing, optional, typingInferrableFromZeroValue };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Return a printable expression for the default value of a field.
|
|
123
|
+
* Only applicable for singular scalar and enum fields.
|
|
124
|
+
*/
|
|
125
|
+
export function getFieldDefaultValueExpression(
|
|
126
|
+
field: DescField | DescExtension,
|
|
127
|
+
enumAs:
|
|
128
|
+
| "enum_value_as_is"
|
|
129
|
+
| "enum_value_as_integer"
|
|
130
|
+
| "enum_value_as_cast_integer" = "enum_value_as_is",
|
|
131
|
+
): Printable | undefined {
|
|
132
|
+
if (field.repeated) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
if (field.fieldKind !== "enum" && field.fieldKind !== "scalar") {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
const defaultValue = field.getDefaultValue();
|
|
139
|
+
if (defaultValue === undefined) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
switch (field.fieldKind) {
|
|
143
|
+
case "enum": {
|
|
144
|
+
const enumValue = field.enum.values.find(
|
|
145
|
+
(value) => value.number === defaultValue,
|
|
146
|
+
);
|
|
147
|
+
if (enumValue === undefined) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`invalid enum default value: ${String(defaultValue)} for ${enumValue}`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return literalEnumValue(enumValue, enumAs);
|
|
153
|
+
}
|
|
154
|
+
case "scalar":
|
|
155
|
+
return literalScalarValue(defaultValue, field);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Return a printable expression for the zero value of a field.
|
|
161
|
+
*
|
|
162
|
+
* Returns either:
|
|
163
|
+
* - empty array literal for repeated fields
|
|
164
|
+
* - empty object literal for maps
|
|
165
|
+
* - undefined for message fields
|
|
166
|
+
* - an enums first value
|
|
167
|
+
* - scalar zero value
|
|
168
|
+
*/
|
|
169
|
+
export function getFieldZeroValueExpression(
|
|
170
|
+
field: DescField | DescExtension,
|
|
171
|
+
enumAs:
|
|
172
|
+
| "enum_value_as_is"
|
|
173
|
+
| "enum_value_as_integer"
|
|
174
|
+
| "enum_value_as_cast_integer" = "enum_value_as_is",
|
|
175
|
+
): Printable | undefined {
|
|
176
|
+
if (field.repeated) {
|
|
177
|
+
return "[]";
|
|
178
|
+
}
|
|
179
|
+
switch (field.fieldKind) {
|
|
180
|
+
case "message":
|
|
181
|
+
return undefined;
|
|
182
|
+
case "map":
|
|
183
|
+
return "{}";
|
|
184
|
+
case "enum": {
|
|
185
|
+
// In proto3, the first enum value must be zero.
|
|
186
|
+
// In proto2, protobuf-go returns the first value as the default.
|
|
187
|
+
if (field.enum.values.length < 1) {
|
|
188
|
+
throw new Error("invalid enum: missing at least one value");
|
|
189
|
+
}
|
|
190
|
+
const zeroValue = field.enum.values[0];
|
|
191
|
+
return literalEnumValue(zeroValue, enumAs);
|
|
192
|
+
}
|
|
193
|
+
case "scalar": {
|
|
194
|
+
const defaultValue = codegenInfo.scalarZeroValue(
|
|
195
|
+
field.scalar,
|
|
196
|
+
field.longType,
|
|
197
|
+
);
|
|
198
|
+
return literalScalarValue(defaultValue, field);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function literalScalarValue(
|
|
204
|
+
value: ScalarValue,
|
|
205
|
+
field: (DescField | DescExtension) & { fieldKind: "scalar" },
|
|
206
|
+
): Printable {
|
|
207
|
+
switch (field.scalar) {
|
|
208
|
+
case ScalarType.DOUBLE:
|
|
209
|
+
case ScalarType.FLOAT:
|
|
210
|
+
case ScalarType.INT32:
|
|
211
|
+
case ScalarType.FIXED32:
|
|
212
|
+
case ScalarType.UINT32:
|
|
213
|
+
case ScalarType.SFIXED32:
|
|
214
|
+
case ScalarType.SINT32:
|
|
215
|
+
if (typeof value != "number") {
|
|
216
|
+
throw new Error(
|
|
217
|
+
`Unexpected value for ${ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return value;
|
|
221
|
+
case ScalarType.BOOL:
|
|
222
|
+
if (typeof value != "boolean") {
|
|
223
|
+
throw new Error(
|
|
224
|
+
`Unexpected value for ${ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
return value;
|
|
228
|
+
case ScalarType.STRING:
|
|
229
|
+
if (typeof value != "string") {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`Unexpected value for ${ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
return { kind: "es_string", value };
|
|
235
|
+
case ScalarType.BYTES:
|
|
236
|
+
if (!(value instanceof Uint8Array)) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`Unexpected value for ${ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
return value;
|
|
242
|
+
case ScalarType.INT64:
|
|
243
|
+
case ScalarType.SINT64:
|
|
244
|
+
case ScalarType.SFIXED64:
|
|
245
|
+
case ScalarType.UINT64:
|
|
246
|
+
case ScalarType.FIXED64:
|
|
247
|
+
if (typeof value != "bigint" && typeof value != "string") {
|
|
248
|
+
throw new Error(
|
|
249
|
+
`Unexpected value for ${ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
kind: "es_proto_int64",
|
|
254
|
+
type: field.scalar,
|
|
255
|
+
longType: field.longType,
|
|
256
|
+
value,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function literalEnumValue(
|
|
262
|
+
value: DescEnumValue,
|
|
263
|
+
enumAs:
|
|
264
|
+
| "enum_value_as_is"
|
|
265
|
+
| "enum_value_as_integer"
|
|
266
|
+
| "enum_value_as_cast_integer",
|
|
267
|
+
): Printable {
|
|
268
|
+
switch (enumAs) {
|
|
269
|
+
case "enum_value_as_is":
|
|
270
|
+
return [
|
|
271
|
+
{ kind: "es_ref_enum", type: value.parent, typeOnly: false },
|
|
272
|
+
".",
|
|
273
|
+
localName(value),
|
|
274
|
+
];
|
|
275
|
+
case "enum_value_as_integer":
|
|
276
|
+
return [
|
|
277
|
+
value.number,
|
|
278
|
+
" /* ",
|
|
279
|
+
value.parent.typeName,
|
|
280
|
+
".",
|
|
281
|
+
value.name,
|
|
282
|
+
" */",
|
|
283
|
+
];
|
|
284
|
+
case "enum_value_as_cast_integer":
|
|
285
|
+
return [
|
|
286
|
+
value.number,
|
|
287
|
+
" as ",
|
|
288
|
+
{ kind: "es_ref_enum", type: value.parent, typeOnly: true },
|
|
289
|
+
".",
|
|
290
|
+
localName(value),
|
|
291
|
+
];
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function scalarTypeScriptType(type: ScalarType, longType: LongType): Printable {
|
|
296
|
+
switch (type) {
|
|
297
|
+
case ScalarType.STRING:
|
|
298
|
+
return "string";
|
|
299
|
+
case ScalarType.BOOL:
|
|
300
|
+
return "boolean";
|
|
301
|
+
case ScalarType.UINT64:
|
|
302
|
+
case ScalarType.SFIXED64:
|
|
303
|
+
case ScalarType.FIXED64:
|
|
304
|
+
case ScalarType.SINT64:
|
|
305
|
+
case ScalarType.INT64:
|
|
306
|
+
if (longType === LongType.STRING) {
|
|
307
|
+
return "string";
|
|
308
|
+
}
|
|
309
|
+
return "bigint";
|
|
310
|
+
case ScalarType.BYTES:
|
|
311
|
+
return "Uint8Array";
|
|
312
|
+
default:
|
|
313
|
+
return "number";
|
|
314
|
+
}
|
|
315
|
+
}
|