ts-proto 2.11.6 → 2.11.8

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.
Files changed (2) hide show
  1. package/build/src/main.js +71 -13
  2. package/package.json +1 -1
package/build/src/main.js CHANGED
@@ -72,8 +72,7 @@ function generateFile(ctx, fileDesc) {
72
72
  const prefix = (0, case_1.camelToSnake)(fileDesc.package.replace(/\./g, "_"));
73
73
  chunks.push((0, ts_poet_1.code) `export const ${prefix}_PACKAGE_NAME = '${fileDesc.package}';`);
74
74
  }
75
- if (options.useDate === options_1.DateOption.DATE &&
76
- fileDesc.messageType.find((message) => message.field.find((field) => field.typeName === ".google.protobuf.Timestamp"))) {
75
+ if (options.useDate === options_1.DateOption.DATE && fileDesc.messageType.find(hasTimestampField)) {
77
76
  chunks.push(makeProtobufTimestampWrapper());
78
77
  }
79
78
  }
@@ -220,7 +219,7 @@ function generateFile(ctx, fileDesc) {
220
219
  }
221
220
  }
222
221
  if (options.nestJs) {
223
- if (fileDesc.messageType.find((message) => message.field.find(types_1.isStructType))) {
222
+ if (fileDesc.messageType.find(hasStructTypeField)) {
224
223
  chunks.push(makeProtobufStructWrapper(options));
225
224
  }
226
225
  }
@@ -358,6 +357,15 @@ function makeProtobufTimestampWrapper() {
358
357
  },
359
358
  } as any;`;
360
359
  }
360
+ function hasField(message, predicate) {
361
+ return (message.field.some(predicate) || message.nestedType.some((nestedMessage) => hasField(nestedMessage, predicate)));
362
+ }
363
+ function hasTimestampField(message) {
364
+ return hasField(message, types_1.isTimestamp);
365
+ }
366
+ function hasStructTypeField(message) {
367
+ return hasField(message, types_1.isStructType);
368
+ }
361
369
  function makeProtobufStructWrapper(options) {
362
370
  const wrappers = (0, ts_poet_1.imp)("wrappers@protobufjs");
363
371
  const Struct = (0, utils_1.impProto)(options, "google/protobuf/struct", (0, utils_1.wrapTypeName)(options, "Struct"));
@@ -1796,14 +1804,37 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1796
1804
  const chunks = [];
1797
1805
  // Handle Duration string format as a special case
1798
1806
  if (fullTypeName === "google.protobuf.Duration" && ctx.options.useDuration === options_1.DurationOption.STRING) {
1807
+ let parseSeconds;
1808
+ switch (ctx.options.forceLong) {
1809
+ case options_1.LongOption.BIGINT:
1810
+ parseSeconds = (0, ts_poet_1.code) `negative && secondsStr !== "0" ? -BigInt(secondsStr) : BigInt(secondsStr)`;
1811
+ break;
1812
+ case options_1.LongOption.LONG:
1813
+ // Long.fromString handles the sign internally, including the asymmetric i64 min case.
1814
+ parseSeconds = (0, ts_poet_1.code) `${utils.Long}.fromString(negative ? "-" + secondsStr : secondsStr)`;
1815
+ break;
1816
+ case options_1.LongOption.STRING:
1817
+ parseSeconds = (0, ts_poet_1.code) `negative && secondsStr !== "0" ? "-" + secondsStr : secondsStr`;
1818
+ break;
1819
+ case options_1.LongOption.NUMBER:
1820
+ default:
1821
+ parseSeconds = (0, ts_poet_1.code) `negative && secondsStr !== "0" ? -Number(secondsStr) : Number(secondsStr)`;
1822
+ break;
1823
+ }
1799
1824
  return (0, ts_poet_1.code) `
1800
1825
  fromJSON(object: string): ${fullName} {
1801
- const match = object.match(/^(-?[0-9.]+)s$/);
1802
- if (!match) throw new Error('Invalid duration string');
1803
- const seconds = Number(match[1]);
1804
- const wholeSeconds = Math.trunc(seconds);
1805
- const nanos = Math.round((seconds - wholeSeconds) * 1e9);
1806
- return { seconds: wholeSeconds, nanos };
1826
+ if (!object.endsWith("s")) throw new Error("Invalid duration string");
1827
+ const body = object.slice(0, -1);
1828
+ const negative = body.startsWith("-");
1829
+ const unsigned = negative ? body.slice(1) : body;
1830
+ const dot = unsigned.indexOf(".");
1831
+ const secondsStr = dot < 0 ? unsigned : unsigned.slice(0, dot);
1832
+ const fracStr = dot < 0 ? "" : unsigned.slice(dot + 1);
1833
+ if (secondsStr.length === 0) throw new Error("Invalid duration string");
1834
+ const seconds = ${parseSeconds};
1835
+ const nanosAbs = fracStr === "" ? 0 : Number(fracStr.padEnd(9, "0").slice(0, 9));
1836
+ const nanos = negative && nanosAbs !== 0 ? -nanosAbs : nanosAbs;
1837
+ return { seconds, nanos };
1807
1838
  }
1808
1839
  `;
1809
1840
  }
@@ -2120,7 +2151,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
2120
2151
  chunks.push((0, ts_poet_1.code) `}`);
2121
2152
  return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
2122
2153
  }
2123
- function generateCanonicalToJson(fullName, fullProtobufTypeName, { useOptionals, useNullAsOptional, useDuration }) {
2154
+ function generateCanonicalToJson(fullName, fullProtobufTypeName, { useOptionals, useNullAsOptional, useDuration, forceLong }) {
2124
2155
  if ((0, types_1.isFieldMaskTypeName)(fullProtobufTypeName)) {
2125
2156
  const returnType = useOptionals === "all" ? `string | ${(0, utils_1.nullOrUndefined)({ useNullAsOptional })}` : "string";
2126
2157
  const pathModifier = useOptionals === "all" ? "?" : "";
@@ -2131,11 +2162,38 @@ function generateCanonicalToJson(fullName, fullProtobufTypeName, { useOptionals,
2131
2162
  `;
2132
2163
  }
2133
2164
  if (fullProtobufTypeName === "google.protobuf.Duration" && useDuration === options_1.DurationOption.STRING) {
2165
+ let isNegSeconds;
2166
+ let absSeconds;
2167
+ switch (forceLong) {
2168
+ case options_1.LongOption.BIGINT:
2169
+ isNegSeconds = (0, ts_poet_1.code) `message.seconds < 0n`;
2170
+ absSeconds = (0, ts_poet_1.code) `message.seconds < 0n ? -message.seconds : message.seconds`;
2171
+ break;
2172
+ case options_1.LongOption.LONG:
2173
+ // Format via toString rather than negate(); Long.MIN_VALUE.negate() === Long.MIN_VALUE.
2174
+ isNegSeconds = (0, ts_poet_1.code) `message.seconds.isNegative()`;
2175
+ absSeconds = (0, ts_poet_1.code) `message.seconds.isNegative() ? message.seconds.toString().slice(1) : message.seconds.toString()`;
2176
+ break;
2177
+ case options_1.LongOption.STRING:
2178
+ isNegSeconds = (0, ts_poet_1.code) `message.seconds.startsWith("-")`;
2179
+ absSeconds = (0, ts_poet_1.code) `message.seconds.startsWith("-") ? message.seconds.slice(1) : message.seconds`;
2180
+ break;
2181
+ case options_1.LongOption.NUMBER:
2182
+ default:
2183
+ isNegSeconds = (0, ts_poet_1.code) `message.seconds < 0`;
2184
+ absSeconds = (0, ts_poet_1.code) `message.seconds < 0 ? -message.seconds : message.seconds`;
2185
+ break;
2186
+ }
2134
2187
  return (0, ts_poet_1.code) `
2135
2188
  toJSON(message: ${fullName}): string {
2136
- const secs = Number(message.seconds);
2137
- const nanos = message.nanos;
2138
- return \`\${secs + nanos/1e9}s\`;
2189
+ const negative = ${isNegSeconds} || message.nanos < 0;
2190
+ const sign = negative ? "-" : "";
2191
+ const absSeconds = ${absSeconds};
2192
+ const absNanos = message.nanos < 0 ? -message.nanos : message.nanos;
2193
+ if (absNanos === 0) return \`\${sign}\${absSeconds}s\`;
2194
+ const padded = absNanos.toString().padStart(9, "0");
2195
+ const len = absNanos % 1_000_000 === 0 ? 3 : absNanos % 1_000 === 0 ? 6 : 9;
2196
+ return \`\${sign}\${absSeconds}.\${padded.slice(0, len)}s\`;
2139
2197
  }
2140
2198
  `;
2141
2199
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "2.11.6",
3
+ "version": "2.11.8",
4
4
  "description": "",
5
5
  "main": "build/src/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",