ts-proto 2.10.1 → 2.11.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/README.markdown +3 -0
- package/build/src/main.js +65 -4
- package/build/src/options.d.ts +1 -0
- package/build/src/options.js +6 -0
- package/build/src/schema.js +1 -1
- package/package.json +1 -1
package/README.markdown
CHANGED
|
@@ -414,6 +414,9 @@ Generated code will be placed in the Gradle build directory.
|
|
|
414
414
|
|
|
415
415
|
The default behavior is `keys_json`, i.e. both will be camel cased, and `json_name` will be used if set.
|
|
416
416
|
|
|
417
|
+
- With `--ts_proto_opt=protoJsonFormat=true` (default), the `toJSON` and `fromJSON` methods follow the [protoJSON format](https://protobuf.dev/programming-guides/json). This means `toJSON` will output standard lowerCamelCase keys (or custom `json_name` if set). `fromJSON` will accept both the lowerCamelCase key (or `json_name`) AND the original proto field name.
|
|
418
|
+
With `--ts_proto_opt=protoJsonFormat=false`, strict proto3 compliance is disabled. The JSON keys will simply follow the `snakeToCamel` option, and `fromJSON` will only accept that specific format.
|
|
419
|
+
|
|
417
420
|
- With `--ts_proto_opt=outputEncodeMethods=false`, the `Message.encode` and `Message.decode` methods for working with protobuf-encoded/binary data will not be output.
|
|
418
421
|
|
|
419
422
|
This is useful if you want "only types".
|
package/build/src/main.js
CHANGED
|
@@ -1964,6 +1964,9 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1964
1964
|
};
|
|
1965
1965
|
const noDefaultValue = !options.initializeFieldsAsUndefined &&
|
|
1966
1966
|
(0, types_1.isOptionalProperty)(field, messageDesc.options, options, currentFile.isProto3Syntax);
|
|
1967
|
+
// if the protoJsonFormat option is enabled and the field name is different from the json name, we need to
|
|
1968
|
+
// accept both formats in the fromJSON method.
|
|
1969
|
+
let protoJsonComparison = (0, ts_poet_1.code) ``;
|
|
1967
1970
|
// and then use the snippet to handle repeated fields if necessary
|
|
1968
1971
|
if (canonicalFromJson[fullTypeName]?.[fieldName]) {
|
|
1969
1972
|
chunks.push((0, ts_poet_1.code) `${fieldName}: ${canonicalFromJson[fullTypeName][fieldName]("object")},`);
|
|
@@ -1975,23 +1978,45 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1975
1978
|
const i = convertFromObjectKey(ctx, messageDesc, field, "key");
|
|
1976
1979
|
if ((0, types_1.shouldGenerateJSMapType)(ctx, messageDesc, field)) {
|
|
1977
1980
|
const fallback = noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : "new Map()";
|
|
1981
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
1982
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
1983
|
+
protoJsonComparison = (0, ts_poet_1.code) `
|
|
1984
|
+
: ${ctx.utils.isObject}(${protoJsonProperty})
|
|
1985
|
+
? (${ctx.utils.globalThis}.Object.entries(${protoJsonProperty}) as [string, any][]).reduce((acc: ${fieldType}, [key, value]: [string, any]) => {
|
|
1986
|
+
acc.set(${i}, ${readSnippet("value")});
|
|
1987
|
+
return acc;
|
|
1988
|
+
}, new Map())
|
|
1989
|
+
`;
|
|
1990
|
+
}
|
|
1978
1991
|
chunks.push((0, ts_poet_1.code) `
|
|
1979
1992
|
${fieldKey}: ${ctx.utils.isObject}(${jsonProperty})
|
|
1980
1993
|
? (${ctx.utils.globalThis}.Object.entries(${jsonProperty}) as [string, any][]).reduce((acc: ${fieldType}, [key, value]: [string, any]) => {
|
|
1981
1994
|
acc.set(${i}, ${readSnippet("value")});
|
|
1982
1995
|
return acc;
|
|
1983
1996
|
}, new Map())
|
|
1997
|
+
${protoJsonComparison}
|
|
1984
1998
|
: ${fallback},
|
|
1985
1999
|
`);
|
|
1986
2000
|
}
|
|
1987
2001
|
else {
|
|
1988
2002
|
const fallback = noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : "{}";
|
|
2003
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2004
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2005
|
+
protoJsonComparison = (0, ts_poet_1.code) `
|
|
2006
|
+
: ${ctx.utils.isObject}(${protoJsonProperty})
|
|
2007
|
+
? (${ctx.utils.globalThis}.Object.entries(${protoJsonProperty}) as [string, any][]).reduce((acc: ${fieldType}, [key, value]: [string, any]) => {
|
|
2008
|
+
acc[${i}] = ${readSnippet("value")};
|
|
2009
|
+
return acc;
|
|
2010
|
+
}, {})
|
|
2011
|
+
`;
|
|
2012
|
+
}
|
|
1989
2013
|
chunks.push((0, ts_poet_1.code) `
|
|
1990
2014
|
${fieldKey}: ${ctx.utils.isObject}(${jsonProperty})
|
|
1991
2015
|
? (${ctx.utils.globalThis}.Object.entries(${jsonProperty}) as [string, any][]).reduce((acc: ${fieldType}, [key, value]: [string, any]) => {
|
|
1992
2016
|
acc[${i}] = ${readSnippet("value")};
|
|
1993
2017
|
return acc;
|
|
1994
2018
|
}, {})
|
|
2019
|
+
${protoJsonComparison}
|
|
1995
2020
|
: ${fallback},
|
|
1996
2021
|
`);
|
|
1997
2022
|
}
|
|
@@ -2000,12 +2025,22 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
2000
2025
|
const fallback = noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : "[]";
|
|
2001
2026
|
const needMap = readSnippet("e").toString() !== (0, ts_poet_1.code) `e`.toString();
|
|
2002
2027
|
if (!needMap) {
|
|
2003
|
-
|
|
2028
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2029
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2030
|
+
const protoJsonPropertyOptional = (0, utils_1.getPropertyAccessor)("object", field.name, true);
|
|
2031
|
+
protoJsonComparison = (0, ts_poet_1.code) ` : ${ctx.utils.globalThis}.Array.isArray(${protoJsonPropertyOptional}) ? [...${protoJsonProperty}]`;
|
|
2032
|
+
}
|
|
2033
|
+
chunks.push((0, ts_poet_1.code) `${fieldKey}: ${ctx.utils.globalThis}.Array.isArray(${jsonPropertyOptional}) ? [...${jsonProperty}] ${protoJsonComparison} : [],`);
|
|
2004
2034
|
}
|
|
2005
2035
|
else {
|
|
2006
2036
|
// Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
|
|
2037
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2038
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2039
|
+
const protoJsonPropertyOptional = (0, utils_1.getPropertyAccessor)("object", field.name, true);
|
|
2040
|
+
protoJsonComparison = (0, ts_poet_1.code) ` : ${ctx.utils.globalThis}.Array.isArray(${protoJsonPropertyOptional}) ? ${protoJsonProperty}.map((e: any) => ${readSnippet("e")})`;
|
|
2041
|
+
}
|
|
2007
2042
|
chunks.push((0, ts_poet_1.code) `
|
|
2008
|
-
${fieldKey}: ${ctx.utils.globalThis}.Array.isArray(${jsonPropertyOptional}) ? ${jsonProperty}.map((e: any) => ${readSnippet("e")}): ${fallback},
|
|
2043
|
+
${fieldKey}: ${ctx.utils.globalThis}.Array.isArray(${jsonPropertyOptional}) ? ${jsonProperty}.map((e: any) => ${readSnippet("e")}) ${protoJsonComparison} : ${fallback},
|
|
2009
2044
|
`);
|
|
2010
2045
|
}
|
|
2011
2046
|
}
|
|
@@ -2022,33 +2057,59 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
2022
2057
|
const ternaryIf = (0, ts_poet_1.code) `${ctx.utils.isSet}(${jsonProperty})`;
|
|
2023
2058
|
const ternaryThen = (0, ts_poet_1.code) `{ $case: '${fieldName}', ${valueName}: ${readSnippet(`${jsonProperty}`)}`;
|
|
2024
2059
|
chunks.push((0, ts_poet_1.code) `${ternaryIf} ? ${ternaryThen}} : `);
|
|
2060
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2061
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2062
|
+
const ternaryOriginalIf = (0, ts_poet_1.code) `${ctx.utils.isSet}(${protoJsonProperty})`;
|
|
2063
|
+
const ternaryOriginalThen = (0, ts_poet_1.code) `{ $case: '${fieldName}', ${valueName}: ${readSnippet(`${protoJsonProperty}`)}`;
|
|
2064
|
+
chunks.push((0, ts_poet_1.code) `${ternaryOriginalIf} ? ${ternaryOriginalThen}} : `);
|
|
2065
|
+
}
|
|
2025
2066
|
if (field === lastCase) {
|
|
2026
2067
|
chunks.push((0, ts_poet_1.code) `${(0, utils_1.nullOrUndefined)(options)},`);
|
|
2027
2068
|
}
|
|
2028
2069
|
}
|
|
2029
2070
|
else if ((0, types_1.isAnyValueType)(field)) {
|
|
2071
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2072
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2073
|
+
const protoJsonPropertyOptional = (0, utils_1.getPropertyAccessor)("object", field.name, true);
|
|
2074
|
+
protoJsonComparison = (0, ts_poet_1.code) ` : ${ctx.utils.isSet}(${protoJsonPropertyOptional}) ? ${readSnippet(`${protoJsonProperty}`)}`;
|
|
2075
|
+
}
|
|
2030
2076
|
chunks.push((0, ts_poet_1.code) `${fieldKey}: ${ctx.utils.isSet}(${jsonPropertyOptional})
|
|
2031
2077
|
? ${readSnippet(`${jsonProperty}`)}
|
|
2078
|
+
${protoJsonComparison}
|
|
2032
2079
|
: ${(0, utils_1.nullOrUndefined)(options)},
|
|
2033
2080
|
`);
|
|
2034
2081
|
}
|
|
2035
2082
|
else if ((0, types_1.isStructType)(field)) {
|
|
2083
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2084
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2085
|
+
protoJsonComparison = (0, ts_poet_1.code) ` : ${ctx.utils.isObject}(${protoJsonProperty}) ? ${readSnippet(`${protoJsonProperty}`)}`;
|
|
2086
|
+
}
|
|
2036
2087
|
chunks.push((0, ts_poet_1.code) `${fieldKey}: ${ctx.utils.isObject}(${jsonProperty})
|
|
2037
2088
|
? ${readSnippet(`${jsonProperty}`)}
|
|
2089
|
+
${protoJsonComparison}
|
|
2038
2090
|
: ${(0, utils_1.nullOrUndefined)(options)},`);
|
|
2039
2091
|
}
|
|
2040
2092
|
else if ((0, types_1.isListValueType)(field)) {
|
|
2093
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2094
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2095
|
+
protoJsonComparison = (0, ts_poet_1.code) ` : ${ctx.utils.globalThis}.Array.isArray(${protoJsonProperty}) ? ${readSnippet(`${protoJsonProperty}`)}`;
|
|
2096
|
+
}
|
|
2041
2097
|
chunks.push((0, ts_poet_1.code) `
|
|
2042
2098
|
${fieldKey}: ${ctx.utils.globalThis}.Array.isArray(${jsonProperty})
|
|
2043
2099
|
? ${readSnippet(`${jsonProperty}`)}
|
|
2100
|
+
${protoJsonComparison}
|
|
2044
2101
|
: ${(0, utils_1.nullOrUndefined)(options)},
|
|
2045
2102
|
`);
|
|
2046
2103
|
}
|
|
2047
2104
|
else {
|
|
2048
2105
|
const fallback = (0, types_1.isWithinOneOf)(field) || noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : (0, types_1.defaultValue)(ctx, field);
|
|
2106
|
+
if (options.protoJsonFormat && field.name !== field.jsonName) {
|
|
2107
|
+
const protoJsonProperty = (0, utils_1.getPropertyAccessor)("object", field.name);
|
|
2108
|
+
protoJsonComparison = (0, ts_poet_1.code) ` : ${ctx.utils.isSet}(${protoJsonProperty}) ? ${readSnippet(`${protoJsonProperty}`)}`;
|
|
2109
|
+
}
|
|
2049
2110
|
chunks.push((0, ts_poet_1.code) `
|
|
2050
|
-
${fieldKey}: ${ctx.utils.isSet}(${jsonProperty})
|
|
2051
|
-
|
|
2111
|
+
${fieldKey}: ${ctx.utils.isSet}(${jsonProperty}) ? ${readSnippet(`${jsonProperty}`)}
|
|
2112
|
+
${protoJsonComparison}
|
|
2052
2113
|
: ${fallback},
|
|
2053
2114
|
`);
|
|
2054
2115
|
}
|
package/build/src/options.d.ts
CHANGED
package/build/src/options.js
CHANGED
|
@@ -60,6 +60,7 @@ function defaultOptions() {
|
|
|
60
60
|
return {
|
|
61
61
|
context: false,
|
|
62
62
|
snakeToCamel: ["json", "keys"],
|
|
63
|
+
protoJsonFormat: true,
|
|
63
64
|
emitDefaultValues: [],
|
|
64
65
|
globalThisPolyfill: false,
|
|
65
66
|
forceLong: LongOption.NUMBER,
|
|
@@ -204,6 +205,11 @@ function optionsFromParameter(parameter) {
|
|
|
204
205
|
else if (typeof options.snakeToCamel === "string") {
|
|
205
206
|
options.snakeToCamel = options.snakeToCamel.split("_");
|
|
206
207
|
}
|
|
208
|
+
if (options.protoJsonFormat && !options.snakeToCamel.includes("json")) {
|
|
209
|
+
// protoJSONFormat implies snakeToCamel=json, Message field names must be mapped to lowerCamelCase and become JSON object keys.
|
|
210
|
+
// If the json_name field option is specified, the specified value will be used as the key instead.
|
|
211
|
+
options.snakeToCamel.push("json");
|
|
212
|
+
}
|
|
207
213
|
if (options.emitDefaultValues === "json-methods") {
|
|
208
214
|
options.emitDefaultValues = ["json-methods"];
|
|
209
215
|
}
|
package/build/src/schema.js
CHANGED
|
@@ -70,7 +70,7 @@ function generateSchema(ctx, fileDesc, sourceInfo) {
|
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
const dependencies = fileDesc.dependency.map((dep) => {
|
|
73
|
-
return (0, ts_poet_1.code) `${(0, utils_1.impFile)(options, `protoMetadata@./${dep.replace(".proto", "")}`)}`;
|
|
73
|
+
return (0, ts_poet_1.code) `${(0, utils_1.impFile)(options, `protoMetadata@./${dep.replace(".proto", "")}${options.fileSuffix}`)}`;
|
|
74
74
|
});
|
|
75
75
|
// Use toObject so that we get enums as numbers (instead of the default toJSON behavior)
|
|
76
76
|
const descriptor = ts_proto_descriptors_1.FileDescriptorProto.fromPartial(fileDesc);
|