@nextera.one/tps-standard 0.5.3 → 0.5.34

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 (57) hide show
  1. package/dist/date.d.ts +54 -0
  2. package/dist/date.js +174 -0
  3. package/dist/date.js.map +1 -0
  4. package/dist/drivers/gregorian.d.ts +3 -5
  5. package/dist/drivers/gregorian.js +26 -19
  6. package/dist/drivers/gregorian.js.map +1 -1
  7. package/dist/drivers/hijri.d.ts +1 -16
  8. package/dist/drivers/hijri.js +9 -102
  9. package/dist/drivers/hijri.js.map +1 -1
  10. package/dist/drivers/holocene.d.ts +6 -3
  11. package/dist/drivers/holocene.js +7 -20
  12. package/dist/drivers/holocene.js.map +1 -1
  13. package/dist/drivers/julian.d.ts +3 -10
  14. package/dist/drivers/julian.js +11 -71
  15. package/dist/drivers/julian.js.map +1 -1
  16. package/dist/drivers/persian.d.ts +1 -6
  17. package/dist/drivers/persian.js +17 -92
  18. package/dist/drivers/persian.js.map +1 -1
  19. package/dist/drivers/tps.d.ts +11 -28
  20. package/dist/drivers/tps.js +8 -58
  21. package/dist/drivers/tps.js.map +1 -1
  22. package/dist/drivers/unix.d.ts +5 -6
  23. package/dist/drivers/unix.js +10 -32
  24. package/dist/drivers/unix.js.map +1 -1
  25. package/dist/index.d.ts +6 -477
  26. package/dist/index.js +33 -978
  27. package/dist/index.js.map +1 -1
  28. package/dist/types.d.ts +85 -0
  29. package/dist/types.js +30 -0
  30. package/dist/types.js.map +1 -0
  31. package/dist/uid.d.ts +48 -0
  32. package/dist/uid.js +225 -0
  33. package/dist/uid.js.map +1 -0
  34. package/dist/utils/calendar.d.ts +55 -0
  35. package/dist/utils/calendar.js +136 -0
  36. package/dist/utils/calendar.js.map +1 -0
  37. package/dist/utils/env.d.ts +12 -0
  38. package/dist/utils/env.js +79 -0
  39. package/dist/utils/env.js.map +1 -0
  40. package/dist/utils/tps-string.d.ts +12 -0
  41. package/dist/utils/tps-string.js +164 -0
  42. package/dist/utils/tps-string.js.map +1 -0
  43. package/package.json +1 -1
  44. package/src/date.ts +243 -0
  45. package/src/drivers/gregorian.ts +29 -27
  46. package/src/drivers/hijri.ts +13 -113
  47. package/src/drivers/holocene.ts +11 -12
  48. package/src/drivers/julian.ts +18 -72
  49. package/src/drivers/persian.ts +25 -92
  50. package/src/drivers/tps.ts +16 -55
  51. package/src/drivers/unix.ts +12 -33
  52. package/src/index.ts +18 -1446
  53. package/src/types.ts +107 -0
  54. package/src/uid.ts +308 -0
  55. package/src/utils/calendar.ts +161 -0
  56. package/src/utils/env.ts +88 -0
  57. package/src/utils/tps-string.ts +166 -0
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * TPS: Temporal Positioning System
4
4
  * The Universal Protocol for Space-Time Coordinates.
5
5
  * @packageDocumentation
6
- * @version 0.5.3
6
+ * @version 0.5.34
7
7
  * @license Apache-2.0
8
8
  * @copyright 2026 TPS Standards Working Group
9
9
  *
@@ -13,8 +13,22 @@
13
13
  * - Added structural anchors (bldg, floor, room, zone)
14
14
  * - Added geospatial cell systems (S2, H3, Plus Code, what3words)
15
15
  */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
28
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
29
+ };
16
30
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.TpsDate = exports.TPSUID7RB = exports.TPS = exports.TimeOrder = exports.DefaultCalendars = void 0;
31
+ exports.TPS = exports.Env = void 0;
18
32
  // built-in drivers are registered automatically; importing them here
19
33
  // ensures they are included when the library bundler/tree-shaker runs.
20
34
  const gregorian_1 = require("./drivers/gregorian");
@@ -24,28 +38,13 @@ const persian_1 = require("./drivers/persian");
24
38
  const hijri_1 = require("./drivers/hijri");
25
39
  const julian_1 = require("./drivers/julian");
26
40
  const holocene_1 = require("./drivers/holocene");
27
- // Calendar codes are plain strings to allow arbitrary user-defined
28
- // calendars. The library still exports constants for the built-in values but
29
- // callers may also supply their own codes.
30
- exports.DefaultCalendars = {
31
- TPS: "tps",
32
- GREG: "greg",
33
- HIJ: "hij",
34
- PER: "per",
35
- JUL: "jul",
36
- HOLO: "holo",
37
- UNIX: "unix",
38
- };
39
- /**
40
- * Specifies the direction of the time-component hierarchy when serializing or
41
- * deserializing a TPS string. The default is `'descending'` (millennium → … →
42
- * second), but `'ascending'` produces the reverse order.
43
- */
44
- var TimeOrder;
45
- (function (TimeOrder) {
46
- TimeOrder["DESC"] = "desc";
47
- TimeOrder["ASC"] = "asc";
48
- })(TimeOrder || (exports.TimeOrder = TimeOrder = {}));
41
+ __exportStar(require("./types"), exports);
42
+ __exportStar(require("./uid"), exports);
43
+ __exportStar(require("./date"), exports);
44
+ var env_1 = require("./utils/env");
45
+ Object.defineProperty(exports, "Env", { enumerable: true, get: function () { return env_1.Env; } });
46
+ const tps_string_1 = require("./utils/tps-string");
47
+ const types_1 = require("./types");
49
48
  class TPS {
50
49
  /**
51
50
  * Registers a calendar driver plugin.
@@ -208,7 +207,7 @@ class TPS {
208
207
  timeStr = timeStr.split(/[!;?#]/)[0];
209
208
  }
210
209
  if (timeStr) {
211
- const parsed = this.parseTimeString(timeStr);
210
+ const parsed = (0, tps_string_1.parseTimeString)(timeStr);
212
211
  if (!parsed)
213
212
  return null;
214
213
  Object.assign(comp, parsed.components);
@@ -231,7 +230,7 @@ class TPS {
231
230
  signature = sigMatch.groups.sig;
232
231
  timeOnly = input.split(/[!;?#]/)[0];
233
232
  }
234
- const parsed = this.parseTimeString(timeOnly);
233
+ const parsed = (0, tps_string_1.parseTimeString)(timeOnly);
235
234
  if (!parsed)
236
235
  return null;
237
236
  const comp = parsed.components;
@@ -293,7 +292,7 @@ class TPS {
293
292
  actorPart = `/A:${comp.actor}`;
294
293
  }
295
294
  // 3. Build Time Part (handles order & signature)
296
- const timePart = this.buildTimePart(comp);
295
+ const timePart = (0, tps_string_1.buildTimePart)(comp);
297
296
  // 5. Build Extensions
298
297
  let extPart = "";
299
298
  if (comp.extensions && Object.keys(comp.extensions).length > 0) {
@@ -314,7 +313,7 @@ class TPS {
314
313
  * supported key is `order` which may be `'ascending'` or `'descending'`.
315
314
  * @returns Canonical string (e.g., "T:tps.m3.c1.y26...").
316
315
  */
317
- static fromDate(date = new Date(), calendar = exports.DefaultCalendars.TPS, opts) {
316
+ static fromDate(date = new Date(), calendar = types_1.DefaultCalendars.TPS, opts) {
318
317
  const normalizedCalendar = calendar.toLowerCase();
319
318
  const driver = this.drivers.get(normalizedCalendar);
320
319
  if (driver) {
@@ -326,21 +325,21 @@ class TPS {
326
325
  const comp = driver.getComponentsFromDate(date);
327
326
  comp.calendar = normalizedCalendar;
328
327
  comp.order = opts.order;
329
- return this.buildTimePart(comp);
328
+ return (0, tps_string_1.buildTimePart)(comp);
330
329
  }
331
330
  return driver.getFromDate(date);
332
331
  }
333
332
  // Fallback for old built-in calendars (shouldn't happen once drivers are
334
333
  // registered, but kept for backwards compatibility).
335
334
  const comp = { calendar: normalizedCalendar };
336
- if (normalizedCalendar === exports.DefaultCalendars.UNIX) {
335
+ if (normalizedCalendar === types_1.DefaultCalendars.UNIX) {
337
336
  const s = (date.getTime() / 1000).toFixed(3);
338
337
  comp.unixSeconds = parseFloat(s);
339
338
  if (opts?.order)
340
339
  comp.order = opts.order;
341
- return this.buildTimePart(comp);
340
+ return (0, tps_string_1.buildTimePart)(comp);
342
341
  }
343
- if (normalizedCalendar === exports.DefaultCalendars.GREG) {
342
+ if (normalizedCalendar === types_1.DefaultCalendars.GREG) {
344
343
  const fullYear = date.getUTCFullYear();
345
344
  comp.millennium = Math.floor(fullYear / 1000) + 1;
346
345
  comp.century = Math.floor((fullYear % 1000) / 100) + 1;
@@ -353,7 +352,7 @@ class TPS {
353
352
  comp.millisecond = date.getUTCMilliseconds();
354
353
  if (opts?.order)
355
354
  comp.order = opts.order;
356
- return this.buildTimePart(comp);
355
+ return (0, tps_string_1.buildTimePart)(comp);
357
356
  }
358
357
  throw new Error(`Calendar driver '${normalizedCalendar}' not implemented. Register a driver.`);
359
358
  }
@@ -382,7 +381,7 @@ class TPS {
382
381
  const parsed = this.parse(tpsString);
383
382
  if (!parsed)
384
383
  return null;
385
- const cal = parsed.calendar || exports.DefaultCalendars.TPS;
384
+ const cal = parsed.calendar || types_1.DefaultCalendars.TPS;
386
385
  const driver = this.drivers.get(cal);
387
386
  if (!driver) {
388
387
  console.error(`Calendar driver '${cal}' not registered.`);
@@ -479,217 +478,6 @@ class TPS {
479
478
  return driver.format(components, format);
480
479
  }
481
480
  // --- INTERNAL HELPERS ---
482
- /**
483
- * Generate the canonical `T:` time string for a set of components. The
484
- * `order` field (or `comp.order`) controls whether tokens are emitted in
485
- * ascending or descending hierarchy; if undefined the default
486
- * `'descending'` orientation is used.
487
- *
488
- * Drivers may ignore this helper and produce their own time strings if they
489
- * implement custom ordering logic.
490
- */
491
- static buildTimePart(comp) {
492
- const calendar = (comp.calendar || "").toLowerCase();
493
- if (!/^[a-z]{3,4}$/.test(calendar)) {
494
- throw new Error(`Invalid calendar code '${comp.calendar}'. Calendar code width must be 3–4 lowercase letters.`);
495
- }
496
- let time = `T:${calendar}`;
497
- if (calendar === exports.DefaultCalendars.UNIX) {
498
- if (comp.unixSeconds !== undefined) {
499
- time += `.s${comp.unixSeconds}`;
500
- }
501
- return time;
502
- }
503
- // sequence of [prefix, value, rank]
504
- // All four of millennium / month / minute / millisecond share the prefix 'm'.
505
- // Position within the ordered sequence disambiguates them during parsing.
506
- const tokens = [
507
- ["m", comp.millennium, 8], // m-token rank 8 → millennium
508
- ["c", comp.century, 7],
509
- ["y", comp.year, 6],
510
- ["m", comp.month, 5], // m-token rank 5 → month
511
- ["d", comp.day, 4],
512
- ["h", comp.hour, 3],
513
- ["m", comp.minute, 2], // m-token rank 2 → minute
514
- ["s", comp.second, 1],
515
- ["m", comp.millisecond, 0], // m-token rank 0 → millisecond
516
- ];
517
- const order = comp.order || TimeOrder.DESC;
518
- if (order === TimeOrder.ASC)
519
- tokens.reverse();
520
- for (const [pref, val] of tokens) {
521
- if (val !== undefined) {
522
- // seconds may be fractional
523
- time += `.${pref}${val}`;
524
- }
525
- }
526
- if (comp.signature) {
527
- time += `!${comp.signature}`;
528
- }
529
- return time;
530
- }
531
- /**
532
- * Parse the *time* portion of a TPS string (optionally beginning with
533
- * `T:`) into components and determine the component ordering. This helper
534
- * accepts tokens in **any** sequence and will return an `order` value of
535
- * `'ascending'` or `'descending'`.
536
- *
537
- * The caller is responsible for stripping off a leading signature or other
538
- * trailer characters; this method will drop anything after `!`, `;`, `?` or
539
- * `#`.
540
- *
541
- * ### `m`-token disambiguation
542
- * All four of millennium (rank 8), month (rank 5), minute (rank 2) and
543
- * millisecond (rank 0) share the single-character prefix `m`. They are told
544
- * apart by their **position relative to the neighbouring tokens**. The
545
- * algorithm is:
546
- *
547
- * 1. Pre-scan the non-`m` tokens (c, y, d, h, s) whose ranks are fixed to
548
- * determine whether the string is ascending or descending.
549
- * 2. While iterating, track `lastAssignedRank` – the rank of the most
550
- * recently processed token (m or non-m).
551
- * 3. When an `m` token is encountered, derive its rank from `lastAssignedRank`
552
- * and the detected order:
553
- * - **DESC** null → 8 (mill) | rank > 5 → 5 (month) | rank > 2 → 2 (min) | else → 0 (ms)
554
- * - **ASC** null → 0 (ms) | rank < 2 → 2 (min) | rank < 5 → 5 (month) | else → 8 (mill)
555
- *
556
- * @param input - Time fragment (e.g. `"T:greg.m3.c1.y26"` or `"greg.m0.s25.m30"`)
557
- */
558
- static parseTimeString(input) {
559
- let s = input.trim();
560
- // strip off anything after signature or extensions/query/fragment
561
- s = s.split(/[!;?#]/)[0];
562
- if (s.startsWith("T:"))
563
- s = s.slice(2);
564
- const parts = s.split(".");
565
- if (parts.length === 0)
566
- return null;
567
- const calendar = parts[0];
568
- const comp = { calendar };
569
- // Fixed-rank prefixes (unambiguous regardless of position)
570
- const fixedRankMap = {
571
- c: 7,
572
- y: 6,
573
- d: 4,
574
- h: 3,
575
- s: 1,
576
- };
577
- // ── Step 1: pre-scan non-m tokens to estimate order ─────────────────────
578
- // This is only needed to handle the first 'm' token when lastAssignedRank
579
- // is still null (nothing has been seen yet).
580
- let initialOrder = TimeOrder.DESC;
581
- if (calendar !== exports.DefaultCalendars.UNIX) {
582
- const nonMRanks = [];
583
- for (let i = 1; i < parts.length; i++) {
584
- const pr = parts[i]?.charAt(0);
585
- if (pr && pr in fixedRankMap)
586
- nonMRanks.push(fixedRankMap[pr]);
587
- }
588
- if (nonMRanks.length >= 2) {
589
- const isAsc = nonMRanks.every((v, i, a) => i === 0 || a[i - 1] <= v);
590
- if (isAsc)
591
- initialOrder = TimeOrder.ASC;
592
- }
593
- }
594
- // ── Step 2: resolve the semantic rank of an 'm' token ───────────────────
595
- const assignMRank = (lastRank, ord) => {
596
- if (ord === TimeOrder.DESC) {
597
- if (lastRank === null)
598
- return 8; // first token → millennium
599
- if (lastRank > 5)
600
- return 5; // after century / year → month
601
- if (lastRank > 2)
602
- return 2; // after day / hour → minute
603
- return 0; // after second → millisecond
604
- }
605
- else {
606
- if (lastRank === null)
607
- return 0; // first token → millisecond
608
- if (lastRank < 2)
609
- return 2; // after millisecond / second → minute
610
- if (lastRank < 5)
611
- return 5; // after minute / hour / day → month
612
- return 8; // after month / year / cent → millennium
613
- }
614
- };
615
- // ── Step 3: iterate and build components ────────────────────────────────
616
- const ranks = [];
617
- let lastAssignedRank = null;
618
- for (let i = 1; i < parts.length; i++) {
619
- const token = parts[i];
620
- if (!token)
621
- continue;
622
- const prefix = token.charAt(0);
623
- const value = token.slice(1);
624
- // UNIX calendar: single 's' token carries the full unix timestamp
625
- if (calendar === exports.DefaultCalendars.UNIX && prefix === "s") {
626
- comp.unixSeconds = parseFloat(value);
627
- ranks.push(9);
628
- continue;
629
- }
630
- if (prefix === "m") {
631
- const rank = assignMRank(lastAssignedRank, initialOrder);
632
- switch (rank) {
633
- case 8:
634
- comp.millennium = parseInt(value, 10);
635
- break;
636
- case 5:
637
- comp.month = parseInt(value, 10);
638
- break;
639
- case 2:
640
- comp.minute = parseInt(value, 10);
641
- break;
642
- case 0:
643
- comp.millisecond = parseInt(value, 10);
644
- break;
645
- }
646
- ranks.push(rank);
647
- lastAssignedRank = rank;
648
- }
649
- else {
650
- switch (prefix) {
651
- case "c":
652
- comp.century = parseInt(value, 10);
653
- ranks.push(7);
654
- lastAssignedRank = 7;
655
- break;
656
- case "y":
657
- comp.year = parseInt(value, 10);
658
- ranks.push(6);
659
- lastAssignedRank = 6;
660
- break;
661
- case "d":
662
- comp.day = parseInt(value, 10);
663
- ranks.push(4);
664
- lastAssignedRank = 4;
665
- break;
666
- case "h":
667
- comp.hour = parseInt(value, 10);
668
- ranks.push(3);
669
- lastAssignedRank = 3;
670
- break;
671
- case "s":
672
- comp.second = parseFloat(value);
673
- ranks.push(1);
674
- lastAssignedRank = 1;
675
- break;
676
- default:
677
- // unknown prefix – ignore
678
- break;
679
- }
680
- }
681
- }
682
- // ── Step 4: confirm order from the complete rank sequence ────────────────
683
- let order = TimeOrder.DESC;
684
- if (ranks.length > 1) {
685
- const isAsc = ranks.every((v, i, a) => i === 0 || a[i - 1] <= v);
686
- const isDesc = ranks.every((v, i, a) => i === 0 || a[i - 1] >= v);
687
- if (isAsc && !isDesc)
688
- order = TimeOrder.ASC;
689
- // mixed / single direction → defaults to DESC
690
- }
691
- return { components: comp, order };
692
- }
693
481
  static _mapGroupsToComponents(g) {
694
482
  const components = {};
695
483
  components.calendar = g.calendar;
@@ -815,582 +603,6 @@ TPS.registerDriver(new persian_1.PersianDriver());
815
603
  TPS.registerDriver(new hijri_1.HijriDriver());
816
604
  TPS.registerDriver(new julian_1.JulianDriver());
817
605
  TPS.registerDriver(new holocene_1.HoloceneDriver());
818
- /**
819
- * TPS-UID v1 — Temporal Positioning System Identifier (Binary Reversible)
820
- *
821
- * A time-first, reversible identifier that binds an event to a TPS coordinate.
822
- * Unlike UUIDs, TPS-UID identifies events in spacetime and allows exact
823
- * reconstruction of the original TPS string.
824
- *
825
- * Binary Schema (all integers big-endian):
826
- * ```
827
- * MAGIC 4 bytes "TPU7"
828
- * VER 1 byte 0x01
829
- * FLAGS 1 byte bit0 = compression flag
830
- * TIME 6 bytes epoch_ms (48-bit unsigned)
831
- * NONCE 4 bytes 32-bit random
832
- * LEN varint length of TPS payload
833
- * TPS bytes UTF-8 TPS string (raw or zlib-compressed)
834
- * ```
835
- *
836
- * @example
837
- * ```ts
838
- * const tps = 'tps://31.95,35.91@T:greg.m3.c1.y26.m01.d09';
839
- *
840
- * // Encode to binary
841
- * const bytes = TPSUID7RB.encodeBinary(tps);
842
- *
843
- * // Encode to base64url string
844
- * const id = TPSUID7RB.encodeBinaryB64(tps);
845
- * // → "tpsuid7rb_AFRQV..."
846
- *
847
- * // Decode back to original TPS
848
- * const decoded = TPSUID7RB.decodeBinaryB64(id);
849
- * console.log(decoded.tps); // exact original TPS
850
- * ```
851
- */
852
- class TPSUID7RB {
853
- // ---------------------------
854
- // Public API
855
- // ---------------------------
856
- /**
857
- * Encode TPS string to binary bytes (Uint8Array).
858
- * This is the canonical form for hashing, signing, and storage.
859
- *
860
- * @param tps - The TPS string to encode
861
- * @param opts - Encoding options (compress, epochMs override)
862
- * @returns Binary TPS-UID as Uint8Array
863
- */
864
- static encodeBinary(tps, opts = {}) {
865
- const compress = opts.compress ?? false;
866
- const epochMs = opts.epochMs ?? this.epochMsFromTPSString(tps);
867
- if (!Number.isInteger(epochMs) || epochMs < 0) {
868
- throw new Error("epochMs must be a non-negative integer");
869
- }
870
- if (epochMs > 0xffffffffffff) {
871
- throw new Error("epochMs exceeds 48-bit range");
872
- }
873
- const flags = compress ? 0x01 : 0x00;
874
- // Generate 32-bit nonce
875
- const nonceBuf = this.randomBytes(4);
876
- const nonce = ((nonceBuf[0] << 24) >>> 0) +
877
- ((nonceBuf[1] << 16) >>> 0) +
878
- ((nonceBuf[2] << 8) >>> 0) +
879
- nonceBuf[3];
880
- // Encode TPS to UTF-8
881
- const tpsUtf8 = new TextEncoder().encode(tps);
882
- // Optionally compress
883
- const payload = compress ? this.deflateRaw(tpsUtf8) : tpsUtf8;
884
- // Encode length as varint
885
- const lenVar = this.uvarintEncode(payload.length);
886
- // Construct binary structure
887
- const out = new Uint8Array(4 + 1 + 1 + 6 + 4 + lenVar.length + payload.length);
888
- let offset = 0;
889
- // MAGIC
890
- out.set(this.MAGIC, offset);
891
- offset += 4;
892
- // VER
893
- out[offset++] = this.VER;
894
- // FLAGS
895
- out[offset++] = flags;
896
- // TIME (48-bit big-endian)
897
- const timeBytes = this.writeU48(epochMs);
898
- out.set(timeBytes, offset);
899
- offset += 6;
900
- // NONCE (32-bit big-endian)
901
- out.set(nonceBuf, offset);
902
- offset += 4;
903
- // LEN (varint)
904
- out.set(lenVar, offset);
905
- offset += lenVar.length;
906
- // TPS payload
907
- out.set(payload, offset);
908
- return out;
909
- }
910
- /**
911
- * Decode binary bytes back to original TPS string.
912
- *
913
- * @param bytes - Binary TPS-UID
914
- * @returns Decoded result with original TPS string
915
- */
916
- static decodeBinary(bytes) {
917
- // Header min size: 4+1+1+6+4 + 1 (at least 1 byte varint) = 17
918
- if (bytes.length < 17) {
919
- throw new Error("TPSUID7RB: too short");
920
- }
921
- // MAGIC
922
- if (bytes[0] !== 0x54 ||
923
- bytes[1] !== 0x50 ||
924
- bytes[2] !== 0x55 ||
925
- bytes[3] !== 0x37) {
926
- throw new Error("TPSUID7RB: bad magic");
927
- }
928
- // VERSION
929
- const ver = bytes[4];
930
- if (ver !== this.VER) {
931
- throw new Error(`TPSUID7RB: unsupported version ${ver}`);
932
- }
933
- // FLAGS
934
- const flags = bytes[5];
935
- const compressed = (flags & 0x01) === 0x01;
936
- // TIME (48-bit big-endian)
937
- const epochMs = this.readU48(bytes, 6);
938
- // NONCE (32-bit big-endian)
939
- const nonce = ((bytes[12] << 24) >>> 0) +
940
- ((bytes[13] << 16) >>> 0) +
941
- ((bytes[14] << 8) >>> 0) +
942
- bytes[15];
943
- // LEN (varint at offset 16)
944
- let offset = 16;
945
- const { value: tpsLen, bytesRead } = this.uvarintDecode(bytes, offset);
946
- offset += bytesRead;
947
- if (offset + tpsLen > bytes.length) {
948
- throw new Error("TPSUID7RB: length overflow");
949
- }
950
- // TPS payload
951
- const payload = bytes.slice(offset, offset + tpsLen);
952
- const tpsUtf8 = compressed ? this.inflateRaw(payload) : payload;
953
- const tps = new TextDecoder().decode(tpsUtf8);
954
- return { version: "tpsuid7rb", epochMs, compressed, nonce, tps };
955
- }
956
- /**
957
- * Encode TPS to base64url string with prefix.
958
- * This is the transport/storage form.
959
- *
960
- * @param tps - The TPS string to encode
961
- * @param opts - Encoding options
962
- * @returns Base64url encoded TPS-UID with prefix
963
- */
964
- static encodeBinaryB64(tps, opts) {
965
- const bytes = this.encodeBinary(tps, opts ?? {});
966
- return `${this.PREFIX}${this.base64UrlEncode(bytes)}`;
967
- }
968
- /**
969
- * Decode base64url string back to original TPS string.
970
- *
971
- * @param id - Base64url encoded TPS-UID with prefix
972
- * @returns Decoded result with original TPS string
973
- */
974
- static decodeBinaryB64(id) {
975
- const s = id.trim();
976
- if (!s.startsWith(this.PREFIX)) {
977
- throw new Error("TPSUID7RB: missing prefix");
978
- }
979
- const b64 = s.slice(this.PREFIX.length);
980
- const bytes = this.base64UrlDecode(b64);
981
- return this.decodeBinary(bytes);
982
- }
983
- /**
984
- * Validate base64url encoded TPS-UID format.
985
- * Note: This validates shape only; binary decode is authoritative.
986
- *
987
- * @param id - String to validate
988
- * @returns true if format is valid
989
- */
990
- static validateBinaryB64(id) {
991
- return this.REGEX.test(id.trim());
992
- }
993
- /**
994
- * Generate a TPS-UID from the current time and optional location.
995
- *
996
- * @param opts - Generation options
997
- * @returns Base64url encoded TPS-UID
998
- */
999
- static generate(opts) {
1000
- const now = new Date();
1001
- const time = TPS.fromDate(now, exports.DefaultCalendars.TPS, {
1002
- order: opts?.order,
1003
- });
1004
- let space = "unknown";
1005
- if (opts?.latitude !== undefined && opts?.longitude !== undefined) {
1006
- space = `${opts.latitude},${opts.longitude}`;
1007
- if (opts.altitude !== undefined) {
1008
- space += `,${opts.altitude}m`;
1009
- }
1010
- }
1011
- const tps = `tps://${space}@${time}`;
1012
- return this.encodeBinaryB64(tps, {
1013
- compress: opts?.compress,
1014
- epochMs: now.getTime(),
1015
- });
1016
- }
1017
- // ---------------------------
1018
- // TPS String Helpers
1019
- // ---------------------------
1020
- /**
1021
- * Generate a TPS string from a Date and optional location.
1022
- */
1023
- /**
1024
- * Parse epoch milliseconds from a TPS string.
1025
- * Supports both URI format (tps://...) and time-only format (T:greg...)
1026
- */
1027
- static epochMsFromTPSString(tps) {
1028
- const date = TPS.toDate(tps);
1029
- if (date)
1030
- return date.getTime();
1031
- // If parse fails due to unsupported/extended extension payloads,
1032
- // strip extensions/query/fragment and retry. Epoch only depends on time.
1033
- const stripped = tps.replace(/;[^?#]*/, "").replace(/[?#].*$/, "");
1034
- const retryDate = TPS.toDate(stripped);
1035
- if (!retryDate)
1036
- throw new Error("TPS: unable to parse date for epoch");
1037
- return retryDate.getTime();
1038
- }
1039
- // ---------------------------
1040
- // Binary Helpers
1041
- // ---------------------------
1042
- /** Write 48-bit unsigned integer (big-endian) */
1043
- static writeU48(epochMs) {
1044
- const b = new Uint8Array(6);
1045
- // Use BigInt for proper 48-bit handling
1046
- const v = BigInt(epochMs);
1047
- b[0] = Number((v >> 40n) & 0xffn);
1048
- b[1] = Number((v >> 32n) & 0xffn);
1049
- b[2] = Number((v >> 24n) & 0xffn);
1050
- b[3] = Number((v >> 16n) & 0xffn);
1051
- b[4] = Number((v >> 8n) & 0xffn);
1052
- b[5] = Number(v & 0xffn);
1053
- return b;
1054
- }
1055
- /** Read 48-bit unsigned integer (big-endian) */
1056
- static readU48(bytes, offset) {
1057
- const v = (BigInt(bytes[offset]) << 40n) +
1058
- (BigInt(bytes[offset + 1]) << 32n) +
1059
- (BigInt(bytes[offset + 2]) << 24n) +
1060
- (BigInt(bytes[offset + 3]) << 16n) +
1061
- (BigInt(bytes[offset + 4]) << 8n) +
1062
- BigInt(bytes[offset + 5]);
1063
- const n = Number(v);
1064
- if (!Number.isSafeInteger(n)) {
1065
- throw new Error("TPSUID7RB: u48 not safe integer");
1066
- }
1067
- return n;
1068
- }
1069
- /** Encode unsigned integer as LEB128 varint */
1070
- static uvarintEncode(n) {
1071
- if (!Number.isInteger(n) || n < 0) {
1072
- throw new Error("uvarint must be non-negative int");
1073
- }
1074
- const out = [];
1075
- let x = n >>> 0;
1076
- while (x >= 0x80) {
1077
- out.push((x & 0x7f) | 0x80);
1078
- x >>>= 7;
1079
- }
1080
- out.push(x);
1081
- return new Uint8Array(out);
1082
- }
1083
- /** Decode LEB128 varint */
1084
- static uvarintDecode(bytes, offset) {
1085
- let x = 0;
1086
- let s = 0;
1087
- let i = 0;
1088
- while (true) {
1089
- if (offset + i >= bytes.length) {
1090
- throw new Error("uvarint overflow");
1091
- }
1092
- const b = bytes[offset + i];
1093
- if (b < 0x80) {
1094
- if (i > 9 || (i === 9 && b > 1)) {
1095
- throw new Error("uvarint too large");
1096
- }
1097
- x |= b << s;
1098
- return { value: x >>> 0, bytesRead: i + 1 };
1099
- }
1100
- x |= (b & 0x7f) << s;
1101
- s += 7;
1102
- i++;
1103
- if (i > 10) {
1104
- throw new Error("uvarint too long");
1105
- }
1106
- }
1107
- }
1108
- // ---------------------------
1109
- // Base64url Helpers
1110
- // ---------------------------
1111
- /** Encode bytes to base64url (no padding) */
1112
- static base64UrlEncode(bytes) {
1113
- // Node.js environment
1114
- if (typeof Buffer !== "undefined") {
1115
- return Buffer.from(bytes)
1116
- .toString("base64")
1117
- .replace(/\+/g, "-")
1118
- .replace(/\//g, "_")
1119
- .replace(/=+$/g, "");
1120
- }
1121
- // Browser environment
1122
- let binary = "";
1123
- for (let i = 0; i < bytes.length; i++) {
1124
- binary += String.fromCharCode(bytes[i]);
1125
- }
1126
- return btoa(binary)
1127
- .replace(/\+/g, "-")
1128
- .replace(/\//g, "_")
1129
- .replace(/=+$/g, "");
1130
- }
1131
- /** Decode base64url to bytes */
1132
- static base64UrlDecode(b64url) {
1133
- // Add padding
1134
- const padLen = (4 - (b64url.length % 4)) % 4;
1135
- const b64 = (b64url + "=".repeat(padLen))
1136
- .replace(/-/g, "+")
1137
- .replace(/_/g, "/");
1138
- // Node.js environment
1139
- if (typeof Buffer !== "undefined") {
1140
- return new Uint8Array(Buffer.from(b64, "base64"));
1141
- }
1142
- // Browser environment
1143
- const binary = atob(b64);
1144
- const bytes = new Uint8Array(binary.length);
1145
- for (let i = 0; i < binary.length; i++) {
1146
- bytes[i] = binary.charCodeAt(i);
1147
- }
1148
- return bytes;
1149
- }
1150
- // ---------------------------
1151
- // Compression Helpers
1152
- // ---------------------------
1153
- /** Compress using zlib deflate raw */
1154
- static deflateRaw(data) {
1155
- // Node.js environment
1156
- if (typeof require !== "undefined") {
1157
- try {
1158
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1159
- const zlib = require("zlib");
1160
- return new Uint8Array(zlib.deflateRawSync(Buffer.from(data)));
1161
- }
1162
- catch {
1163
- throw new Error("TPSUID7RB: compression not available");
1164
- }
1165
- }
1166
- // Browser: would need pako or similar library
1167
- throw new Error("TPSUID7RB: compression not available in browser");
1168
- }
1169
- /** Decompress using zlib inflate raw */
1170
- static inflateRaw(data) {
1171
- // Node.js environment
1172
- if (typeof require !== "undefined") {
1173
- try {
1174
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1175
- const zlib = require("zlib");
1176
- return new Uint8Array(zlib.inflateRawSync(Buffer.from(data)));
1177
- }
1178
- catch {
1179
- throw new Error("TPSUID7RB: decompression failed");
1180
- }
1181
- }
1182
- // Browser: would need pako or similar library
1183
- throw new Error("TPSUID7RB: decompression not available in browser");
1184
- }
1185
- // ---------------------------
1186
- // Cryptographic Sealing (Ed25519)
1187
- // ---------------------------
1188
- /**
1189
- * Seal (sign) a TPS string to create a cryptographically verifiable TPS-UID.
1190
- * This appends an Ed25519 signature to the binary form.
1191
- *
1192
- * @param tps - The TPS string to seal
1193
- * @param privateKey - Ed25519 private key (hex or buffer)
1194
- * @param opts - Encoding options
1195
- * @returns Sealed binary TPS-UID
1196
- */
1197
- static seal(tps, privateKey, opts) {
1198
- // 1. Create standard binary (unsealed first)
1199
- // We force the SEAL flag (bit 1) to be 0 initially for the "content to sign"
1200
- // But wait, we want the signature to cover the header too.
1201
- // Strategy: Construct the full binary with SEAL flag OFF, sign it, then set SEAL flag ON and append sig.
1202
- // Actually, the standard way is:
1203
- // Content = MAGIC + VER + FLAGS(with seal bit set) + TIME + NONCE + LEN + PAYLOAD
1204
- // Signature = Sign(Content)
1205
- // Final = Content + SEAL_TYPE + SIGNATURE
1206
- const compress = opts?.compress ?? false;
1207
- const epochMs = opts?.epochMs ?? this.epochMsFromTPSString(tps);
1208
- // Validate epoch
1209
- if (!Number.isInteger(epochMs) || epochMs < 0 || epochMs > 0xffffffffffff) {
1210
- throw new Error("epochMs must be a valid 48-bit non-negative integer");
1211
- }
1212
- // Flags: Bit 0 = compress, Bit 1 = sealed
1213
- const flags = (compress ? 0x01 : 0x00) | 0x02; // Set SEAL bit
1214
- // Generate Nonce
1215
- const nonceBuf = this.randomBytes(4);
1216
- // Encode Payload
1217
- const tpsUtf8 = new TextEncoder().encode(tps);
1218
- const payload = compress ? this.deflateRaw(tpsUtf8) : tpsUtf8;
1219
- const lenVar = this.uvarintEncode(payload.length);
1220
- // Construct Content (Header + Payload)
1221
- const contentLen = 4 + 1 + 1 + 6 + 4 + lenVar.length + payload.length;
1222
- const content = new Uint8Array(contentLen);
1223
- let offset = 0;
1224
- content.set(this.MAGIC, offset);
1225
- offset += 4;
1226
- content[offset++] = this.VER;
1227
- content[offset++] = flags;
1228
- content.set(this.writeU48(epochMs), offset);
1229
- offset += 6;
1230
- content.set(nonceBuf, offset);
1231
- offset += 4;
1232
- content.set(lenVar, offset);
1233
- offset += lenVar.length;
1234
- content.set(payload, offset);
1235
- // Sign the content
1236
- const signature = this.signEd25519(content, privateKey);
1237
- const sealType = 0x01; // Ed25519
1238
- // Final Output: Content + SealType (1) + Signature (64)
1239
- const final = new Uint8Array(contentLen + 1 + signature.length);
1240
- final.set(content, 0);
1241
- final.set([sealType], contentLen);
1242
- final.set(signature, contentLen + 1);
1243
- return final;
1244
- }
1245
- /**
1246
- * Verify a sealed TPS-UID and decode it.
1247
- * Throws if signature is invalid or not sealed.
1248
- *
1249
- * @param sealedBytes - The binary sealed TPS-UID
1250
- * @param publicKey - Ed25519 public key (hex or buffer) to verify against
1251
- * @returns Decoded result
1252
- */
1253
- static verifyAndDecode(sealedBytes, publicKey) {
1254
- if (sealedBytes.length < 18)
1255
- throw new Error("TPSUID7RB: too short");
1256
- // Check Magic
1257
- if (sealedBytes[0] !== 0x54 ||
1258
- sealedBytes[1] !== 0x50 ||
1259
- sealedBytes[2] !== 0x55 ||
1260
- sealedBytes[3] !== 0x37) {
1261
- throw new Error("TPSUID7RB: bad magic");
1262
- }
1263
- // Check Flags for Sealed Bit (bit 1)
1264
- const flags = sealedBytes[5];
1265
- if ((flags & 0x02) === 0) {
1266
- throw new Error("TPSUID7RB: not a sealed UID");
1267
- }
1268
- // 1. Parse the structure to find where content ends
1269
- // We need to parse LEN and Payload to find the split point
1270
- let offset = 16; // Start of LEN
1271
- // Decode LEN
1272
- const { value: tpsLen, bytesRead } = this.uvarintDecode(sealedBytes, offset);
1273
- offset += bytesRead;
1274
- const payloadEnd = offset + tpsLen;
1275
- if (payloadEnd > sealedBytes.length) {
1276
- throw new Error("TPSUID7RB: length overflow (truncated)");
1277
- }
1278
- // The Content to verify matches exactly [0 ... payloadEnd]
1279
- const content = sealedBytes.slice(0, payloadEnd);
1280
- // After content: SealType (1 byte) + Signature
1281
- if (sealedBytes.length <= payloadEnd + 1) {
1282
- throw new Error("TPSUID7RB: missing signature data");
1283
- }
1284
- const sealType = sealedBytes[payloadEnd];
1285
- if (sealType !== 0x01) {
1286
- throw new Error(`TPSUID7RB: unsupported seal type 0x${sealType.toString(16)}`);
1287
- }
1288
- const signature = sealedBytes.slice(payloadEnd + 1);
1289
- if (signature.length !== 64) {
1290
- throw new Error(`TPSUID7RB: invalid Ed25519 signature length ${signature.length}`);
1291
- }
1292
- // Verify
1293
- const isValid = this.verifyEd25519(content, signature, publicKey);
1294
- if (!isValid) {
1295
- throw new Error("TPSUID7RB: signature verification failed");
1296
- }
1297
- // Decode (reuse standard logic, but ignoring the extra bytes at end is fine?)
1298
- // Actually standard logic doesn't expect trailing bytes unless we tell it to.
1299
- // But since we verified, we can just slice the content and decode that as a strict binary
1300
- // EXCEPT standard decodeBinary checks strict length.
1301
- // So we manually decode the components here to be safe and efficient.
1302
- return this.decodeBinary(content); // Reuse strict decoder on the content part
1303
- }
1304
- // --- Crypto Implementation (Ed25519) ---
1305
- static signEd25519(data, privateKey) {
1306
- if (typeof require !== "undefined") {
1307
- try {
1308
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1309
- const crypto = require("crypto");
1310
- let key;
1311
- if (typeof privateKey === "string") {
1312
- if (privateKey.includes("PRIVATE KEY")) {
1313
- // PEM format — use directly
1314
- key = privateKey;
1315
- }
1316
- else {
1317
- // Hex-encoded DER/PKCS8
1318
- key = crypto.createPrivateKey({
1319
- key: Buffer.from(privateKey, "hex"),
1320
- format: "der",
1321
- type: "pkcs8",
1322
- });
1323
- }
1324
- }
1325
- else if (typeof privateKey === "object" &&
1326
- privateKey !== null &&
1327
- "asymmetricKeyType" in privateKey) {
1328
- // Node.js KeyObject (e.g. from crypto.generateKeyPairSync)
1329
- key = privateKey;
1330
- }
1331
- else {
1332
- // Buffer or Uint8Array — assume DER/PKCS8 encoded
1333
- key = crypto.createPrivateKey({
1334
- key: Buffer.from(privateKey),
1335
- format: "der",
1336
- type: "pkcs8",
1337
- });
1338
- }
1339
- return new Uint8Array(crypto.sign(null, data, key));
1340
- }
1341
- catch (e) {
1342
- throw new Error("TPSUID7RB: signing failed (check key format)");
1343
- }
1344
- }
1345
- throw new Error("TPSUID7RB: signing not available in browser");
1346
- }
1347
- static verifyEd25519(data, signature, publicKey) {
1348
- if (typeof require !== "undefined") {
1349
- try {
1350
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1351
- const crypto = require("crypto");
1352
- return crypto.verify(null, data, publicKey, signature);
1353
- }
1354
- catch {
1355
- return false;
1356
- }
1357
- }
1358
- throw new Error("TPSUID7RB: verification not available in browser");
1359
- }
1360
- // ---------------------------
1361
- // Random Bytes
1362
- // ---------------------------
1363
- /** Generate cryptographically secure random bytes */
1364
- static randomBytes(length) {
1365
- // Node.js environment
1366
- if (typeof require !== "undefined") {
1367
- try {
1368
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1369
- const crypto = require("crypto");
1370
- return new Uint8Array(crypto.randomBytes(length));
1371
- }
1372
- catch {
1373
- // Fallback to crypto.getRandomValues
1374
- }
1375
- }
1376
- // Browser or fallback
1377
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
1378
- const bytes = new Uint8Array(length);
1379
- crypto.getRandomValues(bytes);
1380
- return bytes;
1381
- }
1382
- throw new Error("TPSUID7RB: no crypto available");
1383
- }
1384
- }
1385
- exports.TPSUID7RB = TPSUID7RB;
1386
- /** Magic bytes: "TPU7" */
1387
- TPSUID7RB.MAGIC = new Uint8Array([0x54, 0x50, 0x55, 0x37]);
1388
- /** Version 1 */
1389
- TPSUID7RB.VER = 0x01;
1390
- /** String prefix for base64url encoded form */
1391
- TPSUID7RB.PREFIX = "tpsuid7rb_";
1392
- /** Regex for validating base64url encoded form */
1393
- TPSUID7RB.REGEX = /^tpsuid7rb_[A-Za-z0-9_-]+$/;
1394
606
  /**
1395
607
  * `TpsDate` is a Date-like wrapper with native TPS conversion helpers.
1396
608
  *
@@ -1401,161 +613,4 @@ TPSUID7RB.REGEX = /^tpsuid7rb_[A-Za-z0-9_-]+$/;
1401
613
  * - `new TpsDate(tpsString)`
1402
614
  * - `new TpsDate(year, monthIndex, day?, hour?, minute?, second?, ms?)`
1403
615
  */
1404
- class TpsDate {
1405
- getTpsComponents() {
1406
- const parsed = TPS.parse(this.toTPS(exports.DefaultCalendars.TPS));
1407
- if (!parsed) {
1408
- throw new Error("TpsDate: failed to derive TPS components");
1409
- }
1410
- return parsed;
1411
- }
1412
- getTpsFullYear() {
1413
- const comp = this.getTpsComponents();
1414
- return (comp.millennium - 1) * 1000 + (comp.century - 1) * 100 + comp.year;
1415
- }
1416
- constructor(...args) {
1417
- if (args.length === 0) {
1418
- this.internal = new Date();
1419
- return;
1420
- }
1421
- if (args.length === 1) {
1422
- const value = args[0];
1423
- if (value instanceof TpsDate) {
1424
- this.internal = new Date(value.getTime());
1425
- return;
1426
- }
1427
- if (value instanceof Date) {
1428
- this.internal = new Date(value.getTime());
1429
- return;
1430
- }
1431
- if (typeof value === "string" && TpsDate.looksLikeTPS(value)) {
1432
- const parsed = TPS.toDate(value);
1433
- if (!parsed) {
1434
- throw new RangeError(`Invalid TPS date string: ${value}`);
1435
- }
1436
- this.internal = parsed;
1437
- return;
1438
- }
1439
- this.internal = new Date(value);
1440
- return;
1441
- }
1442
- const [year, monthIndex, day, hours, minutes, seconds, ms] = args;
1443
- this.internal = new Date(year, monthIndex, day ?? 1, hours ?? 0, minutes ?? 0, seconds ?? 0, ms ?? 0);
1444
- }
1445
- static looksLikeTPS(input) {
1446
- const s = input.trim();
1447
- return s.startsWith("tps://") || s.startsWith("T:") || s.startsWith("t:");
1448
- }
1449
- static now() {
1450
- return Date.now();
1451
- }
1452
- static parse(input) {
1453
- if (this.looksLikeTPS(input)) {
1454
- const d = TPS.toDate(input);
1455
- return d ? d.getTime() : Number.NaN;
1456
- }
1457
- return Date.parse(input);
1458
- }
1459
- static UTC(year, monthIndex, day, hours, minutes, seconds, ms) {
1460
- return Date.UTC(year, monthIndex, day ?? 1, hours ?? 0, minutes ?? 0, seconds ?? 0, ms ?? 0);
1461
- }
1462
- static fromTPS(tps) {
1463
- return new TpsDate(tps);
1464
- }
1465
- toGregorianDate() {
1466
- return new Date(this.internal.getTime());
1467
- }
1468
- toDate() {
1469
- return this.toGregorianDate();
1470
- }
1471
- toTPS(calendar = exports.DefaultCalendars.TPS, opts) {
1472
- return TPS.fromDate(this.internal, calendar, opts);
1473
- }
1474
- toTPSURI(calendar = exports.DefaultCalendars.TPS, opts) {
1475
- const time = this.toTPS(calendar, { order: opts?.order });
1476
- const comp = TPS.parse(time);
1477
- if (opts?.latitude !== undefined && opts?.longitude !== undefined) {
1478
- comp.latitude = opts.latitude;
1479
- comp.longitude = opts.longitude;
1480
- if (opts.altitude !== undefined)
1481
- comp.altitude = opts.altitude;
1482
- }
1483
- else if (opts?.isHiddenLocation) {
1484
- comp.isHiddenLocation = true;
1485
- }
1486
- else if (opts?.isRedactedLocation) {
1487
- comp.isRedactedLocation = true;
1488
- }
1489
- else {
1490
- comp.isUnknownLocation = true;
1491
- }
1492
- return TPS.toURI(comp);
1493
- }
1494
- getTime() {
1495
- return this.internal.getTime();
1496
- }
1497
- valueOf() {
1498
- return this.internal.valueOf();
1499
- }
1500
- toString() {
1501
- return this.toTPS(exports.DefaultCalendars.TPS);
1502
- }
1503
- toISOString() {
1504
- return this.internal.toISOString();
1505
- }
1506
- toUTCString() {
1507
- return this.internal.toUTCString();
1508
- }
1509
- toJSON() {
1510
- return this.internal.toJSON();
1511
- }
1512
- getFullYear() {
1513
- return this.getTpsFullYear();
1514
- }
1515
- getUTCFullYear() {
1516
- return this.getTpsFullYear();
1517
- }
1518
- getMonth() {
1519
- return this.getTpsComponents().month - 1;
1520
- }
1521
- getUTCMonth() {
1522
- return this.getTpsComponents().month - 1;
1523
- }
1524
- getDate() {
1525
- return this.getTpsComponents().day;
1526
- }
1527
- getUTCDate() {
1528
- return this.getTpsComponents().day;
1529
- }
1530
- getHours() {
1531
- return this.getTpsComponents().hour;
1532
- }
1533
- getUTCHours() {
1534
- return this.getTpsComponents().hour;
1535
- }
1536
- getMinutes() {
1537
- return this.getTpsComponents().minute;
1538
- }
1539
- getUTCMinutes() {
1540
- return this.getTpsComponents().minute;
1541
- }
1542
- getSeconds() {
1543
- return this.getTpsComponents().second;
1544
- }
1545
- getUTCSeconds() {
1546
- return this.getTpsComponents().second;
1547
- }
1548
- getMilliseconds() {
1549
- return this.getTpsComponents().millisecond;
1550
- }
1551
- getUTCMilliseconds() {
1552
- return this.getTpsComponents().millisecond;
1553
- }
1554
- [Symbol.toPrimitive](hint) {
1555
- if (hint === "number")
1556
- return this.valueOf();
1557
- return this.toString();
1558
- }
1559
- }
1560
- exports.TpsDate = TpsDate;
1561
616
  //# sourceMappingURL=index.js.map