ts-proto 1.165.3 → 1.166.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
@@ -899,12 +899,14 @@ ExampleMessage.encode({ anything: true });
899
899
  The representation of `google.protobuf.Timestamp` is configurable by the `useDate` flag.
900
900
  The `useJsonTimestamp` flag controls precision when `useDate` is `false`.
901
901
 
902
- | Protobuf well-known type | Default/`useDate=true` | `useDate=false` | `useDate=string` |
903
- | --------------------------- | ---------------------- | ------------------------------------ | ---------------- |
904
- | `google.protobuf.Timestamp` | `Date` | `{ seconds: number, nanos: number }` | `string` |
902
+ | Protobuf well-known type | Default/`useDate=true` | `useDate=false` | `useDate=string` | `useDate=string-nano` |
903
+ | --------------------------- | ---------------------- | ------------------------------------ | ---------------- | --------------------- |
904
+ | `google.protobuf.Timestamp` | `Date` | `{ seconds: number, nanos: number }` | `string` | `string` |
905
905
 
906
906
  When using `useDate=false` and `useJsonTimestamp=raw` timestamp is represented as `{ seconds: number, nanos: number }`, but has nanosecond precision.
907
907
 
908
+ When using `useDate=string-nano` timestamp is represented as an ISO string with nanosecond precision `1970-01-01T14:27:59.987654321Z` and relies on [nano-date](https://www.npmjs.com/package/nano-date) library for conversion. You'll need to install it in your project.
909
+
908
910
  # Number Types
909
911
 
910
912
  Numbers are by default assumed to be plain JavaScript `number`s.
package/build/encode.js CHANGED
@@ -13,7 +13,9 @@ function generateEncoder(ctx, typeName) {
13
13
  if (name == "Timestamp") {
14
14
  const TimestampValue = (0, utils_1.impProto)(ctx.options, "google/protobuf/timestamp", name);
15
15
  let value = (0, ts_poet_1.code) `value`;
16
- if (ctx.options.useDate === options_1.DateOption.DATE || ctx.options.useDate === options_1.DateOption.STRING) {
16
+ if (ctx.options.useDate === options_1.DateOption.DATE ||
17
+ ctx.options.useDate === options_1.DateOption.STRING ||
18
+ ctx.options.useDate === options_1.DateOption.STRING_NANO) {
17
19
  value = (0, ts_poet_1.code) `${ctx.utils.toTimestamp}(${value})`;
18
20
  }
19
21
  return (0, ts_poet_1.code) `${TimestampValue}.encode(${value}).finish()`;
@@ -59,7 +61,9 @@ function generateDecoder(ctx, typeName) {
59
61
  if (name == "Timestamp") {
60
62
  TypeValue = (0, utils_1.impProto)(ctx.options, "google/protobuf/timestamp", name);
61
63
  const decoder = (0, ts_poet_1.code) `${TypeValue}.decode(value)`;
62
- if (ctx.options.useDate === options_1.DateOption.DATE || ctx.options.useDate === options_1.DateOption.STRING) {
64
+ if (ctx.options.useDate === options_1.DateOption.DATE ||
65
+ ctx.options.useDate === options_1.DateOption.STRING ||
66
+ ctx.options.useDate === options_1.DateOption.STRING_NANO) {
63
67
  return (0, ts_poet_1.code) `${ctx.utils.fromTimestamp}(${decoder})`;
64
68
  }
65
69
  return decoder;
package/build/main.js CHANGED
@@ -462,23 +462,21 @@ function makeObjectIdMethods() {
462
462
  }
463
463
  function makeTimestampMethods(options, longs, bytes) {
464
464
  const Timestamp = (0, utils_1.impProto)(options, "google/protobuf/timestamp", "Timestamp");
465
- let seconds = "date.getTime() / 1_000";
465
+ const NanoDate = (0, ts_poet_1.imp)("NanoDate=nano-date");
466
+ let seconds = "Math.trunc(date.getTime() / 1_000)";
466
467
  let toNumberCode = "t.seconds";
467
468
  const makeToNumberCode = (methodCall) => `t.seconds${options.useOptionals === "all" ? "?" : ""}.${methodCall}`;
468
469
  if (options.forceLong === options_1.LongOption.LONG) {
469
470
  toNumberCode = makeToNumberCode("toNumber()");
470
- seconds = (0, ts_poet_1.code) `${longs.numberToLong}(date.getTime() / 1_000)`;
471
+ seconds = (0, ts_poet_1.code) `${longs.numberToLong}(${seconds})`;
471
472
  }
472
473
  else if (options.forceLong === options_1.LongOption.BIGINT) {
473
474
  toNumberCode = (0, ts_poet_1.code) `${bytes.globalThis}.Number(${makeToNumberCode("toString()")})`;
474
- seconds = (0, ts_poet_1.code) `BigInt(Math.trunc(date.getTime() / 1_000))`;
475
+ seconds = (0, ts_poet_1.code) `BigInt(${seconds})`;
475
476
  }
476
477
  else if (options.forceLong === options_1.LongOption.STRING) {
477
478
  toNumberCode = (0, ts_poet_1.code) `${bytes.globalThis}.Number(t.seconds)`;
478
- // Must discard the fractional piece here
479
- // Otherwise the fraction ends up on the seconds when parsed as a Long
480
- // (note this only occurs when the string is > 8 characters)
481
- seconds = "Math.trunc(date.getTime() / 1_000).toString()";
479
+ seconds = (0, ts_poet_1.code) `${seconds}.toString()`;
482
480
  }
483
481
  const maybeTypeField = (0, options_1.addTypeToMessages)(options) ? `$type: 'google.protobuf.Timestamp',` : "";
484
482
  const toTimestamp = (0, ts_poet_1.conditionalOutput)("toTimestamp", options.useDate === options_1.DateOption.STRING
@@ -490,7 +488,24 @@ function makeTimestampMethods(options, longs, bytes) {
490
488
  return { ${maybeTypeField} seconds, nanos };
491
489
  }
492
490
  `
493
- : (0, ts_poet_1.code) `
491
+ : options.useDate === options_1.DateOption.STRING_NANO
492
+ ? (0, ts_poet_1.code) `
493
+ function toTimestamp(dateStr: string): ${Timestamp} {
494
+ const nanoDate = new ${NanoDate}(dateStr);
495
+
496
+ const date = {
497
+ getTime: (): number => nanoDate.valueOf(),
498
+ } as const;
499
+ const seconds = ${seconds};
500
+
501
+ let nanos = nanoDate.getMilliseconds() * 1_000_000;
502
+ nanos += nanoDate.getMicroseconds() * 1_000;
503
+ nanos += nanoDate.getNanoseconds();
504
+
505
+ return { ${maybeTypeField} seconds, nanos };
506
+ }
507
+ `
508
+ : (0, ts_poet_1.code) `
494
509
  function toTimestamp(date: Date): ${Timestamp} {
495
510
  const seconds = ${seconds};
496
511
  const nanos = (date.getTime() % 1_000) * 1_000_000;
@@ -505,7 +520,23 @@ function makeTimestampMethods(options, longs, bytes) {
505
520
  return new ${bytes.globalThis}.Date(millis).toISOString();
506
521
  }
507
522
  `
508
- : (0, ts_poet_1.code) `
523
+ : options.useDate === options_1.DateOption.STRING_NANO
524
+ ? (0, ts_poet_1.code) `
525
+ function fromTimestamp(t: ${Timestamp}): string {
526
+ const seconds = ${toNumberCode} || 0;
527
+ const nanos = (t.nanos || 0) % 1_000;
528
+ const micros = Math.trunc(((t.nanos || 0) % 1_000_000) / 1_000)
529
+ let millis = seconds * 1_000;
530
+ millis += Math.trunc((t.nanos || 0) / 1_000_000);
531
+
532
+ const nanoDate = new ${NanoDate}(millis);
533
+ nanoDate.setMicroseconds(micros);
534
+ nanoDate.setNanoseconds(nanos);
535
+
536
+ return nanoDate.toISOStringFull();
537
+ }
538
+ `
539
+ : (0, ts_poet_1.code) `
509
540
  function fromTimestamp(t: ${Timestamp}): Date {
510
541
  let millis = (${toNumberCode} || 0) * 1_000;
511
542
  millis += (t.nanos || 0) / 1_000_000;
@@ -748,7 +779,10 @@ function getDecodeReadSnippet(ctx, field) {
748
779
  const decoder = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
749
780
  readSnippet = (0, ts_poet_1.code) `${unwrap(decoder)}`;
750
781
  }
751
- else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
782
+ else if ((0, types_1.isTimestamp)(field) &&
783
+ (options.useDate === options_1.DateOption.DATE ||
784
+ options.useDate === options_1.DateOption.STRING ||
785
+ options.useDate === options_1.DateOption.STRING_NANO)) {
752
786
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
753
787
  readSnippet = (0, ts_poet_1.code) `${utils.fromTimestamp}(${type}.decode(reader, reader.uint32()))`;
754
788
  }
@@ -977,7 +1011,10 @@ function getEncodeWriteSnippet(ctx, field) {
977
1011
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
978
1012
  return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toProtoObjectId}(${place}), writer.uint32(${tag}).fork()).ldelim()`;
979
1013
  }
980
- else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
1014
+ else if ((0, types_1.isTimestamp)(field) &&
1015
+ (options.useDate === options_1.DateOption.DATE ||
1016
+ options.useDate === options_1.DateOption.STRING ||
1017
+ options.useDate === options_1.DateOption.STRING_NANO)) {
981
1018
  const tag = ((field.number << 3) | 2) >>> 0;
982
1019
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
983
1020
  return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toTimestamp}(${place}), writer.uint32(${tag}).fork()).ldelim()`;
@@ -1316,7 +1353,10 @@ function generateExtension(ctx, message, extension) {
1316
1353
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1317
1354
  return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toProtoObjectId}(${place}), writer.fork()).ldelim()`;
1318
1355
  }
1319
- else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
1356
+ else if ((0, types_1.isTimestamp)(field) &&
1357
+ (options.useDate === options_1.DateOption.DATE ||
1358
+ options.useDate === options_1.DateOption.STRING ||
1359
+ options.useDate === options_1.DateOption.STRING_NANO)) {
1320
1360
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1321
1361
  return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toTimestamp}(${place}), writer.fork()).ldelim()`;
1322
1362
  }
@@ -1505,7 +1545,8 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1505
1545
  else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
1506
1546
  return (0, ts_poet_1.code) `${utils.fromJsonObjectId}(${from})`;
1507
1547
  }
1508
- else if ((0, types_1.isTimestamp)(field) && options.useDate === options_1.DateOption.STRING) {
1548
+ else if ((0, types_1.isTimestamp)(field) &&
1549
+ (options.useDate === options_1.DateOption.STRING || options.useDate === options_1.DateOption.STRING_NANO)) {
1509
1550
  return (0, ts_poet_1.code) `${utils.globalThis}.String(${from})`;
1510
1551
  }
1511
1552
  else if ((0, types_1.isTimestamp)(field) &&
@@ -1568,7 +1609,8 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1568
1609
  else if ((0, types_1.isObjectId)(valueField) && options.useMongoObjectId) {
1569
1610
  return (0, ts_poet_1.code) `${utils.fromJsonObjectId}(${from})`;
1570
1611
  }
1571
- else if ((0, types_1.isTimestamp)(valueField) && options.useDate === options_1.DateOption.STRING) {
1612
+ else if ((0, types_1.isTimestamp)(valueField) &&
1613
+ (options.useDate === options_1.DateOption.STRING || options.useDate === options_1.DateOption.STRING_NANO)) {
1572
1614
  return (0, ts_poet_1.code) `${utils.globalThis}.String(${from})`;
1573
1615
  }
1574
1616
  else if ((0, types_1.isTimestamp)(valueField) &&
@@ -1729,7 +1771,8 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1729
1771
  else if ((0, types_1.isTimestamp)(field) && options.useDate === options_1.DateOption.DATE) {
1730
1772
  return (0, ts_poet_1.code) `${from}.toISOString()`;
1731
1773
  }
1732
- else if ((0, types_1.isTimestamp)(field) && options.useDate === options_1.DateOption.STRING) {
1774
+ else if ((0, types_1.isTimestamp)(field) &&
1775
+ (options.useDate === options_1.DateOption.STRING || options.useDate === options_1.DateOption.STRING_NANO)) {
1733
1776
  return (0, ts_poet_1.code) `${from}`;
1734
1777
  }
1735
1778
  else if ((0, types_1.isTimestamp)(field) && options.useDate === options_1.DateOption.TIMESTAMP) {
@@ -1754,7 +1797,8 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1754
1797
  else if ((0, types_1.isTimestamp)(valueType) && options.useDate === options_1.DateOption.DATE) {
1755
1798
  return (0, ts_poet_1.code) `${from}.toISOString()`;
1756
1799
  }
1757
- else if ((0, types_1.isTimestamp)(valueType) && options.useDate === options_1.DateOption.STRING) {
1800
+ else if ((0, types_1.isTimestamp)(valueType) &&
1801
+ (options.useDate === options_1.DateOption.STRING || options.useDate === options_1.DateOption.STRING_NANO)) {
1758
1802
  return (0, ts_poet_1.code) `${from}`;
1759
1803
  }
1760
1804
  else if ((0, types_1.isTimestamp)(valueType) && options.useDate === options_1.DateOption.TIMESTAMP) {
@@ -1919,7 +1963,10 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1919
1963
  return (0, ts_poet_1.code) `${from} as mongodb.ObjectId`;
1920
1964
  }
1921
1965
  else if ((0, types_1.isPrimitive)(field) ||
1922
- ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) ||
1966
+ ((0, types_1.isTimestamp)(field) &&
1967
+ (options.useDate === options_1.DateOption.DATE ||
1968
+ options.useDate === options_1.DateOption.STRING ||
1969
+ options.useDate === options_1.DateOption.STRING_NANO)) ||
1923
1970
  (0, types_1.isValueType)(ctx, field)) {
1924
1971
  return (0, ts_poet_1.code) `${from}`;
1925
1972
  }
@@ -1951,7 +1998,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1951
1998
  return (0, ts_poet_1.code) `${from} as mongodb.ObjectId`;
1952
1999
  }
1953
2000
  else if ((0, types_1.isTimestamp)(valueField) &&
1954
- (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
2001
+ (options.useDate === options_1.DateOption.DATE ||
2002
+ options.useDate === options_1.DateOption.STRING ||
2003
+ options.useDate === options_1.DateOption.STRING_NANO)) {
1955
2004
  return (0, ts_poet_1.code) `${from}`;
1956
2005
  }
1957
2006
  else if ((0, types_1.isValueType)(ctx, valueField)) {
package/build/options.js CHANGED
@@ -12,6 +12,7 @@ var DateOption;
12
12
  (function (DateOption) {
13
13
  DateOption["DATE"] = "date";
14
14
  DateOption["STRING"] = "string";
15
+ DateOption["STRING_NANO"] = "string-nano";
15
16
  DateOption["TIMESTAMP"] = "timestamp";
16
17
  })(DateOption || (exports.DateOption = DateOption = {}));
17
18
  var JsonTimestampOption;
package/build/types.js CHANGED
@@ -554,7 +554,7 @@ function messageToTypeName(ctx, protoType, typeOptions = {}) {
554
554
  if (options.useDate == options_1.DateOption.DATE) {
555
555
  return (0, ts_poet_1.code) `Date`;
556
556
  }
557
- if (options.useDate == options_1.DateOption.STRING) {
557
+ if (options.useDate == options_1.DateOption.STRING || options.useDate == options_1.DateOption.STRING_NANO) {
558
558
  return (0, ts_poet_1.code) `string`;
559
559
  }
560
560
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.165.3",
3
+ "version": "1.166.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",
@@ -52,6 +52,7 @@
52
52
  "jest": "^29.6.1",
53
53
  "jest-ts-webcompat-resolver": "^1.0.0",
54
54
  "mongodb": "^5.7.0",
55
+ "nano-date": "^4.1.0",
55
56
  "nice-grpc": "^2.1.4",
56
57
  "object-hash": "^3.0.0",
57
58
  "prettier": "^2.8.8",