ts-proto 1.153.3 → 1.154.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.markdown CHANGED
@@ -728,26 +728,15 @@ Foo.fromJSON({ bar: "" }); // => { bar: '' }
728
728
  Foo.fromJSON({ bar: "baz" }); // => { bar: 'baz' }
729
729
  ```
730
730
 
731
- When writing JSON, `ts-proto` currently does **not** normalize message when converting to JSON, other than omitting unset fields, but it may do so in the future.
731
+ When writing JSON, `ts-proto` normalizes messages by omitting unset fields and fields set to their default values.
732
732
 
733
733
  ```typescript
734
- // Current ts-proto behavior
735
- Foo.toJSON({}); // => { }
736
- Foo.toJSON({ bar: undefined }); // => { }
737
- Foo.toJSON({ bar: "" }); // => { bar: '' } - note: this is the default value, but it's not omitted
738
- Foo.toJSON({ bar: "baz" }); // => { bar: 'baz' }
739
- ```
740
-
741
- ```typescript
742
- // Possible future behavior, where ts-proto would normalize message
743
734
  Foo.toJSON({}); // => { }
744
735
  Foo.toJSON({ bar: undefined }); // => { }
745
736
  Foo.toJSON({ bar: "" }); // => { } - note: omitting the default value, as expected
746
737
  Foo.toJSON({ bar: "baz" }); // => { bar: 'baz' }
747
738
  ```
748
739
 
749
- - Please open an issue if you need this behavior.
750
-
751
740
  # Well-Known Types
752
741
 
753
742
  Protobuf comes with several predefined message definitions, called "[Well-Known Types](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf)".
package/build/main.js CHANGED
@@ -1662,9 +1662,7 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1662
1662
  const readSnippet = (from) => {
1663
1663
  if ((0, types_1.isEnum)(field)) {
1664
1664
  const toJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "ToJSON");
1665
- return (0, types_1.isWithinOneOf)(field)
1666
- ? (0, ts_poet_1.code) `${from} !== undefined ? ${toJson}(${from}) : undefined`
1667
- : (0, ts_poet_1.code) `${toJson}(${from})`;
1665
+ return (0, ts_poet_1.code) `${toJson}(${from})`;
1668
1666
  }
1669
1667
  else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
1670
1668
  return (0, ts_poet_1.code) `${from}.toString()`;
@@ -1729,19 +1727,13 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1729
1727
  }
1730
1728
  else if ((0, types_1.isMessage)(field) && !(0, types_1.isValueType)(ctx, field) && !(0, types_1.isMapType)(ctx, messageDesc, field)) {
1731
1729
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1732
- return (0, ts_poet_1.code) `${from} ? ${type}.toJSON(${from}) : ${(0, types_1.defaultValue)(ctx, field)}`;
1730
+ return (0, ts_poet_1.code) `${type}.toJSON(${from})`;
1733
1731
  }
1734
1732
  else if ((0, types_1.isBytes)(field)) {
1735
- if ((0, types_1.isWithinOneOf)(field)) {
1736
- return (0, ts_poet_1.code) `${from} !== undefined ? ${utils.base64FromBytes}(${from}) : undefined`;
1737
- }
1738
- else {
1739
- return (0, ts_poet_1.code) `${utils.base64FromBytes}(${from} !== undefined ? ${from} : ${(0, types_1.defaultValue)(ctx, field)})`;
1740
- }
1733
+ return (0, ts_poet_1.code) `${utils.base64FromBytes}(${from})`;
1741
1734
  }
1742
1735
  else if ((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.LONG) {
1743
- const v = (0, types_1.isWithinOneOf)(field) ? "undefined" : (0, types_1.defaultValue)(ctx, field);
1744
- return (0, ts_poet_1.code) `(${from} || ${v}).toString()`;
1736
+ return (0, ts_poet_1.code) `(${from} || ${(0, types_1.defaultValue)(ctx, field)}).toString()`;
1745
1737
  }
1746
1738
  else if ((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.BIGINT) {
1747
1739
  return (0, ts_poet_1.code) `${from}.toString()`;
@@ -1758,8 +1750,8 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1758
1750
  const i = convertToObjectKey(ctx, messageDesc, field, "k");
1759
1751
  if (ctx.options.useMapType) {
1760
1752
  chunks.push((0, ts_poet_1.code) `
1761
- ${jsonProperty} = {};
1762
- if (message.${fieldName}) {
1753
+ if (message.${fieldName}?.size) {
1754
+ ${jsonProperty} = {};
1763
1755
  message.${fieldName}.forEach((v, k) => {
1764
1756
  ${jsonProperty}[${i}] = ${readSnippet("v")};
1765
1757
  });
@@ -1768,34 +1760,46 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1768
1760
  }
1769
1761
  else {
1770
1762
  chunks.push((0, ts_poet_1.code) `
1771
- ${jsonProperty} = {};
1772
- if (message.${fieldName}) {
1773
- Object.entries(message.${fieldName}).forEach(([k, v]) => {
1774
- ${jsonProperty}[${i}] = ${readSnippet("v")};
1775
- });
1763
+ if (message.${fieldName}) {
1764
+ const entries = Object.entries(message.${fieldName});
1765
+ if (entries.length > 0) {
1766
+ ${jsonProperty} = {};
1767
+ entries.forEach(([k, v]) => {
1768
+ ${jsonProperty}[${i}] = ${readSnippet("v")};
1769
+ });
1770
+ }
1776
1771
  }
1777
1772
  `);
1778
1773
  }
1779
1774
  }
1780
1775
  else if ((0, types_1.isRepeated)(field)) {
1781
1776
  // Arrays might need their elements transformed
1777
+ const transformElement = readSnippet("e");
1778
+ const maybeMap = transformElement.toCodeString([]) !== "e" ? (0, ts_poet_1.code) `.map(e => ${transformElement})` : "";
1782
1779
  chunks.push((0, ts_poet_1.code) `
1783
- if (message.${fieldName}) {
1784
- ${jsonProperty} = message.${fieldName}.map(e => ${readSnippet("e")});
1785
- } else {
1786
- ${jsonProperty} = [];
1780
+ if (message.${fieldName}?.length) {
1781
+ ${jsonProperty} = message.${fieldName}${maybeMap};
1787
1782
  }
1788
1783
  `);
1789
1784
  }
1790
1785
  else if ((0, types_1.isWithinOneOfThatShouldBeUnion)(options, field)) {
1791
1786
  // oneofs in a union are only output as `oneof name = ...`
1792
1787
  const oneofName = (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[field.oneofIndex].name, options);
1793
- const v = readSnippet(`message.${oneofName}?.${fieldName}`);
1794
- chunks.push((0, ts_poet_1.code) `message.${oneofName}?.$case === '${fieldName}' && (${jsonProperty} = ${v});`);
1788
+ chunks.push((0, ts_poet_1.code) `
1789
+ if (message.${oneofName}?.$case === '${fieldName}') {
1790
+ ${jsonProperty} = ${readSnippet(`message.${oneofName}.${fieldName}`)};
1791
+ }
1792
+ `);
1795
1793
  }
1796
1794
  else {
1797
- const v = readSnippet(`message.${fieldName}`);
1798
- chunks.push((0, ts_poet_1.code) `message.${fieldName} !== undefined && (${jsonProperty} = ${v});`);
1795
+ const check = ((0, types_1.isScalar)(field) || (0, types_1.isEnum)(field)) && !(0, types_1.isWithinOneOf)(field)
1796
+ ? (0, types_1.notDefaultCheck)(ctx, field, messageDesc.options, `message.${fieldName}`)
1797
+ : `message.${fieldName} !== undefined`;
1798
+ chunks.push((0, ts_poet_1.code) `
1799
+ if (${check}) {
1800
+ ${jsonProperty} = ${readSnippet(`message.${fieldName}`)};
1801
+ }
1802
+ `);
1799
1803
  }
1800
1804
  });
1801
1805
  chunks.push((0, ts_poet_1.code) `return obj;`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.153.3",
3
+ "version": "1.154.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",