@matter/general 0.16.0-alpha.0-20250817-1b000357c → 0.16.0-alpha.0-20250819-0a388db8b

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 (193) hide show
  1. package/dist/cjs/codec/DnsCodec.d.ts +8 -6
  2. package/dist/cjs/codec/DnsCodec.d.ts.map +1 -1
  3. package/dist/cjs/codec/DnsCodec.js +10 -7
  4. package/dist/cjs/codec/DnsCodec.js.map +1 -1
  5. package/dist/cjs/crypto/Crypto.d.ts +32 -36
  6. package/dist/cjs/crypto/Crypto.d.ts.map +1 -1
  7. package/dist/cjs/environment/Environment.d.ts.map +1 -1
  8. package/dist/cjs/environment/Environment.js +2 -1
  9. package/dist/cjs/environment/Environment.js.map +1 -1
  10. package/dist/cjs/log/Diagnostic.d.ts +4 -6
  11. package/dist/cjs/log/Diagnostic.d.ts.map +1 -1
  12. package/dist/cjs/log/Diagnostic.js +6 -26
  13. package/dist/cjs/log/Diagnostic.js.map +1 -1
  14. package/dist/cjs/log/Logger.js +1 -1
  15. package/dist/cjs/log/Logger.js.map +1 -1
  16. package/dist/cjs/net/RetrySchedule.d.ts +10 -11
  17. package/dist/cjs/net/RetrySchedule.d.ts.map +1 -1
  18. package/dist/cjs/net/RetrySchedule.js +8 -7
  19. package/dist/cjs/net/RetrySchedule.js.map +1 -1
  20. package/dist/cjs/net/ServerAddress.d.ts +15 -4
  21. package/dist/cjs/net/ServerAddress.d.ts.map +1 -1
  22. package/dist/cjs/net/ServerAddress.js +33 -3
  23. package/dist/cjs/net/ServerAddress.js.map +2 -2
  24. package/dist/cjs/net/UdpMulticastServer.d.ts.map +1 -1
  25. package/dist/cjs/net/UdpMulticastServer.js +2 -1
  26. package/dist/cjs/net/UdpMulticastServer.js.map +1 -1
  27. package/dist/cjs/storage/StringifyTools.d.ts +2 -1
  28. package/dist/cjs/storage/StringifyTools.d.ts.map +1 -1
  29. package/dist/cjs/storage/StringifyTools.js +3 -0
  30. package/dist/cjs/storage/StringifyTools.js.map +1 -1
  31. package/dist/cjs/time/Duration.d.ts +47 -0
  32. package/dist/cjs/time/Duration.d.ts.map +1 -0
  33. package/dist/cjs/time/Duration.js +145 -0
  34. package/dist/cjs/time/Duration.js.map +6 -0
  35. package/dist/cjs/time/Time.d.ts +21 -19
  36. package/dist/cjs/time/Time.d.ts.map +1 -1
  37. package/dist/cjs/time/Time.js +44 -33
  38. package/dist/cjs/time/Time.js.map +1 -1
  39. package/dist/cjs/time/TimeUnit.d.ts +87 -0
  40. package/dist/cjs/time/TimeUnit.d.ts.map +1 -0
  41. package/dist/cjs/time/TimeUnit.js +88 -0
  42. package/dist/cjs/time/TimeUnit.js.map +6 -0
  43. package/dist/cjs/time/Timespan.d.ts +26 -0
  44. package/dist/cjs/time/Timespan.d.ts.map +1 -0
  45. package/dist/cjs/time/Timespan.js +52 -0
  46. package/dist/cjs/time/Timespan.js.map +6 -0
  47. package/dist/cjs/time/Timestamp.d.ts +47 -0
  48. package/dist/cjs/time/Timestamp.d.ts.map +1 -0
  49. package/dist/cjs/time/Timestamp.js +78 -0
  50. package/dist/cjs/time/Timestamp.js.map +6 -0
  51. package/dist/cjs/time/index.d.ts +4 -0
  52. package/dist/cjs/time/index.d.ts.map +1 -1
  53. package/dist/cjs/time/index.js +4 -0
  54. package/dist/cjs/time/index.js.map +1 -1
  55. package/dist/cjs/transaction/Status.d.ts +1 -1
  56. package/dist/cjs/transaction/Status.d.ts.map +1 -1
  57. package/dist/cjs/transaction/Status.js +2 -1
  58. package/dist/cjs/transaction/Status.js.map +1 -1
  59. package/dist/cjs/transaction/Tx.d.ts.map +1 -1
  60. package/dist/cjs/transaction/Tx.js +10 -8
  61. package/dist/cjs/transaction/Tx.js.map +1 -1
  62. package/dist/cjs/util/Cache.d.ts +5 -4
  63. package/dist/cjs/util/Cache.d.ts.map +1 -1
  64. package/dist/cjs/util/Cache.js +11 -11
  65. package/dist/cjs/util/Cache.js.map +1 -1
  66. package/dist/cjs/util/DataReadQueue.d.ts +2 -1
  67. package/dist/cjs/util/DataReadQueue.d.ts.map +1 -1
  68. package/dist/cjs/util/DataReadQueue.js +9 -3
  69. package/dist/cjs/util/DataReadQueue.js.map +1 -1
  70. package/dist/cjs/util/DeepEqual.d.ts +13 -1
  71. package/dist/cjs/util/DeepEqual.d.ts.map +1 -1
  72. package/dist/cjs/util/DeepEqual.js +24 -5
  73. package/dist/cjs/util/DeepEqual.js.map +2 -2
  74. package/dist/cjs/util/Observable.d.ts +4 -3
  75. package/dist/cjs/util/Observable.d.ts.map +1 -1
  76. package/dist/cjs/util/Observable.js +16 -15
  77. package/dist/cjs/util/Observable.js.map +1 -1
  78. package/dist/cjs/util/PromiseQueue.d.ts +2 -1
  79. package/dist/cjs/util/PromiseQueue.d.ts.map +1 -1
  80. package/dist/cjs/util/PromiseQueue.js +2 -1
  81. package/dist/cjs/util/PromiseQueue.js.map +1 -1
  82. package/dist/cjs/util/Promises.d.ts +3 -2
  83. package/dist/cjs/util/Promises.d.ts.map +1 -1
  84. package/dist/cjs/util/Promises.js +4 -4
  85. package/dist/cjs/util/Promises.js.map +1 -1
  86. package/dist/esm/codec/DnsCodec.d.ts +8 -6
  87. package/dist/esm/codec/DnsCodec.d.ts.map +1 -1
  88. package/dist/esm/codec/DnsCodec.js +10 -7
  89. package/dist/esm/codec/DnsCodec.js.map +1 -1
  90. package/dist/esm/crypto/Crypto.d.ts +32 -36
  91. package/dist/esm/crypto/Crypto.d.ts.map +1 -1
  92. package/dist/esm/environment/Environment.d.ts.map +1 -1
  93. package/dist/esm/environment/Environment.js +2 -1
  94. package/dist/esm/environment/Environment.js.map +1 -1
  95. package/dist/esm/log/Diagnostic.d.ts +4 -6
  96. package/dist/esm/log/Diagnostic.d.ts.map +1 -1
  97. package/dist/esm/log/Diagnostic.js +6 -26
  98. package/dist/esm/log/Diagnostic.js.map +1 -1
  99. package/dist/esm/log/Logger.js +1 -1
  100. package/dist/esm/log/Logger.js.map +1 -1
  101. package/dist/esm/net/RetrySchedule.d.ts +10 -11
  102. package/dist/esm/net/RetrySchedule.d.ts.map +1 -1
  103. package/dist/esm/net/RetrySchedule.js +8 -7
  104. package/dist/esm/net/RetrySchedule.js.map +1 -1
  105. package/dist/esm/net/ServerAddress.d.ts +15 -4
  106. package/dist/esm/net/ServerAddress.d.ts.map +1 -1
  107. package/dist/esm/net/ServerAddress.js +33 -3
  108. package/dist/esm/net/ServerAddress.js.map +2 -2
  109. package/dist/esm/net/UdpMulticastServer.d.ts.map +1 -1
  110. package/dist/esm/net/UdpMulticastServer.js +2 -1
  111. package/dist/esm/net/UdpMulticastServer.js.map +1 -1
  112. package/dist/esm/storage/StringifyTools.d.ts +2 -1
  113. package/dist/esm/storage/StringifyTools.d.ts.map +1 -1
  114. package/dist/esm/storage/StringifyTools.js +3 -0
  115. package/dist/esm/storage/StringifyTools.js.map +1 -1
  116. package/dist/esm/time/Duration.d.ts +47 -0
  117. package/dist/esm/time/Duration.d.ts.map +1 -0
  118. package/dist/esm/time/Duration.js +125 -0
  119. package/dist/esm/time/Duration.js.map +6 -0
  120. package/dist/esm/time/Time.d.ts +21 -19
  121. package/dist/esm/time/Time.d.ts.map +1 -1
  122. package/dist/esm/time/Time.js +44 -33
  123. package/dist/esm/time/Time.js.map +1 -1
  124. package/dist/esm/time/TimeUnit.d.ts +87 -0
  125. package/dist/esm/time/TimeUnit.d.ts.map +1 -0
  126. package/dist/esm/time/TimeUnit.js +68 -0
  127. package/dist/esm/time/TimeUnit.js.map +6 -0
  128. package/dist/esm/time/Timespan.d.ts +26 -0
  129. package/dist/esm/time/Timespan.d.ts.map +1 -0
  130. package/dist/esm/time/Timespan.js +32 -0
  131. package/dist/esm/time/Timespan.js.map +6 -0
  132. package/dist/esm/time/Timestamp.d.ts +47 -0
  133. package/dist/esm/time/Timestamp.d.ts.map +1 -0
  134. package/dist/esm/time/Timestamp.js +58 -0
  135. package/dist/esm/time/Timestamp.js.map +6 -0
  136. package/dist/esm/time/index.d.ts +4 -0
  137. package/dist/esm/time/index.d.ts.map +1 -1
  138. package/dist/esm/time/index.js +4 -0
  139. package/dist/esm/time/index.js.map +1 -1
  140. package/dist/esm/transaction/Status.d.ts +1 -1
  141. package/dist/esm/transaction/Status.d.ts.map +1 -1
  142. package/dist/esm/transaction/Status.js +2 -1
  143. package/dist/esm/transaction/Status.js.map +1 -1
  144. package/dist/esm/transaction/Tx.d.ts.map +1 -1
  145. package/dist/esm/transaction/Tx.js +10 -8
  146. package/dist/esm/transaction/Tx.js.map +1 -1
  147. package/dist/esm/util/Cache.d.ts +5 -4
  148. package/dist/esm/util/Cache.d.ts.map +1 -1
  149. package/dist/esm/util/Cache.js +11 -11
  150. package/dist/esm/util/Cache.js.map +1 -1
  151. package/dist/esm/util/DataReadQueue.d.ts +2 -1
  152. package/dist/esm/util/DataReadQueue.d.ts.map +1 -1
  153. package/dist/esm/util/DataReadQueue.js +9 -3
  154. package/dist/esm/util/DataReadQueue.js.map +1 -1
  155. package/dist/esm/util/DeepEqual.d.ts +13 -1
  156. package/dist/esm/util/DeepEqual.d.ts.map +1 -1
  157. package/dist/esm/util/DeepEqual.js +24 -5
  158. package/dist/esm/util/DeepEqual.js.map +2 -2
  159. package/dist/esm/util/Observable.d.ts +4 -3
  160. package/dist/esm/util/Observable.d.ts.map +1 -1
  161. package/dist/esm/util/Observable.js +16 -15
  162. package/dist/esm/util/Observable.js.map +1 -1
  163. package/dist/esm/util/PromiseQueue.d.ts +2 -1
  164. package/dist/esm/util/PromiseQueue.d.ts.map +1 -1
  165. package/dist/esm/util/PromiseQueue.js +2 -1
  166. package/dist/esm/util/PromiseQueue.js.map +1 -1
  167. package/dist/esm/util/Promises.d.ts +3 -2
  168. package/dist/esm/util/Promises.d.ts.map +1 -1
  169. package/dist/esm/util/Promises.js +4 -4
  170. package/dist/esm/util/Promises.js.map +1 -1
  171. package/package.json +3 -3
  172. package/src/codec/DnsCodec.ts +27 -8
  173. package/src/environment/Environment.ts +2 -1
  174. package/src/log/Diagnostic.ts +9 -37
  175. package/src/log/Logger.ts +1 -1
  176. package/src/net/RetrySchedule.ts +14 -14
  177. package/src/net/ServerAddress.ts +44 -5
  178. package/src/net/UdpMulticastServer.ts +2 -1
  179. package/src/storage/StringifyTools.ts +5 -0
  180. package/src/time/Duration.ts +181 -0
  181. package/src/time/Time.ts +50 -39
  182. package/src/time/TimeUnit.ts +159 -0
  183. package/src/time/Timespan.ts +52 -0
  184. package/src/time/Timestamp.ts +94 -0
  185. package/src/time/index.ts +4 -0
  186. package/src/transaction/Status.ts +2 -1
  187. package/src/transaction/Tx.ts +9 -7
  188. package/src/util/Cache.ts +11 -10
  189. package/src/util/DataReadQueue.ts +9 -3
  190. package/src/util/DeepEqual.ts +38 -13
  191. package/src/util/Observable.ts +19 -17
  192. package/src/util/PromiseQueue.ts +4 -2
  193. package/src/util/Promises.ts +6 -5
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Duration } from "./Duration.js";
8
+ import { Timestamp } from "./Timestamp.js";
9
+
10
+ /**
11
+ * A period between two {@link Timestamp}s.
12
+ */
13
+ export interface Timespan {
14
+ start: Timestamp;
15
+ stop: Timestamp;
16
+ duration: Duration;
17
+
18
+ from(newStart: Timestamp.Definition): Timespan;
19
+ to(newStart: Timestamp.Definition): Timespan;
20
+ valueOf(): { start: Timestamp; stop: Timestamp };
21
+ }
22
+
23
+ /**
24
+ * Create a new timespan representing time between {@link start} and {@link stop}.
25
+ */
26
+ export function Timespan(start: Timestamp.Definition, stop: Timestamp.Definition) {
27
+ return Object.create(prototype, {
28
+ start: { value: Timestamp(start), enumerable: true },
29
+ stop: { value: Timestamp(stop), enumerable: true },
30
+ }) as Timespan;
31
+ }
32
+
33
+ const prototype: Timespan = {
34
+ start: 0 as Timestamp,
35
+ stop: 0 as Timestamp,
36
+
37
+ get duration() {
38
+ return (this.stop - this.start) as Duration;
39
+ },
40
+
41
+ from(this: Timespan, newStart) {
42
+ return Timespan(newStart, this.stop);
43
+ },
44
+
45
+ to(this: Timespan, newStop) {
46
+ return Timespan(this.start, newStop);
47
+ },
48
+
49
+ valueOf(this: Timespan) {
50
+ return { start: this.start, stop: this.stop };
51
+ },
52
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { UnexpectedDataError } from "#MatterError.js";
8
+ import { Branded } from "#util/Type.js";
9
+ import { Time } from "./Time.js";
10
+
11
+ /**
12
+ * A UNIX epoch timestamp in milliseconds.
13
+ *
14
+ * Note that the precision of the timestamp may be greater than milliseconds but is limited to floating point precision.
15
+ */
16
+ export type Timestamp = Branded<number, "Timestamp"> | 0;
17
+
18
+ /**
19
+ * Create a timestamp.
20
+ *
21
+ * Input may be a UNIX epoch value in milliseconds, a parseable date string, or a {@link Date}.
22
+ */
23
+ export function Timestamp<T extends undefined | Timestamp.Definition>(
24
+ source: T,
25
+ ): T extends undefined ? undefined | Timestamp : Timestamp {
26
+ if (source === undefined) {
27
+ return Time.nowMs;
28
+ }
29
+
30
+ if (typeof source === "string") {
31
+ const date = Date.parse(source);
32
+ if (Number.isNaN(date.valueOf())) {
33
+ throw new TimestampFormatError("Invalid timestamp format");
34
+ }
35
+ } else if (typeof source === "object" && source !== null && source instanceof Date) {
36
+ if (Number.isNaN(source.valueOf())) {
37
+ throw new TimestampFormatError("Cannot convert date to timestamp because it is invalid");
38
+ }
39
+ source = source.getTime() as T;
40
+ } else if (typeof source === "bigint") {
41
+ source = Number(source) as T;
42
+ }
43
+
44
+ if (typeof source === "number") {
45
+ if (Number.isNaN(source)) {
46
+ throw new TimestampFormatError("A timestamp may not be NaN");
47
+ }
48
+ } else {
49
+ throw new TimestampFormatError(`Timestamp is not a number (received ${typeof source})`);
50
+ }
51
+
52
+ return source as Timestamp;
53
+ }
54
+
55
+ /**
56
+ * Thrown when a textual timestamp cannot be parsed.
57
+ */
58
+ export class TimestampFormatError extends UnexpectedDataError {}
59
+
60
+ export namespace Timestamp {
61
+ /**
62
+ * Values that may be used to initialize a timestamp.
63
+ */
64
+ export type Definition = number | bigint | string | Date;
65
+
66
+ /**
67
+ * Create a low-resolution timestamp from a seconds value.
68
+ */
69
+ export function fromSeconds(source: number) {
70
+ return Math.floor(source * 1000);
71
+ }
72
+
73
+ /**
74
+ * Create a high-resolution timestamp from a microsecond value.
75
+ */
76
+ export function fromMicroseconds(source: number | bigint) {
77
+ if (typeof source === "bigint") {
78
+ source = Number(source);
79
+ }
80
+ return Timestamp(source / 1000);
81
+ }
82
+
83
+ /**
84
+ * The UNIX epoch.
85
+ */
86
+ export const zero = Timestamp(0);
87
+
88
+ /**
89
+ * Obtain a {@link Date} for a {@link Timestamp}.
90
+ */
91
+ export function dateOf(timestamp: Timestamp) {
92
+ return new Date(timestamp);
93
+ }
94
+ }
package/src/time/index.ts CHANGED
@@ -4,4 +4,8 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ export * from "./Duration.js";
7
8
  export * from "./Time.js";
9
+ export * from "./Timespan.js";
10
+ export * from "./Timestamp.js";
11
+ export * from "./TimeUnit.js";
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { LogLevel } from "#log/LogLevel.js";
8
+ import { Millis } from "#time/TimeUnit.js";
8
9
  import { TransactionFlowError } from "./errors.js";
9
10
  import type { Transaction } from "./Transaction.js";
10
11
 
@@ -74,7 +75,7 @@ export namespace Status {
74
75
  * A value of 0 forces lock reports for all async transactions; a negative value disables reporting.
75
76
  */
76
77
  // eslint-disable-next-line prefer-const
77
- export let slowTransactionMs = 200;
78
+ export let slowTransactionTime = Millis(200);
78
79
 
79
80
  /**
80
81
  * The log level for slow transaction reporting.
@@ -8,6 +8,8 @@ import { Diagnostic } from "#log/Diagnostic.js";
8
8
  import { Logger } from "#log/Logger.js";
9
9
  import { ImplementationError, ReadOnlyError } from "#MatterError.js";
10
10
  import { Time, Timer } from "#time/Time.js";
11
+ import { Timestamp } from "#time/Timestamp.js";
12
+ import { Millis } from "#time/TimeUnit.js";
11
13
  import { asError } from "#util/Error.js";
12
14
  import { Observable } from "#util/Observable.js";
13
15
  import { MaybePromise } from "#util/Promises.js";
@@ -810,11 +812,11 @@ function throwIfErrored(errored: undefined | Array<Participant>, when: string) {
810
812
  * "Slow" async transaction monitoring implementation.
811
813
  */
812
814
  const Monitor = (function () {
813
- const monitored = new Map<Tx, number>();
815
+ const monitored = new Map<Tx, Timestamp>();
814
816
  let monitor: Timer | undefined;
815
817
 
816
818
  function check() {
817
- const now = Time.nowMs();
819
+ const now = Time.nowMs;
818
820
  for (const [tx, slowAt] of monitored) {
819
821
  if (now > slowAt) {
820
822
  tx.treatAsSlow();
@@ -824,12 +826,12 @@ const Monitor = (function () {
824
826
 
825
827
  return {
826
828
  add(tx: Tx) {
827
- const { slowTransactionMs } = Status;
828
- if (slowTransactionMs < 0) {
829
+ const { slowTransactionTime } = Status;
830
+ if (slowTransactionTime < 0) {
829
831
  return;
830
832
  }
831
833
 
832
- if (!slowTransactionMs) {
834
+ if (!slowTransactionTime) {
833
835
  tx.treatAsSlow();
834
836
  return;
835
837
  }
@@ -838,9 +840,9 @@ const Monitor = (function () {
838
840
  return;
839
841
  }
840
842
 
841
- monitored.set(tx, Time.nowMs() + slowTransactionMs);
843
+ monitored.set(tx, Timestamp(Time.nowMs + slowTransactionTime));
842
844
  if (monitor === undefined) {
843
- monitor = Time.getPeriodicTimer("tx-lock-monitor", slowTransactionMs / 10, check);
845
+ monitor = Time.getPeriodicTimer("tx-lock-monitor", Millis(slowTransactionTime / 10), check);
844
846
  monitor.start();
845
847
  }
846
848
  },
package/src/util/Cache.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  * SPDX-License-Identifier: Apache-2.0
7
7
  */
8
8
 
9
+ import { Duration } from "#time/Duration.js";
9
10
  import { Diagnostic } from "../log/Diagnostic.js";
10
11
  import { Time, Timer } from "../time/Time.js";
11
12
 
@@ -17,12 +18,12 @@ class GenericCache<T> {
17
18
 
18
19
  constructor(
19
20
  name: string,
20
- private readonly expirationMs: number,
21
+ private readonly expiration: Duration,
21
22
  private readonly expireCallback?: (key: string, value: T) => Promise<void>,
22
23
  ) {
23
24
  this.periodicTimer = Time.getPeriodicTimer(
24
25
  Diagnostic.upgrade(`${name} cache expiration`, [Diagnostic.strong(name), "cache expiration"]),
25
- expirationMs,
26
+ expiration,
26
27
  () => this.expire(),
27
28
  ).start();
28
29
  this.periodicTimer.utility = true;
@@ -56,9 +57,9 @@ class GenericCache<T> {
56
57
  }
57
58
 
58
59
  private async expire() {
59
- const now = Time.nowMs();
60
+ const now = Time.nowMs;
60
61
  for (const [key, timestamp] of this.timestamps.entries()) {
61
- if (now - timestamp < this.expirationMs) continue;
62
+ if (now - timestamp < this.expiration) continue;
62
63
  await this.delete(key);
63
64
  }
64
65
  }
@@ -68,10 +69,10 @@ export class Cache<T> extends GenericCache<T> {
68
69
  constructor(
69
70
  name: string,
70
71
  private readonly generator: (...params: any[]) => T,
71
- expirationMs: number,
72
+ expiration: Duration,
72
73
  expireCallback?: (key: string, value: T) => Promise<void>,
73
74
  ) {
74
- super(name, expirationMs, expireCallback);
75
+ super(name, expiration, expireCallback);
75
76
  }
76
77
 
77
78
  get(...params: any[]) {
@@ -82,7 +83,7 @@ export class Cache<T> extends GenericCache<T> {
82
83
  this.values.set(key, value);
83
84
  this.knownKeys.add(key);
84
85
  }
85
- this.timestamps.set(key, Time.nowMs());
86
+ this.timestamps.set(key, Time.nowMs);
86
87
  return value;
87
88
  }
88
89
  }
@@ -91,10 +92,10 @@ export class AsyncCache<T> extends GenericCache<T> {
91
92
  constructor(
92
93
  name: string,
93
94
  private readonly generator: (...params: any[]) => Promise<T>,
94
- expirationMs: number,
95
+ expiration: Duration,
95
96
  expireCallback?: (key: string, value: T) => Promise<void>,
96
97
  ) {
97
- super(name, expirationMs, expireCallback);
98
+ super(name, expiration, expireCallback);
98
99
  }
99
100
 
100
101
  async get(...params: any[]) {
@@ -105,7 +106,7 @@ export class AsyncCache<T> extends GenericCache<T> {
105
106
  this.values.set(key, value);
106
107
  this.knownKeys.add(key);
107
108
  }
108
- this.timestamps.set(key, Time.nowMs());
109
+ this.timestamps.set(key, Time.nowMs);
109
110
  return value;
110
111
  }
111
112
  }
@@ -6,6 +6,8 @@
6
6
  * SPDX-License-Identifier: Apache-2.0
7
7
  */
8
8
 
9
+ import { Duration } from "#time/Duration.js";
10
+ import { Minutes } from "#time/TimeUnit.js";
9
11
  import { MatterFlowError } from "../MatterError.js";
10
12
  import { Time, Timer } from "../time/Time.js";
11
13
  import { createPromise } from "./Promises.js";
@@ -16,7 +18,7 @@ export class DataReadQueue<T> implements Stream<T> {
16
18
  #pendingRead?: { resolver: (data: T) => void; rejecter: (reason: any) => void; timeoutTimer?: Timer };
17
19
  #closed = false;
18
20
 
19
- async read(timeoutMs = 60_000): Promise<T> {
21
+ async read(timeout = Minutes.one): Promise<T> {
20
22
  const { promise, resolver, rejecter } = createPromise<T>();
21
23
  if (this.#closed) throw new EndOfStreamError();
22
24
  const data = this.#queue.shift();
@@ -27,8 +29,12 @@ export class DataReadQueue<T> implements Stream<T> {
27
29
  this.#pendingRead = {
28
30
  resolver,
29
31
  rejecter,
30
- timeoutTimer: Time.getTimer("Queue timeout", timeoutMs, () =>
31
- rejecter(new NoResponseTimeoutError(`Expected response data missing within timeout of ${timeoutMs}ms`)),
32
+ timeoutTimer: Time.getTimer("Queue timeout", timeout, () =>
33
+ rejecter(
34
+ new NoResponseTimeoutError(
35
+ `Expected response data missing within timeout of ${Duration.format(timeout)}`,
36
+ ),
37
+ ),
32
38
  ).start(),
33
39
  };
34
40
  return promise;
@@ -4,19 +4,41 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ /**
8
+ * An object that supports custom deep equality.
9
+ */
10
+ export interface DeepComparable {
11
+ /**
12
+ * Deep-compare this object to another.
13
+ */
14
+ [DeepComparable.equals](other: unknown): boolean;
15
+ }
16
+
17
+ export namespace DeepComparable {
18
+ export const equals = Symbol("deepEquals");
19
+ }
20
+
7
21
  // TODO - implement more efficient specialization for Array and ArrayBuffer
8
22
  // TODO - currently will hang on self-referential data structures
9
- export function isDeepEqual(a: any, b: any, ignoreUndefinedProperties = false): boolean {
10
- if (
11
- a === null ||
12
- a === undefined ||
13
- b === null ||
14
- b === undefined ||
15
- typeof a !== typeof b ||
16
- (typeof a !== "object" && typeof b !== "object")
17
- ) {
23
+ export function isDeepEqual(a: unknown, b: unknown, ignoreUndefinedProperties = false): boolean {
24
+ const aIsObject = typeof a === "object" && a !== null;
25
+ if (aIsObject) {
26
+ if (DeepComparable.equals in a) {
27
+ return (a as DeepComparable)[DeepComparable.equals](b);
28
+ }
29
+ }
30
+
31
+ const bIsObject = typeof b === "object" && b !== null;
32
+ if (bIsObject) {
33
+ if (DeepComparable.equals in b) {
34
+ return (b as DeepComparable)[DeepComparable.equals](a);
35
+ }
36
+ }
37
+
38
+ if (!aIsObject || !bIsObject) {
18
39
  return a === b;
19
40
  }
41
+
20
42
  // Create arrays of property names
21
43
  const aProps = Object.getOwnPropertyNames(a);
22
44
  const bProps = Object.getOwnPropertyNames(b);
@@ -29,16 +51,19 @@ export function isDeepEqual(a: any, b: any, ignoreUndefinedProperties = false):
29
51
  for (let i = 0; i < aProps.length; i++) {
30
52
  const propName = aProps[i];
31
53
 
32
- if (typeof a[propName] !== typeof b[propName]) {
54
+ const aprop = (a as Record<string, unknown>)[propName];
55
+ const bprop = (b as Record<string, unknown>)[propName];
56
+
57
+ if (typeof aprop !== typeof bprop) {
33
58
  return false;
34
59
  }
35
- if (typeof a[propName] === "object") {
36
- if (!isDeepEqual(a[propName], b[propName])) {
60
+ if (typeof aprop === "object") {
61
+ if (!isDeepEqual(aprop, bprop)) {
37
62
  return false;
38
63
  }
39
64
  } else {
40
65
  // If values of same property are not equal, objects are not equivalent
41
- if (a[propName] !== b[propName]) {
66
+ if (aprop !== bprop) {
42
67
  return false;
43
68
  }
44
69
  }
@@ -4,7 +4,9 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { Duration } from "#time/Duration.js";
7
8
  import { Time, Timer } from "#time/Time.js";
9
+ import { Instant, Millis, Seconds } from "#time/TimeUnit.js";
8
10
  import { ImplementationError } from "../MatterError.js";
9
11
  import { Logger } from "../log/Logger.js";
10
12
  import "../polyfills/disposable.js";
@@ -654,7 +656,7 @@ export namespace ObserverGroup {
654
656
  export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T> implements QuietObservable.State<T> {
655
657
  #emitAutomatically = QuietObservable.defaults.emitAutomatically;
656
658
  #suppressionEnabled = QuietObservable.defaults.suppressionEnabled;
657
- #minimumEmitIntervalMs = QuietObservable.defaults.minimumEmitIntervalMs;
659
+ #minimumEmitInterval = QuietObservable.defaults.minimumEmitInterval;
658
660
  #shouldEmit?: QuietObservable.EmitPredicate<T>;
659
661
  #source?: Observable<T>;
660
662
  #sink?: Observable<T>;
@@ -676,15 +678,15 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
676
678
  }
677
679
 
678
680
  set config(config: QuietObservable.Configuration<T>) {
679
- const { suppressionEnabled, minimumEmitIntervalMs, emitAutomatically } = config;
681
+ const { suppressionEnabled, minimumEmitInterval, emitAutomatically } = config;
680
682
  if (emitAutomatically !== undefined) {
681
683
  this.emitAutomatically = emitAutomatically;
682
684
  }
683
685
  if (suppressionEnabled !== undefined) {
684
686
  this.suppressionEnabled = suppressionEnabled;
685
687
  }
686
- if (minimumEmitIntervalMs !== undefined) {
687
- this.minimumEmitIntervalMs = minimumEmitIntervalMs;
688
+ if (minimumEmitInterval !== undefined) {
689
+ this.minimumEmitInterval = minimumEmitInterval;
688
690
  }
689
691
  if ("shouldEmit" in config) {
690
692
  this.shouldEmit = config.shouldEmit;
@@ -726,19 +728,19 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
726
728
  this.#suppressionEnabled = value;
727
729
  }
728
730
 
729
- get minimumEmitIntervalMs() {
730
- return this.#minimumEmitIntervalMs;
731
+ get minimumEmitInterval() {
732
+ return this.#minimumEmitInterval;
731
733
  }
732
734
 
733
- set minimumEmitIntervalMs(value: number) {
734
- if (this.#minimumEmitIntervalMs === value) {
735
+ set minimumEmitInterval(value: Duration) {
736
+ if (this.#minimumEmitInterval === value) {
735
737
  return;
736
738
  }
737
739
  const needStart = this.#emitTimer !== undefined;
738
740
  if (needStart) {
739
741
  this.#stop();
740
742
  }
741
- this.#minimumEmitIntervalMs = value;
743
+ this.#minimumEmitInterval = value;
742
744
  if (needStart) {
743
745
  this.#start();
744
746
  }
@@ -812,12 +814,12 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
812
814
  this.#deferredPayload = payload;
813
815
  return;
814
816
  }
815
- const now = Time.nowMs();
817
+ const now = Time.nowMs;
816
818
  if (
817
819
  immediate ||
818
820
  !this.#suppressionEnabled ||
819
821
  this.#lastEmitAt === undefined ||
820
- this.#lastEmitAt + this.#minimumEmitIntervalMs < now
822
+ this.#lastEmitAt + this.#minimumEmitInterval < now
821
823
  ) {
822
824
  return this.#emit(payload, now);
823
825
  }
@@ -851,7 +853,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
851
853
 
852
854
  #emit(payload: T, now?: number) {
853
855
  this.#deferredPayload = undefined;
854
- this.#lastEmitAt = now ?? Time.nowMs();
856
+ this.#lastEmitAt = now ?? Time.nowMs;
855
857
  this.#stop();
856
858
  super.emit(...payload);
857
859
  }
@@ -861,11 +863,11 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
861
863
  return;
862
864
  }
863
865
 
864
- let timeout;
866
+ let timeout: Duration;
865
867
  if (this.#lastEmitAt === undefined) {
866
- timeout = 0;
868
+ timeout = Instant;
867
869
  } else {
868
- timeout = this.#minimumEmitIntervalMs - ((now ?? Time.nowMs()) - this.#lastEmitAt);
870
+ timeout = Millis(this.#minimumEmitInterval - ((now ?? Time.nowMs) - this.#lastEmitAt));
869
871
  }
870
872
 
871
873
  if (timeout <= 0) {
@@ -900,7 +902,7 @@ export namespace QuietObservable {
900
902
  /**
901
903
  * The minimum time between emits in milliseconds.
902
904
  */
903
- minimumEmitIntervalMs: number;
905
+ minimumEmitInterval: Duration;
904
906
 
905
907
  /**
906
908
  * An input observable this observable will automatically observe to produce events.
@@ -956,6 +958,6 @@ export namespace QuietObservable {
956
958
  export const defaults: State = {
957
959
  emitAutomatically: true,
958
960
  suppressionEnabled: true,
959
- minimumEmitIntervalMs: 1000,
961
+ minimumEmitInterval: Seconds.one,
960
962
  };
961
963
  }
@@ -4,7 +4,9 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { Duration } from "#time/Duration.js";
7
8
  import { Time } from "#time/Time.js";
9
+ import { Instant } from "#time/TimeUnit.js";
8
10
  import { Logger } from "../log/Logger.js";
9
11
  import { createPromise } from "./Promises.js";
10
12
 
@@ -14,12 +16,12 @@ const logger = Logger.get("PromiseQueue");
14
16
  * A queue that processes promises with a given concurrency and delays after each promise if desired.
15
17
  */
16
18
  export class PromiseQueue {
17
- readonly #delay: number;
19
+ readonly #delay: Duration;
18
20
  readonly #queue = new Array<{ func: () => Promise<any>; rejecter: (reason?: any) => void }>();
19
21
  readonly #concurrency: number;
20
22
  #runningCount = 0;
21
23
 
22
- constructor(concurrency = 1, delay = 0) {
24
+ constructor(concurrency = 1, delay = Instant) {
23
25
  this.#concurrency = concurrency;
24
26
  this.#delay = delay;
25
27
  }
@@ -6,6 +6,7 @@
6
6
  * SPDX-License-Identifier: Apache-2.0
7
7
  */
8
8
 
9
+ import { Duration } from "#time/Duration.js";
9
10
  import { asError } from "#util/Error.js";
10
11
  import { InternalError, TimeoutError } from "../MatterError.js";
11
12
  import { Time } from "../time/Time.js";
@@ -74,12 +75,12 @@ export class PromiseTimeoutError extends TimeoutError {}
74
75
  *
75
76
  * By default, rejects with {@link PromiseTimeoutError} on timeout but you can override by supplying {@link cancel}.
76
77
  *
77
- * @param timeoutMs the timeout in milliseconds
78
+ * @param timeout the timeout in milliseconds
78
79
  * @param promise a promise that resolves or rejects when the timed task completes
79
80
  * @param cancel invoked on timeout (default implementation throws {@link PromiseTimeoutError})
80
81
  */
81
82
  export async function withTimeout<T>(
82
- timeoutMs: number,
83
+ timeout: Duration,
83
84
  promise: Promise<T>,
84
85
  cancel?: AbortController | (() => void),
85
86
  ): Promise<T> {
@@ -97,8 +98,8 @@ export async function withTimeout<T>(
97
98
  let cancelTimer: undefined | (() => void);
98
99
 
99
100
  // Sub-promise 1, the timer
100
- const timeout = new Promise<void>((resolve, reject) => {
101
- const timer = Time.getTimer("promise-timeout", timeoutMs, () => {
101
+ const timedOut = new Promise<void>((resolve, reject) => {
102
+ const timer = Time.getTimer("promise-timeout", timeout, () => {
102
103
  try {
103
104
  cancelFn();
104
105
  } catch (e) {
@@ -130,7 +131,7 @@ export async function withTimeout<T>(
130
131
  );
131
132
 
132
133
  // Output promise, resolves like input promise unless timed out
133
- await Promise.all([timeout, producer]);
134
+ await Promise.all([timedOut, producer]);
134
135
 
135
136
  return result as T;
136
137
  }