@aptre/protobuf-es-lite 0.2.15 → 0.3.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/LICENSE +1 -1
- package/README.md +10 -15
- package/dist/binary.d.ts +13 -10
- package/dist/binary.js +24 -23
- package/dist/codegen-info.d.ts +8 -0
- package/dist/codegen-info.js +12 -4
- package/dist/descriptor-set.d.ts +8 -9
- package/dist/field-wrapper.d.ts +2 -2
- package/dist/google/protobuf/any.pb.d.ts +55 -2
- package/dist/google/protobuf/any.pb.js +85 -4
- package/dist/google/protobuf/api.pb.js +34 -13
- package/dist/google/protobuf/descriptor.pb.js +1045 -161
- package/dist/google/protobuf/duration.pb.d.ts +7 -2
- package/dist/google/protobuf/duration.pb.js +54 -4
- package/dist/google/protobuf/empty.pb.js +1 -0
- package/dist/google/protobuf/source_context.pb.js +3 -2
- package/dist/google/protobuf/struct.pb.d.ts +17 -4
- package/dist/google/protobuf/struct.pb.js +162 -12
- package/dist/google/protobuf/timestamp.pb.d.ts +8 -2
- package/dist/google/protobuf/timestamp.pb.js +68 -4
- package/dist/google/protobuf/type.pb.js +62 -21
- package/dist/google/protobuf/wrappers.pb.d.ts +47 -10
- package/dist/google/protobuf/wrappers.pb.js +280 -19
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -1
- package/dist/json.d.ts +30 -4
- package/dist/json.js +17 -16
- package/dist/message.d.ts +5 -12
- package/dist/message.js +75 -77
- package/dist/protoc-gen-es-lite/typescript.d.ts +2 -2
- package/dist/protoc-gen-es-lite/typescript.js +348 -26
- package/dist/protoplugin/ecmascript/reify-wkt.d.ts +1 -5
- package/dist/protoplugin/ecmascript/reify-wkt.js +0 -10
- package/dist/type-registry.d.ts +43 -0
- package/dist/type-registry.js +14 -0
- package/example/example.pb.ts +56 -32
- package/package.json +3 -1
package/dist/message.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ export interface MessageType<T extends Message<T> = AnyMessage> {
|
|
|
83
83
|
*/
|
|
84
84
|
toJsonString(a: Message<T>, options?: Partial<JsonWriteStringOptions>): string;
|
|
85
85
|
}
|
|
86
|
-
export
|
|
86
|
+
export type MessageTypeParams<T extends Message<T>> = Pick<MessageType<T>, "fieldWrapper" | "typeName"> & {
|
|
87
87
|
/**
|
|
88
88
|
* Fields contains the list of message fields.
|
|
89
89
|
*/
|
|
@@ -98,23 +98,16 @@ export interface MessageTypeParams<T extends Message<T>> extends Pick<MessageTyp
|
|
|
98
98
|
* delimited fields (proto3) or with (proto2 legacy).
|
|
99
99
|
*/
|
|
100
100
|
delimitedMessageEncoding?: boolean;
|
|
101
|
-
|
|
102
|
-
* Serialize the message to a JSON value, a JavaScript value that can be
|
|
103
|
-
* passed to JSON.stringify().
|
|
104
|
-
*
|
|
105
|
-
* When passed as MessageTypeParams this will override the default serializer behavior.
|
|
106
|
-
*/
|
|
107
|
-
toJson?: MessageType<T>["toJson"];
|
|
108
|
-
}
|
|
109
|
-
export declare function compareMessages<T extends Message<T>>(fields: FieldList, a: T | undefined | null, b: T | undefined | null): boolean;
|
|
110
|
-
export declare function cloneMessage<T extends Message<T>>(message: T, fields: FieldList): T;
|
|
101
|
+
};
|
|
111
102
|
/**
|
|
112
103
|
* createMessageType creates a new message type.
|
|
113
104
|
*
|
|
114
105
|
* The argument `packedByDefault` specifies whether fields that do not specify
|
|
115
106
|
* `packed` should be packed (proto3) or unpacked (proto2).
|
|
116
107
|
*/
|
|
117
|
-
export declare function createMessageType<T extends Message<T
|
|
108
|
+
export declare function createMessageType<T extends Message<T>, E extends Record<string, Function> = {}>(params: MessageTypeParams<T>, exts?: E): MessageType<T> & E;
|
|
109
|
+
export declare function compareMessages<T extends Message<T>>(fields: FieldList, a: T | undefined | null, b: T | undefined | null): boolean;
|
|
110
|
+
export declare function cloneMessage<T extends Message<T>>(message: T, fields: FieldList): T;
|
|
118
111
|
/**
|
|
119
112
|
* createMessage recursively builds a message filled with zero values based on the given FieldList.
|
|
120
113
|
*/
|
package/dist/message.js
CHANGED
|
@@ -14,8 +14,81 @@
|
|
|
14
14
|
import { newFieldList, resolveMessageType, } from "./field.js";
|
|
15
15
|
import { applyPartialMessage } from "./partial.js";
|
|
16
16
|
import { ScalarType, scalarEquals } from "./scalar.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { binaryReadMessage, binaryWriteMessage, binaryMakeReadOptions, binaryMakeWriteOptions, } from "./binary.js";
|
|
18
|
+
import { jsonReadMessage, jsonWriteMessage, jsonMakeReadOptions, jsonMakeWriteOptions, } from "./json.js";
|
|
19
|
+
/**
|
|
20
|
+
* createMessageType creates a new message type.
|
|
21
|
+
*
|
|
22
|
+
* The argument `packedByDefault` specifies whether fields that do not specify
|
|
23
|
+
* `packed` should be packed (proto3) or unpacked (proto2).
|
|
24
|
+
*/
|
|
25
|
+
export function createMessageType(params, exts) {
|
|
26
|
+
const { fields: fieldsSource, typeName, packedByDefault, delimitedMessageEncoding, fieldWrapper, } = params;
|
|
27
|
+
const fields = newFieldList(fieldsSource, packedByDefault);
|
|
28
|
+
const mt = {
|
|
29
|
+
typeName,
|
|
30
|
+
fields,
|
|
31
|
+
fieldWrapper,
|
|
32
|
+
create(partial) {
|
|
33
|
+
const message = createMessage(fields);
|
|
34
|
+
applyPartialMessage(partial, message, fields);
|
|
35
|
+
return message;
|
|
36
|
+
},
|
|
37
|
+
equals(a, b) {
|
|
38
|
+
return compareMessages(fields, a, b);
|
|
39
|
+
},
|
|
40
|
+
clone(a) {
|
|
41
|
+
if (a == null) {
|
|
42
|
+
return a;
|
|
43
|
+
}
|
|
44
|
+
return cloneMessage(a, fields);
|
|
45
|
+
},
|
|
46
|
+
fromBinary(bytes, options) {
|
|
47
|
+
const message = {};
|
|
48
|
+
if (bytes && bytes.length) {
|
|
49
|
+
const opt = binaryMakeReadOptions(options);
|
|
50
|
+
binaryReadMessage(message, fields, opt.readerFactory(bytes), bytes.byteLength, opt, delimitedMessageEncoding);
|
|
51
|
+
}
|
|
52
|
+
return message;
|
|
53
|
+
},
|
|
54
|
+
fromJson(jsonValue, options) {
|
|
55
|
+
const message = {};
|
|
56
|
+
if (jsonValue != null) {
|
|
57
|
+
const opts = jsonMakeReadOptions(options);
|
|
58
|
+
jsonReadMessage(fields, typeName, jsonValue, opts, message);
|
|
59
|
+
}
|
|
60
|
+
return message;
|
|
61
|
+
},
|
|
62
|
+
fromJsonString(jsonString, options) {
|
|
63
|
+
let json = null;
|
|
64
|
+
if (jsonString) {
|
|
65
|
+
try {
|
|
66
|
+
json = JSON.parse(jsonString);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
throw new Error(`cannot decode ${typeName} from JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return mt.fromJson(json, options);
|
|
73
|
+
},
|
|
74
|
+
toBinary(a, options) {
|
|
75
|
+
const opt = binaryMakeWriteOptions(options);
|
|
76
|
+
const writer = opt.writerFactory();
|
|
77
|
+
binaryWriteMessage(a, fields, writer, opt);
|
|
78
|
+
return writer.finish();
|
|
79
|
+
},
|
|
80
|
+
toJson(a, options) {
|
|
81
|
+
const opt = jsonMakeWriteOptions(options);
|
|
82
|
+
return jsonWriteMessage(a, fields, opt);
|
|
83
|
+
},
|
|
84
|
+
toJsonString(a, options) {
|
|
85
|
+
const value = mt.toJson(a, options);
|
|
86
|
+
return JSON.stringify(value, null, options?.prettySpaces ?? 0);
|
|
87
|
+
},
|
|
88
|
+
...(exts ?? {}),
|
|
89
|
+
};
|
|
90
|
+
return mt;
|
|
91
|
+
}
|
|
19
92
|
// compareMessages compares two messages for equality.
|
|
20
93
|
export function compareMessages(fields, a, b) {
|
|
21
94
|
if (a == null && b == null) {
|
|
@@ -144,81 +217,6 @@ export function cloneMessage(message, fields) {
|
|
|
144
217
|
}
|
|
145
218
|
return clone;
|
|
146
219
|
}
|
|
147
|
-
/**
|
|
148
|
-
* createMessageType creates a new message type.
|
|
149
|
-
*
|
|
150
|
-
* The argument `packedByDefault` specifies whether fields that do not specify
|
|
151
|
-
* `packed` should be packed (proto3) or unpacked (proto2).
|
|
152
|
-
*/
|
|
153
|
-
export function createMessageType(params) {
|
|
154
|
-
const { fields: fieldsSource, typeName, packedByDefault, delimitedMessageEncoding, fieldWrapper, } = params;
|
|
155
|
-
const fields = newFieldList(fieldsSource, packedByDefault);
|
|
156
|
-
const mt = {
|
|
157
|
-
typeName,
|
|
158
|
-
fields,
|
|
159
|
-
fieldWrapper,
|
|
160
|
-
create(partial) {
|
|
161
|
-
const message = createMessage(fields);
|
|
162
|
-
applyPartialMessage(partial, message, fields);
|
|
163
|
-
return message;
|
|
164
|
-
},
|
|
165
|
-
equals(a, b) {
|
|
166
|
-
return compareMessages(fields, a, b);
|
|
167
|
-
},
|
|
168
|
-
clone(a) {
|
|
169
|
-
if (a == null) {
|
|
170
|
-
return a;
|
|
171
|
-
}
|
|
172
|
-
return cloneMessage(a, fields);
|
|
173
|
-
},
|
|
174
|
-
fromBinary(bytes, options) {
|
|
175
|
-
const message = {};
|
|
176
|
-
if (bytes && bytes.length) {
|
|
177
|
-
const opt = makeBinaryReadOptions(options);
|
|
178
|
-
readBinaryMessage(message, fields, opt.readerFactory(bytes), bytes.byteLength, opt, delimitedMessageEncoding);
|
|
179
|
-
}
|
|
180
|
-
return message;
|
|
181
|
-
},
|
|
182
|
-
fromJson(jsonValue, options) {
|
|
183
|
-
const message = {};
|
|
184
|
-
if (jsonValue != null) {
|
|
185
|
-
const opts = makeJsonReadOptions(options);
|
|
186
|
-
readJsonMessage(fields, typeName, jsonValue, opts, message);
|
|
187
|
-
}
|
|
188
|
-
return message;
|
|
189
|
-
},
|
|
190
|
-
fromJsonString(jsonString, options) {
|
|
191
|
-
let json = null;
|
|
192
|
-
if (jsonString) {
|
|
193
|
-
try {
|
|
194
|
-
json = JSON.parse(jsonString);
|
|
195
|
-
}
|
|
196
|
-
catch (e) {
|
|
197
|
-
throw new Error(`cannot decode ${typeName} from JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return this.fromJson(json, options);
|
|
201
|
-
},
|
|
202
|
-
toBinary(a, options) {
|
|
203
|
-
const opt = makeBinaryWriteOptions(options);
|
|
204
|
-
const writer = opt.writerFactory();
|
|
205
|
-
writeBinaryMessage(a, fields, writer, opt);
|
|
206
|
-
return writer.finish();
|
|
207
|
-
},
|
|
208
|
-
toJson(a, options) {
|
|
209
|
-
const opt = makeJsonWriteOptions(options);
|
|
210
|
-
return writeJsonMessage(a, fields, opt);
|
|
211
|
-
},
|
|
212
|
-
toJsonString(a, options) {
|
|
213
|
-
const value = this.toJson(a, options);
|
|
214
|
-
return JSON.stringify(value, null, options?.prettySpaces ?? 0);
|
|
215
|
-
},
|
|
216
|
-
};
|
|
217
|
-
if (params.toJson) {
|
|
218
|
-
mt.toJson = params.toJson;
|
|
219
|
-
}
|
|
220
|
-
return mt;
|
|
221
|
-
}
|
|
222
220
|
/**
|
|
223
221
|
* createMessage recursively builds a message filled with zero values based on the given FieldList.
|
|
224
222
|
*/
|
|
@@ -3,6 +3,6 @@ import { DescEnum, DescExtension, DescField, DescFile, DescMessage } from "../de
|
|
|
3
3
|
export declare function generateTs(schema: Schema): void;
|
|
4
4
|
export declare function checkSupportedSyntax(file: DescFile): void;
|
|
5
5
|
export declare function makeImportPath(file: DescFile): string;
|
|
6
|
-
export declare function generateFieldInfo(f: GeneratedFile, field: DescField | DescExtension): void;
|
|
6
|
+
export declare function generateFieldInfo(f: GeneratedFile, schema: Schema, field: DescField | DescExtension): void;
|
|
7
7
|
export declare const createTypeImport: (desc: DescMessage | DescEnum | DescExtension) => ImportSymbol;
|
|
8
|
-
export declare function getFieldInfoLiteral(field: DescField | DescExtension): Printable;
|
|
8
|
+
export declare function getFieldInfoLiteral(schema: Schema, field: DescField | DescExtension): Printable;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
|
-
import { createImportSymbol } from "../protoplugin/ecmascript/index.js";
|
|
15
|
+
import { createImportSymbol, reifyWkt, } from "../protoplugin/ecmascript/index.js";
|
|
16
16
|
import { getFieldDefaultValueExpression, getFieldTypeInfo } from "../util.js";
|
|
17
17
|
import { localName } from "../names.js";
|
|
18
18
|
import { LongType, ScalarType } from "../scalar.js";
|
|
@@ -107,20 +107,9 @@ export function checkSupportedSyntax(file) {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
function generateMessage(schema, f, message) {
|
|
110
|
-
// check if we support this runtime
|
|
111
110
|
checkSupportedSyntax(message.file);
|
|
111
|
+
const { MessageType: rtMessageType, createMessageType, PartialFieldInfo, } = schema.runtime;
|
|
112
112
|
f.print(f.jsDoc(message));
|
|
113
|
-
/*
|
|
114
|
-
f.print(
|
|
115
|
-
f.exportDecl("interface", message),
|
|
116
|
-
" extends ",
|
|
117
|
-
schema.runtime.Message,
|
|
118
|
-
"<",
|
|
119
|
-
message,
|
|
120
|
-
">",
|
|
121
|
-
" {",
|
|
122
|
-
);
|
|
123
|
-
*/
|
|
124
113
|
f.print(f.exportDecl("type", message), " = ", schema.runtime.Message, "<{");
|
|
125
114
|
for (const field of message.fields) {
|
|
126
115
|
generateField(f, field);
|
|
@@ -131,17 +120,35 @@ function generateMessage(schema, f, message) {
|
|
|
131
120
|
f.print();
|
|
132
121
|
f.print("}>;");
|
|
133
122
|
f.print();
|
|
134
|
-
|
|
135
|
-
|
|
123
|
+
// If we need to extend the message type, do that here.
|
|
124
|
+
const reWkt = reifyWkt(message);
|
|
125
|
+
if (reWkt != null) {
|
|
126
|
+
f.print("// ", message, "_Wkt contains the well-known-type overrides for ", message, ".");
|
|
127
|
+
f.print("const ", message, "_Wkt = {");
|
|
128
|
+
generateWktMethods(schema, f, message, reWkt);
|
|
129
|
+
f.print("};");
|
|
130
|
+
f.print();
|
|
131
|
+
f.print("// ", message, " contains the message type declaration for ", message, ".");
|
|
132
|
+
f.print(f.exportDecl("const", message), `: `, rtMessageType, `<`, message, `> & typeof `, message, `_Wkt = `, createMessageType, "<", message, ", typeof ", message, "_Wkt>({");
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
f.print("// ", message, " contains the message type declaration for ", message, ".");
|
|
136
|
+
f.print(f.exportDecl("const", message), `: `, rtMessageType, `<`, message, `> = `, createMessageType, "({");
|
|
137
|
+
}
|
|
136
138
|
f.print(" typeName: ", f.string(message.typeName), ",");
|
|
137
139
|
f.print(" fields: [");
|
|
138
140
|
for (const field of message.fields) {
|
|
139
|
-
generateFieldInfo(f, field);
|
|
141
|
+
generateFieldInfo(f, schema, field);
|
|
140
142
|
}
|
|
141
|
-
f.print(" ] as readonly ",
|
|
143
|
+
f.print(" ] as readonly ", PartialFieldInfo, "[],");
|
|
142
144
|
f.print(" packedByDefault: ", message.file.proto.syntax === "proto3", ",");
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
if (reWkt == null) {
|
|
146
|
+
f.print("});");
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
generateWktFieldWrapper(f, message, reWkt);
|
|
150
|
+
f.print("}, ", message, "_Wkt);");
|
|
151
|
+
}
|
|
145
152
|
f.print();
|
|
146
153
|
}
|
|
147
154
|
function generateField(f, field) {
|
|
@@ -175,8 +182,8 @@ function generateOneof(f, oneof) {
|
|
|
175
182
|
export function makeImportPath(file) {
|
|
176
183
|
return "./" + file.name + ".pb.js";
|
|
177
184
|
}
|
|
178
|
-
export function generateFieldInfo(f, field) {
|
|
179
|
-
f.print(" ", getFieldInfoLiteral(field), ",");
|
|
185
|
+
export function generateFieldInfo(f, schema, field) {
|
|
186
|
+
f.print(" ", getFieldInfoLiteral(schema, field), ",");
|
|
180
187
|
}
|
|
181
188
|
export const createTypeImport = (desc) => {
|
|
182
189
|
var name = localName(desc);
|
|
@@ -186,7 +193,8 @@ export const createTypeImport = (desc) => {
|
|
|
186
193
|
const from = makeImportPath(desc.file);
|
|
187
194
|
return createImportSymbol(name, from);
|
|
188
195
|
};
|
|
189
|
-
export function getFieldInfoLiteral(field) {
|
|
196
|
+
export function getFieldInfoLiteral(schema, field) {
|
|
197
|
+
const { ScalarType: rtScalarType, LongType: rtLongType } = schema.runtime;
|
|
190
198
|
const e = [];
|
|
191
199
|
e.push("{ no: ", field.number, `, `);
|
|
192
200
|
if (field.kind == "field") {
|
|
@@ -197,16 +205,16 @@ export function getFieldInfoLiteral(field) {
|
|
|
197
205
|
}
|
|
198
206
|
switch (field.fieldKind) {
|
|
199
207
|
case "scalar":
|
|
200
|
-
e.push(`kind: "scalar", T: `,
|
|
208
|
+
e.push(`kind: "scalar", T: `, rtScalarType, `.`, ScalarType[field.scalar], `, `);
|
|
201
209
|
if (field.longType != LongType.BIGINT) {
|
|
202
|
-
e.push(`L: `,
|
|
210
|
+
e.push(`L: `, rtLongType, `.`, LongType[field.longType], `, `);
|
|
203
211
|
}
|
|
204
212
|
break;
|
|
205
213
|
case "map":
|
|
206
|
-
e.push(`kind: "map", K: `,
|
|
214
|
+
e.push(`kind: "map", K: `, rtScalarType, `.`, ScalarType[field.mapKey], `, `);
|
|
207
215
|
switch (field.mapValue.kind) {
|
|
208
216
|
case "scalar":
|
|
209
|
-
e.push(`V: {kind: "scalar", T: `,
|
|
217
|
+
e.push(`V: {kind: "scalar", T: `, rtScalarType, `.`, ScalarType[field.mapValue.scalar], `}, `);
|
|
210
218
|
break;
|
|
211
219
|
case "message":
|
|
212
220
|
e.push(`V: {kind: "message", T: () => `, field.mapValue.message, `}, `);
|
|
@@ -252,3 +260,317 @@ export function getFieldInfoLiteral(field) {
|
|
|
252
260
|
e.push(" }");
|
|
253
261
|
return e;
|
|
254
262
|
}
|
|
263
|
+
function generateWktMethods(schema, f, message, ref) {
|
|
264
|
+
const { JsonValue, JsonReadOptions, JsonWriteOptions, JsonObject, jsonReadScalar, jsonWriteScalar, jsonDebugValue, Message, MessageType, IMessageTypeRegistry, ScalarType: rtScalarType, LongType: rtLongType,
|
|
265
|
+
// ScalarValue: rtScalarValue,
|
|
266
|
+
protoInt64, applyPartialMessage, } = schema.runtime;
|
|
267
|
+
switch (ref.typeName) {
|
|
268
|
+
case "google.protobuf.Any":
|
|
269
|
+
f.print(" toJson(msg: ", message, ", options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {");
|
|
270
|
+
f.print(" const typeName = msg?.", localName(ref.typeUrl), ";");
|
|
271
|
+
f.print(` if (!typeName) {`);
|
|
272
|
+
f.print(" return {};");
|
|
273
|
+
f.print(" }");
|
|
274
|
+
f.print(" const messageType = options?.typeRegistry?.findMessage(typeName);");
|
|
275
|
+
f.print(" if (!messageType) {");
|
|
276
|
+
f.print(" throw new Error(`cannot encode message ", message.typeName, ' to JSON: "${typeName}" is not in the type registry`);');
|
|
277
|
+
f.print(" }");
|
|
278
|
+
f.print(" const message = messageType.fromBinary(msg.", localName(ref.value), ");");
|
|
279
|
+
f.print(" let json = messageType.toJson(message, options);");
|
|
280
|
+
f.print(` if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) {`);
|
|
281
|
+
f.print(" json = {value: json};");
|
|
282
|
+
f.print(" }");
|
|
283
|
+
f.print(` json["@type"] = typeName;`);
|
|
284
|
+
f.print(" return json;");
|
|
285
|
+
f.print(" },");
|
|
286
|
+
f.print();
|
|
287
|
+
f.print(" fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">) {");
|
|
288
|
+
f.print(` if (json === null || Array.isArray(json) || typeof json != "object") {`);
|
|
289
|
+
f.print(" throw new Error(`cannot decode message ", message.typeName, ' from JSON: expected object but got ${json === null ? "null" : Array.isArray(json) ? "array" : typeof json}`);');
|
|
290
|
+
f.print(" }");
|
|
291
|
+
f.print(` if (Object.keys(json).length == 0) {`);
|
|
292
|
+
f.print(` return {} as `, message, `;`);
|
|
293
|
+
f.print(` }`);
|
|
294
|
+
f.print(` const typeUrl = json["@type"];`);
|
|
295
|
+
f.print(` if (typeof typeUrl != "string" || typeUrl == "") {`);
|
|
296
|
+
f.print(" throw new Error(`cannot decode message ", message.typeName, ' from JSON: "@type" is empty`);');
|
|
297
|
+
f.print(" }");
|
|
298
|
+
f.print(" const typeName = typeUrl, messageType = options?.typeRegistry?.findMessage(typeName);");
|
|
299
|
+
f.print(" if (!messageType) {");
|
|
300
|
+
f.print(" throw new Error(`cannot decode message ", message.typeName, " from JSON: ${typeUrl} is not in the type registry`);");
|
|
301
|
+
f.print(" }");
|
|
302
|
+
f.print(" let message;");
|
|
303
|
+
f.print(` if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) {`);
|
|
304
|
+
f.print(` message = messageType.fromJson(json["value"], options);`);
|
|
305
|
+
f.print(" } else {");
|
|
306
|
+
f.print(" const copy = Object.assign({}, json);");
|
|
307
|
+
f.print(` delete copy["@type"];`);
|
|
308
|
+
f.print(" message = messageType.fromJson(copy, options);");
|
|
309
|
+
f.print(" }");
|
|
310
|
+
f.print(" const out = {} as ", message, ";");
|
|
311
|
+
f.print(" ", message, ".packFrom(out, message, messageType);");
|
|
312
|
+
f.print(" return out;");
|
|
313
|
+
f.print(" },");
|
|
314
|
+
f.print();
|
|
315
|
+
f.print(" packFrom<T extends ", Message, "<T>>(out: ", message, ", message: ", Message, "<T>, messageType: ", MessageType, "<T>): void {");
|
|
316
|
+
f.print(" out.", localName(ref.value), " = messageType.toBinary(message);");
|
|
317
|
+
f.print(" out.", localName(ref.typeUrl), " = messageType.typeName;");
|
|
318
|
+
f.print(" },");
|
|
319
|
+
f.print();
|
|
320
|
+
f.print(" unpackTo<T extends ", Message, "<T>>(msg: ", message, ", target: ", Message, "<T>, targetMessageType: ", MessageType, "<T>): boolean {");
|
|
321
|
+
f.print(" if (!", message, ".is(msg, targetMessageType)) {");
|
|
322
|
+
f.print(" return false;");
|
|
323
|
+
f.print(" }");
|
|
324
|
+
f.print(" const partial = targetMessageType.fromBinary(msg.", localName(ref.value), ");");
|
|
325
|
+
f.print(" ", applyPartialMessage, "(partial, target, targetMessageType.fields);");
|
|
326
|
+
f.print(" return true;");
|
|
327
|
+
f.print(" },");
|
|
328
|
+
f.print();
|
|
329
|
+
f.print(" unpack<T extends Message<T>>(msg: ", message, ", registry: ", IMessageTypeRegistry, "): {message: ", Message, "<T>, messageType: ", MessageType, "<T>} | undefined {");
|
|
330
|
+
f.print(" const typeUrl = msg.", localName(ref.typeUrl)), ";";
|
|
331
|
+
f.print(" const messageType = !!typeUrl && registry.findMessage<T>(typeUrl);");
|
|
332
|
+
f.print(" return messageType ? {message: messageType.fromBinary(msg.", localName(ref.value), "), messageType} : undefined;");
|
|
333
|
+
f.print(" },");
|
|
334
|
+
f.print();
|
|
335
|
+
f.print(" is(msg: ", message, ", msgType: ", MessageType, " | string): boolean {");
|
|
336
|
+
f.print(" const name = msg.", localName(ref.typeUrl)), ";";
|
|
337
|
+
f.print(" return !!name && (typeof msgType === 'string' ? name === msgType : name === msgType.typeName);");
|
|
338
|
+
f.print(" },");
|
|
339
|
+
break;
|
|
340
|
+
case "google.protobuf.Timestamp":
|
|
341
|
+
f.print(" fromJson(json: ", JsonValue, "): ", message, " {");
|
|
342
|
+
f.print(` if (typeof json !== "string") {`);
|
|
343
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, "(json)}`);");
|
|
344
|
+
f.print(" }");
|
|
345
|
+
f.print(` const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);`);
|
|
346
|
+
f.print(" if (!matches) {");
|
|
347
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: invalid RFC 3339 string`);");
|
|
348
|
+
f.print(" }");
|
|
349
|
+
f.print(` const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));`);
|
|
350
|
+
f.print(" if (Number.isNaN(ms)) {");
|
|
351
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: invalid RFC 3339 string`);");
|
|
352
|
+
f.print(" }");
|
|
353
|
+
f.print(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`);
|
|
354
|
+
f.print(" throw new Error(`cannot decode message ", message.typeName, " from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);");
|
|
355
|
+
f.print(" }");
|
|
356
|
+
f.print(" return {");
|
|
357
|
+
if (ref.seconds.longType === LongType.STRING) {
|
|
358
|
+
f.print(" ", localName(ref.seconds), ": ", protoInt64, ".parse(ms / 1000).toString(),");
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
f.print(" ", localName(ref.seconds), ": ", protoInt64, ".parse(ms / 1000),");
|
|
362
|
+
}
|
|
363
|
+
f.print(" ", localName(ref.nanos), ": !matches[7] ? 0 : ", `(parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000),`);
|
|
364
|
+
f.print(" }");
|
|
365
|
+
f.print(" },");
|
|
366
|
+
f.print(" toJson(msg: ", message, "): JsonValue {");
|
|
367
|
+
f.print(" const ms = Number(msg.", localName(ref.seconds), ") * 1000;");
|
|
368
|
+
f.print(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`);
|
|
369
|
+
f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);");
|
|
370
|
+
f.print(" }");
|
|
371
|
+
f.print(" if (msg.", localName(ref.nanos), " != null && msg.", localName(ref.nanos), " < 0) {");
|
|
372
|
+
f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: nanos must not be negative`);");
|
|
373
|
+
f.print(" }");
|
|
374
|
+
f.print(` let z = "Z";`);
|
|
375
|
+
f.print(" if (msg.", localName(ref.nanos), " != null && msg.", localName(ref.nanos), " > 0) {");
|
|
376
|
+
f.print(" const nanosStr = (msg.", localName(ref.nanos), " + 1000000000).toString().substring(1);");
|
|
377
|
+
f.print(` if (nanosStr.substring(3) === "000000") {`);
|
|
378
|
+
f.print(` z = "." + nanosStr.substring(0, 3) + "Z";`);
|
|
379
|
+
f.print(` } else if (nanosStr.substring(6) === "000") {`);
|
|
380
|
+
f.print(` z = "." + nanosStr.substring(0, 6) + "Z";`);
|
|
381
|
+
f.print(" } else {");
|
|
382
|
+
f.print(` z = "." + nanosStr + "Z";`);
|
|
383
|
+
f.print(" }");
|
|
384
|
+
f.print(" }");
|
|
385
|
+
f.print(` return new Date(ms).toISOString().replace(".000Z", z);`);
|
|
386
|
+
f.print(" },");
|
|
387
|
+
f.print(" toDate(msg: ", message, "): Date {");
|
|
388
|
+
f.print(" return new Date(Number(msg.", localName(ref.seconds), " ?? 0) * 1000 + Math.ceil((msg.", localName(ref.nanos), " ?? 0) / 1000000));");
|
|
389
|
+
f.print(" },");
|
|
390
|
+
break;
|
|
391
|
+
case "google.protobuf.Duration":
|
|
392
|
+
f.print(" fromJson(json: ", JsonValue, " | null | undefined, _options?: Partial<", JsonReadOptions, ">): ", message, " {");
|
|
393
|
+
f.print(` if (typeof json !== "string") {`);
|
|
394
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", jsonDebugValue, "(json)}`);");
|
|
395
|
+
f.print(" }");
|
|
396
|
+
f.print(` const match = json.match(/^(-?[0-9]+)(?:\\.([0-9]+))?s/);`);
|
|
397
|
+
f.print(" if (match === null) {");
|
|
398
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", jsonDebugValue, "(json)}`);");
|
|
399
|
+
f.print(" }");
|
|
400
|
+
f.print(" const longSeconds = Number(match[1]);");
|
|
401
|
+
f.print(" if (longSeconds > 315576000000 || longSeconds < -315576000000) {");
|
|
402
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", jsonDebugValue, "(json)}`);");
|
|
403
|
+
f.print(" }");
|
|
404
|
+
f.print(" const msg = {} as ", message, ";");
|
|
405
|
+
if (ref.seconds.longType === LongType.STRING) {
|
|
406
|
+
f.print(" msg.", localName(ref.seconds), " = ", protoInt64, ".parse(longSeconds).toString();");
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
f.print(" msg.", localName(ref.seconds), " = ", protoInt64, ".parse(longSeconds);");
|
|
410
|
+
}
|
|
411
|
+
f.print(` if (typeof match[2] == "string") {`);
|
|
412
|
+
f.print(` const nanosStr = match[2] + "0".repeat(9 - match[2].length);`);
|
|
413
|
+
f.print(" msg.", localName(ref.nanos), " = parseInt(nanosStr);");
|
|
414
|
+
f.print(" if (longSeconds < 0 || Object.is(longSeconds, -0)) {");
|
|
415
|
+
f.print(" msg.", localName(ref.nanos), " = -msg.", localName(ref.nanos), ";");
|
|
416
|
+
f.print(" }");
|
|
417
|
+
f.print(" }");
|
|
418
|
+
f.print(" return msg;");
|
|
419
|
+
f.print(" },");
|
|
420
|
+
f.print(" toJson(msg: ", message, "): JsonValue {");
|
|
421
|
+
f.print(" const secs = Number(msg.", localName(ref.seconds), " ?? 0);");
|
|
422
|
+
f.print(" const nanos = Number(msg.", localName(ref.nanos), " ?? 0);");
|
|
423
|
+
f.print(" if (secs > 315576000000 || secs < -315576000000) {");
|
|
424
|
+
f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: value out of range`);");
|
|
425
|
+
f.print(" }");
|
|
426
|
+
f.print(" let text = secs.toString();");
|
|
427
|
+
f.print(" if (nanos !== 0) {");
|
|
428
|
+
f.print(" let nanosStr = Math.abs(nanos).toString();");
|
|
429
|
+
f.print(` nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr;`);
|
|
430
|
+
f.print(` if (nanosStr.substring(3) === "000000") {`);
|
|
431
|
+
f.print(" nanosStr = nanosStr.substring(0, 3);");
|
|
432
|
+
f.print(` } else if (nanosStr.substring(6) === "000") {`);
|
|
433
|
+
f.print(" nanosStr = nanosStr.substring(0, 6);");
|
|
434
|
+
f.print(` }`);
|
|
435
|
+
f.print(` text += "." + nanosStr;`);
|
|
436
|
+
f.print(" if (nanos < 0 && secs === 0) {");
|
|
437
|
+
f.print(` text = "-" + text;`);
|
|
438
|
+
f.print(` }`);
|
|
439
|
+
f.print(" }");
|
|
440
|
+
f.print(` return text + "s";`);
|
|
441
|
+
f.print(" },");
|
|
442
|
+
break;
|
|
443
|
+
case "google.protobuf.Struct":
|
|
444
|
+
f.print(" toJson(msg: ", message, ", options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {");
|
|
445
|
+
f.print(" const json: ", JsonObject, " = {}");
|
|
446
|
+
f.print(" if (!msg.", localName(ref.fields), ") { return json; }");
|
|
447
|
+
f.print(" for (const [k, v] of Object.entries(msg.", localName(ref.fields), ")) {");
|
|
448
|
+
f.print(" json[k] = v != null ? ", ref.fields.mapValue.message, ".toJson(v, options) : null;");
|
|
449
|
+
f.print(" }");
|
|
450
|
+
f.print(" return json;");
|
|
451
|
+
f.print(" },");
|
|
452
|
+
f.print(" fromJson(json: ", JsonValue, " | null | undefined, _options?: Partial<", JsonReadOptions, ">): ", message, " {");
|
|
453
|
+
f.print(` if (typeof json != "object" || json == null || Array.isArray(json)) {`);
|
|
454
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON ${", jsonDebugValue, "(json)}`);");
|
|
455
|
+
f.print(" }");
|
|
456
|
+
f.print(" const fields = {} as { [key: string]: Value };");
|
|
457
|
+
f.print(" for (const [k, v] of Object.entries(json)) {");
|
|
458
|
+
f.print(" fields[k] = ", ref.fields.mapValue.message ?? "", ".fromJson(v);");
|
|
459
|
+
f.print(" }");
|
|
460
|
+
f.print(" return {", localName(ref.fields), ": fields} as ", message, ";");
|
|
461
|
+
f.print(" },");
|
|
462
|
+
break;
|
|
463
|
+
case "google.protobuf.Value":
|
|
464
|
+
f.print(" toJson(msg: ", message, ", options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {");
|
|
465
|
+
f.print(" switch (msg.", localName(ref.kind), "?.case) {");
|
|
466
|
+
f.print(` case "`, localName(ref.nullValue), `":`);
|
|
467
|
+
f.print(" return null;");
|
|
468
|
+
f.print(` case "`, localName(ref.numberValue), `":`);
|
|
469
|
+
f.print(` if (!Number.isFinite(msg.`, localName(ref.kind), `.value)) {`);
|
|
470
|
+
f.print(` throw new Error("google.protobuf.Value cannot be NaN or Infinity");`);
|
|
471
|
+
f.print(` }`);
|
|
472
|
+
f.print(` return msg.`, localName(ref.kind), `.value;`);
|
|
473
|
+
f.print(` case "`, localName(ref.boolValue), `":`);
|
|
474
|
+
f.print(` return msg.`, localName(ref.kind), `.value;`);
|
|
475
|
+
f.print(` case "`, localName(ref.stringValue), `":`);
|
|
476
|
+
f.print(" return msg.", localName(ref.kind), ".value;");
|
|
477
|
+
f.print(` case "`, localName(ref.structValue), `":`);
|
|
478
|
+
f.print(` return `, ref.structValue.message, `.toJson(msg.`, localName(ref.kind), `.value, {...options, emitDefaultValues: true});`);
|
|
479
|
+
f.print(` case "`, localName(ref.listValue), `":`);
|
|
480
|
+
f.print(` return `, ref.listValue.message, `.toJson(msg.`, localName(ref.kind), `.value, {...options, emitDefaultValues: true});`);
|
|
481
|
+
f.print(` case null:`);
|
|
482
|
+
f.print(` case undefined:`);
|
|
483
|
+
f.print(` default:`);
|
|
484
|
+
f.print(` return null;`);
|
|
485
|
+
f.print(" }");
|
|
486
|
+
f.print(" },");
|
|
487
|
+
f.print(" fromJson(json: ", JsonValue, " | null | undefined, _options?: Partial<", JsonReadOptions, ">): ", message, " {");
|
|
488
|
+
f.print(" const msg = {} as ", message, ";");
|
|
489
|
+
f.print(" switch (typeof json) {");
|
|
490
|
+
f.print(` case "number":`);
|
|
491
|
+
f.print(` msg.kind = { case: "`, localName(ref.numberValue), `", value: json };`);
|
|
492
|
+
f.print(" break;");
|
|
493
|
+
f.print(` case "string":`);
|
|
494
|
+
f.print(` msg.kind = { case: "`, localName(ref.stringValue), `", value: json };`);
|
|
495
|
+
f.print(" break;");
|
|
496
|
+
f.print(` case "boolean":`);
|
|
497
|
+
f.print(` msg.kind = { case: "`, localName(ref.boolValue), `", value: json };`);
|
|
498
|
+
f.print(" break;");
|
|
499
|
+
f.print(` case "object":`);
|
|
500
|
+
f.print(" if (json == null) {");
|
|
501
|
+
f.print(` msg.kind = { case: "`, localName(ref.nullValue), `", value: `, ref.nullValue.enum, `.`, localName(ref.nullValue.enum.values[0]), ` };`);
|
|
502
|
+
f.print(" } else if (Array.isArray(json)) {");
|
|
503
|
+
f.print(` msg.kind = { case: "`, localName(ref.listValue), `", value: `, ref.listValue.message, `.fromJson(json) };`);
|
|
504
|
+
f.print(" } else {");
|
|
505
|
+
f.print(` msg.kind = { case: "`, localName(ref.structValue), `", value: `, ref.structValue.message, `.fromJson(json) };`);
|
|
506
|
+
f.print(" }");
|
|
507
|
+
f.print(" break;");
|
|
508
|
+
f.print(" default:");
|
|
509
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON ${", jsonDebugValue, "(json)}`);");
|
|
510
|
+
f.print(" }");
|
|
511
|
+
f.print(" return msg;");
|
|
512
|
+
f.print(" },");
|
|
513
|
+
break;
|
|
514
|
+
case "google.protobuf.ListValue":
|
|
515
|
+
f.print(` toJson(msg: `, message, `, options?: Partial<`, JsonWriteOptions, `>): `, JsonValue, ` {`);
|
|
516
|
+
f.print(` return msg.`, localName(ref.values), `?.map(v => `, ref.values.message, `.toJson(v, options)) ?? [];`);
|
|
517
|
+
f.print(` },`);
|
|
518
|
+
f.print(` fromJson(json: `, JsonValue, ` | null | undefined, options?: Partial<`, JsonReadOptions, `>): `, message, ` {`);
|
|
519
|
+
f.print(` if (json == null) { return {}; }`);
|
|
520
|
+
f.print(` if (!Array.isArray(json)) {`);
|
|
521
|
+
f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON ${", jsonDebugValue, "(json)}`);");
|
|
522
|
+
f.print(` }`);
|
|
523
|
+
f.print(` const values: `, ref.values.message, `[] = json.map(v => `, ref.values.message, `.fromJson(v, options));`);
|
|
524
|
+
f.print(` return {`, localName(ref.values), `: values} as `, message, `;`);
|
|
525
|
+
f.print(` },`);
|
|
526
|
+
break;
|
|
527
|
+
case "google.protobuf.DoubleValue":
|
|
528
|
+
case "google.protobuf.FloatValue":
|
|
529
|
+
case "google.protobuf.Int64Value":
|
|
530
|
+
case "google.protobuf.UInt64Value":
|
|
531
|
+
case "google.protobuf.Int32Value":
|
|
532
|
+
case "google.protobuf.UInt32Value":
|
|
533
|
+
case "google.protobuf.BoolValue":
|
|
534
|
+
case "google.protobuf.StringValue":
|
|
535
|
+
case "google.protobuf.BytesValue":
|
|
536
|
+
f.print(" toJson(msg: ", message, ", _options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {");
|
|
537
|
+
f.print(" return ", jsonWriteScalar, "(", rtScalarType, ".", ScalarType[ref.value.scalar], ", msg.value)!;");
|
|
538
|
+
f.print(" },");
|
|
539
|
+
f.print(" fromJson(json: ", JsonValue, " | null | undefined, _options?: Partial<", JsonReadOptions, ">): ", message, " {");
|
|
540
|
+
f.print(" try {");
|
|
541
|
+
f.print(" return {", localName(ref.value), ": ", jsonReadScalar, "(", rtScalarType, ".", ScalarType[ref.value.scalar], ", json, ", rtLongType, ".", LongType[ref.value.longType], ")} as ", message, ";");
|
|
542
|
+
f.print(" } catch (e) {");
|
|
543
|
+
f.print(" let m = `cannot decode message ", message.typeName, ' from JSON"`;');
|
|
544
|
+
f.print(" if (e instanceof Error && e.message.length > 0) {");
|
|
545
|
+
f.print(" m += `: ${e.message}`");
|
|
546
|
+
f.print(" }");
|
|
547
|
+
f.print(" throw new Error(m);");
|
|
548
|
+
f.print(" }");
|
|
549
|
+
f.print(" },");
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
function generateWktFieldWrapper(f, message, ref) {
|
|
554
|
+
switch (ref?.typeName) {
|
|
555
|
+
case "google.protobuf.DoubleValue":
|
|
556
|
+
case "google.protobuf.FloatValue":
|
|
557
|
+
case "google.protobuf.Int64Value":
|
|
558
|
+
case "google.protobuf.UInt64Value":
|
|
559
|
+
case "google.protobuf.Int32Value":
|
|
560
|
+
case "google.protobuf.UInt32Value":
|
|
561
|
+
case "google.protobuf.BoolValue":
|
|
562
|
+
case "google.protobuf.StringValue":
|
|
563
|
+
case "google.protobuf.BytesValue": {
|
|
564
|
+
const { typing } = getFieldTypeInfo(ref.value);
|
|
565
|
+
f.print(" fieldWrapper: {");
|
|
566
|
+
f.print(" wrapField(value: ", typing, " | null | undefined): ", message, " {");
|
|
567
|
+
f.print(" return ", message, ".create({ value: value ?? undefined });");
|
|
568
|
+
f.print(" },");
|
|
569
|
+
f.print(" unwrapField(msg: ", message, "): ", typing, " | null | undefined {");
|
|
570
|
+
f.print(" return msg.", localName(ref.value), ";");
|
|
571
|
+
f.print(" }");
|
|
572
|
+
f.print(" } as const,");
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|