@matter/general 0.16.0-alpha.0-20251203-aaf94bca8 → 0.16.0-alpha.0-20251207-37e501b18

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 (260) hide show
  1. package/dist/cjs/MatterError.js +2 -2
  2. package/dist/cjs/MatterError.js.map +1 -1
  3. package/dist/cjs/codec/DerTypes.d.ts.map +1 -1
  4. package/dist/cjs/codec/DerTypes.js +2 -1
  5. package/dist/cjs/codec/DerTypes.js.map +1 -1
  6. package/dist/cjs/environment/Environment.d.ts +4 -1
  7. package/dist/cjs/environment/Environment.d.ts.map +1 -1
  8. package/dist/cjs/environment/Environment.js +83 -3
  9. package/dist/cjs/environment/Environment.js.map +1 -1
  10. package/dist/cjs/environment/RuntimeService.d.ts +3 -44
  11. package/dist/cjs/environment/RuntimeService.d.ts.map +1 -1
  12. package/dist/cjs/environment/RuntimeService.js +65 -10
  13. package/dist/cjs/environment/RuntimeService.js.map +2 -2
  14. package/dist/cjs/environment/Worker.d.ts +56 -0
  15. package/dist/cjs/environment/Worker.d.ts.map +1 -0
  16. package/dist/cjs/environment/Worker.js +44 -0
  17. package/dist/cjs/environment/Worker.js.map +6 -0
  18. package/dist/cjs/environment/index.d.ts +1 -0
  19. package/dist/cjs/environment/index.d.ts.map +1 -1
  20. package/dist/cjs/environment/index.js +1 -0
  21. package/dist/cjs/environment/index.js.map +1 -1
  22. package/dist/cjs/log/Diagnostic.d.ts +11 -1
  23. package/dist/cjs/log/Diagnostic.d.ts.map +1 -1
  24. package/dist/cjs/log/Diagnostic.js +3 -0
  25. package/dist/cjs/log/Diagnostic.js.map +1 -1
  26. package/dist/cjs/log/DiagnosticPresentation.d.ts +4 -0
  27. package/dist/cjs/log/DiagnosticPresentation.d.ts.map +1 -1
  28. package/dist/cjs/log/DiagnosticPresentation.js +3 -2
  29. package/dist/cjs/log/DiagnosticPresentation.js.map +1 -1
  30. package/dist/cjs/log/DiagnosticSource.d.ts +1 -1
  31. package/dist/cjs/log/DiagnosticSource.d.ts.map +1 -1
  32. package/dist/cjs/log/DiagnosticSource.js +5 -1
  33. package/dist/cjs/log/DiagnosticSource.js.map +1 -1
  34. package/dist/cjs/log/LogFormat.js +2 -2
  35. package/dist/cjs/log/LogFormat.js.map +1 -1
  36. package/dist/cjs/net/Channel.d.ts +1 -1
  37. package/dist/cjs/net/Channel.d.ts.map +1 -1
  38. package/dist/cjs/net/Channel.js +1 -1
  39. package/dist/cjs/net/Channel.js.map +1 -1
  40. package/dist/cjs/net/mock/MockUdpChannel.d.ts +1 -1
  41. package/dist/cjs/net/mock/MockUdpChannel.d.ts.map +1 -1
  42. package/dist/cjs/net/mock/NetworkSimulator.d.ts.map +1 -1
  43. package/dist/cjs/net/mock/NetworkSimulator.js +2 -1
  44. package/dist/cjs/net/mock/NetworkSimulator.js.map +1 -1
  45. package/dist/cjs/net/udp/UdpChannel.d.ts +5 -1
  46. package/dist/cjs/net/udp/UdpChannel.d.ts.map +1 -1
  47. package/dist/cjs/net/udp/UdpMulticastServer.d.ts +4 -6
  48. package/dist/cjs/net/udp/UdpMulticastServer.d.ts.map +1 -1
  49. package/dist/cjs/net/udp/UdpMulticastServer.js +114 -37
  50. package/dist/cjs/net/udp/UdpMulticastServer.js.map +1 -1
  51. package/dist/cjs/time/StandardTime.d.ts +38 -0
  52. package/dist/cjs/time/StandardTime.d.ts.map +1 -0
  53. package/dist/cjs/time/StandardTime.js +172 -0
  54. package/dist/cjs/time/StandardTime.js.map +6 -0
  55. package/dist/cjs/time/Time.d.ts +4 -23
  56. package/dist/cjs/time/Time.d.ts.map +1 -1
  57. package/dist/cjs/time/Time.js +12 -88
  58. package/dist/cjs/time/Time.js.map +1 -1
  59. package/dist/cjs/time/Timestamp.d.ts +5 -0
  60. package/dist/cjs/time/Timestamp.d.ts.map +1 -1
  61. package/dist/cjs/time/Timestamp.js +4 -0
  62. package/dist/cjs/time/Timestamp.js.map +1 -1
  63. package/dist/cjs/time/index.d.ts +1 -0
  64. package/dist/cjs/time/index.d.ts.map +1 -1
  65. package/dist/cjs/time/index.js +1 -0
  66. package/dist/cjs/time/index.js.map +1 -1
  67. package/dist/cjs/transaction/Transaction.d.ts +12 -4
  68. package/dist/cjs/transaction/Transaction.d.ts.map +1 -1
  69. package/dist/cjs/transaction/Transaction.js +4 -4
  70. package/dist/cjs/transaction/Transaction.js.map +1 -1
  71. package/dist/cjs/transaction/Tx.d.ts +2 -1
  72. package/dist/cjs/transaction/Tx.d.ts.map +1 -1
  73. package/dist/cjs/transaction/Tx.js +92 -6
  74. package/dist/cjs/transaction/Tx.js.map +1 -1
  75. package/dist/cjs/util/Abort.js +1 -1
  76. package/dist/cjs/util/Abort.js.map +1 -1
  77. package/dist/cjs/util/Construction.d.ts +2 -1
  78. package/dist/cjs/util/Construction.d.ts.map +1 -1
  79. package/dist/cjs/util/Construction.js +60 -16
  80. package/dist/cjs/util/Construction.js.map +2 -2
  81. package/dist/cjs/util/DataReadQueue.d.ts +1 -5
  82. package/dist/cjs/util/DataReadQueue.d.ts.map +1 -1
  83. package/dist/cjs/util/DataReadQueue.js +12 -11
  84. package/dist/cjs/util/DataReadQueue.js.map +1 -1
  85. package/dist/cjs/util/FormattedText.d.ts +1 -1
  86. package/dist/cjs/util/FormattedText.d.ts.map +1 -1
  87. package/dist/cjs/util/FormattedText.js +1 -3
  88. package/dist/cjs/util/FormattedText.js.map +1 -1
  89. package/dist/cjs/util/Lifetime.d.ts +97 -0
  90. package/dist/cjs/util/Lifetime.d.ts.map +1 -0
  91. package/dist/cjs/util/Lifetime.js +166 -0
  92. package/dist/cjs/util/Lifetime.js.map +6 -0
  93. package/dist/cjs/util/Multiplex.js +2 -2
  94. package/dist/cjs/util/Multiplex.js.map +1 -1
  95. package/dist/cjs/util/Observable.d.ts +27 -26
  96. package/dist/cjs/util/Observable.d.ts.map +1 -1
  97. package/dist/cjs/util/Observable.js +76 -35
  98. package/dist/cjs/util/Observable.js.map +2 -2
  99. package/dist/cjs/util/String.d.ts +5 -29
  100. package/dist/cjs/util/String.d.ts.map +1 -1
  101. package/dist/cjs/util/String.js +16 -158
  102. package/dist/cjs/util/String.js.map +2 -2
  103. package/dist/cjs/util/identifier-case.d.ts +19 -0
  104. package/dist/cjs/util/identifier-case.d.ts.map +1 -0
  105. package/dist/cjs/util/identifier-case.js +99 -0
  106. package/dist/cjs/util/identifier-case.js.map +6 -0
  107. package/dist/cjs/util/index.d.ts +3 -0
  108. package/dist/cjs/util/index.d.ts.map +1 -1
  109. package/dist/cjs/util/index.js +3 -0
  110. package/dist/cjs/util/index.js.map +1 -1
  111. package/dist/cjs/util/serialize.d.ts +25 -0
  112. package/dist/cjs/util/serialize.d.ts.map +1 -0
  113. package/dist/cjs/util/serialize.js +116 -0
  114. package/dist/cjs/util/serialize.js.map +6 -0
  115. package/dist/esm/MatterError.js +1 -1
  116. package/dist/esm/codec/DerTypes.d.ts.map +1 -1
  117. package/dist/esm/codec/DerTypes.js +2 -1
  118. package/dist/esm/codec/DerTypes.js.map +1 -1
  119. package/dist/esm/environment/Environment.d.ts +4 -1
  120. package/dist/esm/environment/Environment.d.ts.map +1 -1
  121. package/dist/esm/environment/Environment.js +83 -3
  122. package/dist/esm/environment/Environment.js.map +1 -1
  123. package/dist/esm/environment/RuntimeService.d.ts +3 -44
  124. package/dist/esm/environment/RuntimeService.d.ts.map +1 -1
  125. package/dist/esm/environment/RuntimeService.js +65 -10
  126. package/dist/esm/environment/RuntimeService.js.map +2 -2
  127. package/dist/esm/environment/Worker.d.ts +56 -0
  128. package/dist/esm/environment/Worker.d.ts.map +1 -0
  129. package/dist/esm/environment/Worker.js +24 -0
  130. package/dist/esm/environment/Worker.js.map +6 -0
  131. package/dist/esm/environment/index.d.ts +1 -0
  132. package/dist/esm/environment/index.d.ts.map +1 -1
  133. package/dist/esm/environment/index.js +1 -0
  134. package/dist/esm/environment/index.js.map +1 -1
  135. package/dist/esm/log/Diagnostic.d.ts +11 -1
  136. package/dist/esm/log/Diagnostic.d.ts.map +1 -1
  137. package/dist/esm/log/Diagnostic.js +3 -0
  138. package/dist/esm/log/Diagnostic.js.map +1 -1
  139. package/dist/esm/log/DiagnosticPresentation.d.ts +4 -0
  140. package/dist/esm/log/DiagnosticPresentation.d.ts.map +1 -1
  141. package/dist/esm/log/DiagnosticPresentation.js +3 -2
  142. package/dist/esm/log/DiagnosticPresentation.js.map +1 -1
  143. package/dist/esm/log/DiagnosticSource.d.ts +1 -1
  144. package/dist/esm/log/DiagnosticSource.d.ts.map +1 -1
  145. package/dist/esm/log/DiagnosticSource.js +5 -1
  146. package/dist/esm/log/DiagnosticSource.js.map +1 -1
  147. package/dist/esm/log/LogFormat.js +1 -1
  148. package/dist/esm/log/LogFormat.js.map +1 -1
  149. package/dist/esm/net/Channel.d.ts +1 -1
  150. package/dist/esm/net/Channel.d.ts.map +1 -1
  151. package/dist/esm/net/Channel.js +1 -1
  152. package/dist/esm/net/Channel.js.map +1 -1
  153. package/dist/esm/net/mock/MockUdpChannel.d.ts +1 -1
  154. package/dist/esm/net/mock/MockUdpChannel.d.ts.map +1 -1
  155. package/dist/esm/net/mock/NetworkSimulator.d.ts.map +1 -1
  156. package/dist/esm/net/mock/NetworkSimulator.js +2 -1
  157. package/dist/esm/net/mock/NetworkSimulator.js.map +1 -1
  158. package/dist/esm/net/udp/UdpChannel.d.ts +5 -1
  159. package/dist/esm/net/udp/UdpChannel.d.ts.map +1 -1
  160. package/dist/esm/net/udp/UdpMulticastServer.d.ts +4 -6
  161. package/dist/esm/net/udp/UdpMulticastServer.d.ts.map +1 -1
  162. package/dist/esm/net/udp/UdpMulticastServer.js +114 -37
  163. package/dist/esm/net/udp/UdpMulticastServer.js.map +1 -1
  164. package/dist/esm/time/StandardTime.d.ts +38 -0
  165. package/dist/esm/time/StandardTime.d.ts.map +1 -0
  166. package/dist/esm/time/StandardTime.js +152 -0
  167. package/dist/esm/time/StandardTime.js.map +6 -0
  168. package/dist/esm/time/Time.d.ts +4 -23
  169. package/dist/esm/time/Time.d.ts.map +1 -1
  170. package/dist/esm/time/Time.js +12 -88
  171. package/dist/esm/time/Time.js.map +1 -1
  172. package/dist/esm/time/Timestamp.d.ts +5 -0
  173. package/dist/esm/time/Timestamp.d.ts.map +1 -1
  174. package/dist/esm/time/Timestamp.js +4 -0
  175. package/dist/esm/time/Timestamp.js.map +1 -1
  176. package/dist/esm/time/index.d.ts +1 -0
  177. package/dist/esm/time/index.d.ts.map +1 -1
  178. package/dist/esm/time/index.js +1 -0
  179. package/dist/esm/time/index.js.map +1 -1
  180. package/dist/esm/transaction/Transaction.d.ts +12 -4
  181. package/dist/esm/transaction/Transaction.d.ts.map +1 -1
  182. package/dist/esm/transaction/Transaction.js +4 -4
  183. package/dist/esm/transaction/Transaction.js.map +1 -1
  184. package/dist/esm/transaction/Tx.d.ts +2 -1
  185. package/dist/esm/transaction/Tx.d.ts.map +1 -1
  186. package/dist/esm/transaction/Tx.js +92 -6
  187. package/dist/esm/transaction/Tx.js.map +1 -1
  188. package/dist/esm/util/Abort.js +1 -1
  189. package/dist/esm/util/Abort.js.map +1 -1
  190. package/dist/esm/util/Construction.d.ts +2 -1
  191. package/dist/esm/util/Construction.d.ts.map +1 -1
  192. package/dist/esm/util/Construction.js +60 -16
  193. package/dist/esm/util/Construction.js.map +2 -2
  194. package/dist/esm/util/DataReadQueue.d.ts +1 -5
  195. package/dist/esm/util/DataReadQueue.d.ts.map +1 -1
  196. package/dist/esm/util/DataReadQueue.js +12 -11
  197. package/dist/esm/util/DataReadQueue.js.map +1 -1
  198. package/dist/esm/util/FormattedText.d.ts +1 -1
  199. package/dist/esm/util/FormattedText.d.ts.map +1 -1
  200. package/dist/esm/util/FormattedText.js +2 -4
  201. package/dist/esm/util/FormattedText.js.map +1 -1
  202. package/dist/esm/util/Lifetime.d.ts +97 -0
  203. package/dist/esm/util/Lifetime.d.ts.map +1 -0
  204. package/dist/esm/util/Lifetime.js +146 -0
  205. package/dist/esm/util/Lifetime.js.map +6 -0
  206. package/dist/esm/util/Multiplex.js +2 -2
  207. package/dist/esm/util/Multiplex.js.map +1 -1
  208. package/dist/esm/util/Observable.d.ts +27 -26
  209. package/dist/esm/util/Observable.d.ts.map +1 -1
  210. package/dist/esm/util/Observable.js +76 -35
  211. package/dist/esm/util/Observable.js.map +2 -2
  212. package/dist/esm/util/String.d.ts +5 -29
  213. package/dist/esm/util/String.d.ts.map +1 -1
  214. package/dist/esm/util/String.js +16 -158
  215. package/dist/esm/util/String.js.map +2 -2
  216. package/dist/esm/util/identifier-case.d.ts +19 -0
  217. package/dist/esm/util/identifier-case.d.ts.map +1 -0
  218. package/dist/esm/util/identifier-case.js +79 -0
  219. package/dist/esm/util/identifier-case.js.map +6 -0
  220. package/dist/esm/util/index.d.ts +3 -0
  221. package/dist/esm/util/index.d.ts.map +1 -1
  222. package/dist/esm/util/index.js +3 -0
  223. package/dist/esm/util/index.js.map +1 -1
  224. package/dist/esm/util/serialize.d.ts +25 -0
  225. package/dist/esm/util/serialize.d.ts.map +1 -0
  226. package/dist/esm/util/serialize.js +96 -0
  227. package/dist/esm/util/serialize.js.map +6 -0
  228. package/package.json +2 -2
  229. package/src/MatterError.ts +1 -1
  230. package/src/codec/DerTypes.ts +2 -1
  231. package/src/environment/Environment.ts +29 -4
  232. package/src/environment/RuntimeService.ts +19 -55
  233. package/src/environment/Worker.ts +75 -0
  234. package/src/environment/index.ts +1 -0
  235. package/src/log/Diagnostic.ts +15 -1
  236. package/src/log/DiagnosticPresentation.ts +7 -2
  237. package/src/log/DiagnosticSource.ts +5 -1
  238. package/src/log/LogFormat.ts +1 -1
  239. package/src/net/Channel.ts +2 -2
  240. package/src/net/mock/MockUdpChannel.ts +1 -1
  241. package/src/net/mock/NetworkSimulator.ts +2 -1
  242. package/src/net/udp/UdpChannel.ts +6 -1
  243. package/src/net/udp/UdpMulticastServer.ts +72 -34
  244. package/src/time/StandardTime.ts +122 -0
  245. package/src/time/Time.ts +13 -105
  246. package/src/time/Timestamp.ts +8 -0
  247. package/src/time/index.ts +1 -0
  248. package/src/transaction/Transaction.ts +19 -6
  249. package/src/transaction/Tx.ts +49 -2
  250. package/src/util/Abort.ts +1 -1
  251. package/src/util/Construction.ts +76 -18
  252. package/src/util/DataReadQueue.ts +14 -12
  253. package/src/util/FormattedText.ts +1 -1
  254. package/src/util/Lifetime.ts +284 -0
  255. package/src/util/Multiplex.ts +2 -2
  256. package/src/util/Observable.ts +132 -53
  257. package/src/util/String.ts +14 -215
  258. package/src/util/identifier-case.ts +101 -0
  259. package/src/util/index.ts +3 -0
  260. package/src/util/serialize.ts +129 -0
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { Diagnostic } from "#log/Diagnostic.js";
7
8
  import { Duration } from "#time/Duration.js";
8
9
  import { Time, Timer } from "#time/Time.js";
9
10
  import { Instant, Millis, Seconds } from "#time/TimeUnit.js";
@@ -30,10 +31,12 @@ const logger = Logger.get("Observable");
30
31
  * @param payload a list of arguments to be emitted
31
32
  */
32
33
  export interface Observer<T extends any[] = any[], R = void> {
33
- (...payload: T): MaybePromise<R | undefined>;
34
+ (...payload: T): R | undefined;
34
35
  [observant]?: boolean;
35
36
  }
36
37
 
38
+ export interface AsyncObserver<T extends any[] = any[], R = void> extends Observer<T, MaybePromise<R>> {}
39
+
37
40
  /**
38
41
  * A discrete event that may be monitored via callback. Could call it "event" but that could be confused with Matter
39
42
  * cluster events and/or DOM events.
@@ -113,6 +116,11 @@ export interface Observable<T extends any[] = any[], R = void> extends AsyncIter
113
116
  onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
114
117
  ): Promise<TResult1 | TResult2>;
115
118
 
119
+ /**
120
+ * A diagnostic aid; set this to produce detailed logs of emission.
121
+ */
122
+ traceAs: string | undefined;
123
+
116
124
  /**
117
125
  * Observable supports standard "for await (const value of observable").
118
126
  *
@@ -193,6 +201,7 @@ export class BasicObservable<T extends any[] = any[], R = void> implements Obser
193
201
  #handlePromise!: ObserverPromiseHandler;
194
202
  #observers?: Set<Observer<T, R>>;
195
203
  #once?: Set<Observer<T, R>>;
204
+ #instrumentAs?: string;
196
205
 
197
206
  #joinIteration?: () => Promise<Next<T>>;
198
207
  #removeIterator?: () => void;
@@ -207,6 +216,10 @@ export class BasicObservable<T extends any[] = any[], R = void> implements Obser
207
216
  }
208
217
  }
209
218
 
219
+ set traceAs(name: string | undefined) {
220
+ this.#instrumentAs = name;
221
+ }
222
+
210
223
  [Symbol.dispose]() {
211
224
  this.#observers = this.#once = undefined;
212
225
 
@@ -227,7 +240,8 @@ export class BasicObservable<T extends any[] = any[], R = void> implements Obser
227
240
  // Promises handled by emitter
228
241
  this.#handlePromise = promise => promise;
229
242
  } else {
230
- // We log promise errors but do not otherwise track
243
+ // We log promise errors but do not otherwise track. This generally should not be invoked because types
244
+ // should align with this.#isAsync, so observers should not be returning promises
231
245
  this.#handlePromise = (promise, observer) => {
232
246
  promise.catch(error => {
233
247
  let identity: string;
@@ -290,55 +304,103 @@ export class BasicObservable<T extends any[] = any[], R = void> implements Obser
290
304
  }
291
305
 
292
306
  // Iterate over a clone of observers so we do not trigger new observers added during observation
293
- const iterator = [...this.#observers][Symbol.iterator]();
307
+ const observers = [...this.#observers];
308
+
309
+ let nextObserver = 0;
310
+
311
+ const next = () => {
312
+ const observer = observers[nextObserver];
313
+
314
+ if (this.#once?.has(observer)) {
315
+ this.#once.delete(observer);
316
+ this.#observers?.delete(observer);
317
+ }
294
318
 
295
- const emitNext = (previousEmitResult?: R): R | undefined => {
296
- if (previousEmitResult !== undefined) {
297
- return previousEmitResult;
319
+ if (this.#instrumentAs) {
320
+ logger.debug(
321
+ Diagnostic.strong(this.#instrumentAs),
322
+ `invoking #${nextObserver++}`,
323
+ Diagnostic.strong(observer.name || "(anon)"),
324
+ );
298
325
  }
299
326
 
300
- for (let iteration = iterator.next(); !iteration.done; iteration = iterator.next()) {
301
- let result;
327
+ return observer;
328
+ };
302
329
 
303
- const observer = iteration.value;
330
+ let log: undefined | ((observer: Observer<any, any>) => void), done: undefined | (() => void);
331
+ if (this.#instrumentAs) {
332
+ logger.debug(Diagnostic.strong(this.#instrumentAs), "emitting");
304
333
 
305
- try {
306
- result = observer(...payload);
307
- } catch (e) {
308
- this.#handleError(asError(e), observer);
309
- }
334
+ log = (observer: Observer<any, any>) => {
335
+ logger.debug(
336
+ Diagnostic.strong(this.#instrumentAs),
337
+ `invoking #${nextObserver++}`,
338
+ Diagnostic.strong(observer.name || "(anon)"),
339
+ );
340
+ };
310
341
 
311
- if (this.#once?.has(observer)) {
312
- this.#once.delete(observer);
313
- this.#observers?.delete(observer);
314
- }
342
+ done = () => {
343
+ logger.debug(Diagnostic.strong(this.#instrumentAs), "emission complete");
344
+ };
345
+ }
315
346
 
316
- if (result === undefined) {
317
- continue;
318
- }
347
+ // Initially emit using a synchronous loop. When we hit the first promies we convert to an async function
348
+ for (; nextObserver < observers.length; nextObserver++) {
349
+ let result: ReturnType<Observer<T, R>>;
350
+
351
+ let observer = next();
319
352
 
320
- if (MaybePromise.is(result)) {
321
- result = this.#handlePromise(Promise.resolve(result), observer as Observer) as R | undefined;
353
+ try {
354
+ log?.(observer);
355
+ result = observer(...payload);
356
+ } catch (e) {
357
+ this.#handleError(asError(e), observer);
358
+ }
359
+
360
+ if (result === undefined) {
361
+ continue;
362
+ }
322
363
 
323
- if (MaybePromise.is(result)) {
324
- return result.then(result => {
325
- if (result === undefined) {
326
- return emitNext();
364
+ // If observer was async (which we can only conclude after invocation), switch to async emission
365
+ if (MaybePromise.is(result)) {
366
+ const emitAsync = async () => {
367
+ while (true) {
368
+ if (MaybePromise.is(result)) {
369
+ try {
370
+ result = await result;
371
+ } catch (e) {
372
+ this.#handleError(asError(e), observer);
327
373
  }
374
+ }
375
+
376
+ if (result !== undefined) {
328
377
  return result;
329
- }) as R;
330
- }
378
+ }
331
379
 
332
- if (result === undefined) {
333
- continue;
380
+ nextObserver++;
381
+ if (nextObserver >= observers.length) {
382
+ break;
383
+ }
384
+
385
+ observer = next();
386
+
387
+ try {
388
+ result = observer(...payload);
389
+ } catch (e) {
390
+ this.#handleError(asError(e), observer);
391
+ }
334
392
  }
335
- }
336
393
 
337
- return result;
394
+ done?.();
395
+ };
396
+
397
+ return emitAsync() as R | undefined;
338
398
  }
339
- };
340
399
 
341
- return emitNext();
400
+ done?.();
401
+
402
+ return result;
403
+ }
342
404
  }
343
405
 
344
406
  on(observer: Observer<T, R>) {
@@ -592,7 +654,7 @@ function constructAsyncObservableValue(value?: unknown, handleError?: ObserverEr
592
654
  */
593
655
  export class EventEmitter {
594
656
  // True private screws up TS types
595
- private events?: Record<string, Observable | undefined>;
657
+ private events?: Record<string, AsyncObservable | undefined>;
596
658
 
597
659
  emit<This, N extends EventEmitter.NamesOf<This>>(this: This, name: N, ...payload: EventEmitter.PayloadOf<This, N>) {
598
660
  event(this, name).emit(...payload);
@@ -614,7 +676,7 @@ export class EventEmitter {
614
676
  event(this, name).off(handler as any);
615
677
  }
616
678
 
617
- addEvent(name: string, event?: Observable) {
679
+ addEvent(name: string, event?: AsyncObservable) {
618
680
  if (!this.events) {
619
681
  this.events = {};
620
682
  }
@@ -735,6 +797,18 @@ export class ObserverGroup {
735
797
  this.#defaultTarget = target;
736
798
  }
737
799
 
800
+ on<T extends any[], R>(
801
+ observable: Observable<T, R>,
802
+ observer: Observer<ObserverGroup.VarArgs<NoInfer<T>>, NoInfer<R>>,
803
+ target?: {},
804
+ ): void;
805
+
806
+ on<T extends any[], R>(
807
+ observable: AsyncObservable<T, R>,
808
+ observer: AsyncObserver<ObserverGroup.VarArgs<NoInfer<T>>, NoInfer<R>>,
809
+ target?: {},
810
+ ): void;
811
+
738
812
  /**
739
813
  * Add an observer.
740
814
  *
@@ -820,20 +894,23 @@ export namespace ObserverGroup {
820
894
  /**
821
895
  * An {@link Observable} that emits an algorithmically-reduced number of events.
822
896
  */
823
- export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T> implements QuietObservable.State<T> {
897
+ export class QuietObservable<T extends any[] = any[], R extends MaybePromise<void> = void>
898
+ extends BasicObservable<T, R>
899
+ implements QuietObservable.State<T, R>
900
+ {
824
901
  #emitAutomatically = QuietObservable.defaults.emitAutomatically;
825
902
  #suppressionEnabled = QuietObservable.defaults.suppressionEnabled;
826
903
  #minimumEmitInterval = QuietObservable.defaults.minimumEmitInterval;
827
904
  #shouldEmit?: QuietObservable.EmitPredicate<T>;
828
- #source?: Observable<T>;
829
- #sink?: Observable<T>;
830
- #sourceObserver?: Observer<T>;
831
- #sinkObserver?: Observer<T>;
905
+ #source?: Observable<T, R>;
906
+ #sink?: Observable<T, R>;
907
+ #sourceObserver?: Observer<T, R>;
908
+ #sinkObserver?: Observer<T, R>;
832
909
  #deferredPayload?: T;
833
910
  #lastEmitAt?: number;
834
911
  #emitTimer?: Timer;
835
912
 
836
- constructor(config?: QuietObservable.Configuration<T>) {
913
+ constructor(config?: QuietObservable.Configuration<T, R>) {
837
914
  super();
838
915
  if (config) {
839
916
  this.config = config;
@@ -844,7 +921,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
844
921
  return this;
845
922
  }
846
923
 
847
- set config(config: QuietObservable.Configuration<T>) {
924
+ set config(config: QuietObservable.Configuration<T, R>) {
848
925
  const { suppressionEnabled, minimumEmitInterval, emitAutomatically } = config;
849
926
  if (emitAutomatically !== undefined) {
850
927
  this.emitAutomatically = emitAutomatically;
@@ -917,7 +994,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
917
994
  return this.#source;
918
995
  }
919
996
 
920
- set source(source: Observable<T> | undefined) {
997
+ set source(source: Observable<T, R> | undefined) {
921
998
  if (this.#source === source) {
922
999
  return;
923
1000
  }
@@ -936,7 +1013,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
936
1013
  return this.#sink;
937
1014
  }
938
1015
 
939
- set sink(sink: Observable<T> | undefined) {
1016
+ set sink(sink: Observable<T, R> | undefined) {
940
1017
  if (this.#sink === sink) {
941
1018
  return;
942
1019
  }
@@ -967,11 +1044,11 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
967
1044
  return super.isObserved || this.#sink?.isObserved || false;
968
1045
  }
969
1046
 
970
- override isObservedBy(observer: Observer<T>): boolean {
1047
+ override isObservedBy(observer: Observer<T, R>): boolean {
971
1048
  return this.#sink?.isObservedBy(observer) || this.isObservedBy(observer) || false;
972
1049
  }
973
1050
 
974
- override emit(...payload: T) {
1051
+ override emit(...payload: T): R | undefined {
975
1052
  const shouldEmit = this.#shouldEmit?.(...payload);
976
1053
  if (shouldEmit === false) {
977
1054
  return;
@@ -1022,7 +1099,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
1022
1099
  this.#deferredPayload = undefined;
1023
1100
  this.#lastEmitAt = now ?? Time.nowMs;
1024
1101
  this.#stop();
1025
- super.emit(...payload);
1102
+ return super.emit(...payload);
1026
1103
  }
1027
1104
 
1028
1105
  #start(now?: number) {
@@ -1054,7 +1131,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
1054
1131
  }
1055
1132
 
1056
1133
  export namespace QuietObservable {
1057
- export interface State<T extends any[] = any[]> {
1134
+ export interface State<T extends any[] = any[], R extends MaybePromise<void> = void> {
1058
1135
  /**
1059
1136
  * If true this observable will emit within the suppression constraints. If false it will only emit after calls
1060
1137
  * to {@link emitSoon} or {@link emitNow}.
@@ -1074,12 +1151,12 @@ export namespace QuietObservable {
1074
1151
  /**
1075
1152
  * An input observable this observable will automatically observe to produce events.
1076
1153
  */
1077
- source?: Observable<T>;
1154
+ source?: Observable<T, R>;
1078
1155
 
1079
1156
  /**
1080
1157
  * An output observable this observable will automatically emit to whenever it emits.
1081
1158
  */
1082
- sink?: Observable<T>;
1159
+ sink?: Observable<T, R>;
1083
1160
 
1084
1161
  /**
1085
1162
  * A predicate that determine whether a payload should emit.
@@ -1120,7 +1197,9 @@ export namespace QuietObservable {
1120
1197
  (...payload: T): EmitDirective;
1121
1198
  }
1122
1199
 
1123
- export interface Configuration<T extends any[] = any[]> extends Partial<State<T>> {}
1200
+ export interface Configuration<T extends any[] = any[], R extends MaybePromise<void> = void> extends Partial<
1201
+ State<T, R>
1202
+ > {}
1124
1203
 
1125
1204
  export const defaults: State = {
1126
1205
  emitAutomatically: true,
@@ -8,177 +8,6 @@ import { ImplementationError } from "#MatterError.js";
8
8
  import { Bytes } from "./Bytes.js";
9
9
  import { isObject } from "./Type.js";
10
10
 
11
- export function capitalize<T extends string>(text: T) {
12
- return (text[0].toUpperCase() + text.slice(1)) as Capitalize<T>;
13
- }
14
-
15
- /**
16
- * Converts identifiers of the form "foo-bar", "foo_bar", "foo bar", "foo*bar",
17
- * "fooBar" or "FOOBar" into "fooBar" or "FooBar".
18
- */
19
- export function camelize(name: string, upperFirst = false) {
20
- const pieces = new Array<string>();
21
- let pieceStart = 0,
22
- sawUpper = false,
23
- sawLower = false,
24
- i = 0;
25
-
26
- function addPiece(to: number) {
27
- if (pieceStart < to) pieces.push(name.slice(pieceStart, to));
28
- sawLower = sawUpper = false;
29
- }
30
-
31
- for (; i < name.length; i++) {
32
- if (name[i] >= "A" && name[i] <= "Z") {
33
- if (sawLower) {
34
- addPiece(i);
35
- pieceStart = i;
36
- }
37
- sawUpper = true;
38
- continue;
39
- }
40
-
41
- if (name[i] >= "a" && name[i] <= "z") {
42
- if (!sawLower) {
43
- if (sawUpper) {
44
- addPiece(i - 1);
45
- pieceStart = i - 1;
46
- }
47
- }
48
- sawLower = true;
49
- continue;
50
- }
51
-
52
- addPiece(i);
53
-
54
- if ((name[i] >= "0" && name[i] <= "9") || name[i] === "$") {
55
- pieces.push(name[i]);
56
- }
57
-
58
- pieceStart = i + 1;
59
- continue;
60
- }
61
- addPiece(i);
62
-
63
- let didFirst = false;
64
- let result = pieces
65
- .map(piece => {
66
- let firstChar = piece[0];
67
- if (upperFirst || didFirst) {
68
- firstChar = firstChar.toUpperCase();
69
- } else {
70
- firstChar = firstChar.toLowerCase();
71
- didFirst = true;
72
- }
73
- return `${firstChar}${piece.slice(1).toLowerCase()}`;
74
- })
75
- .join("");
76
-
77
- // Special case so "100ths" doesn't become "100Ths" which is formally correct but goofy
78
- result = result.replace(/(\d)Ths/i, "$1ths");
79
-
80
- return result;
81
- }
82
-
83
- /**
84
- * Converts an identifier from CamelCase to snake_case.
85
- */
86
- export function decamelize(name: string, separator = "-") {
87
- const result = Array<string>();
88
- let needSeparator = false;
89
- for (const c of name) {
90
- if (c >= "A" && c <= "Z") {
91
- if (needSeparator) {
92
- result.push(separator);
93
- needSeparator = false;
94
- }
95
- result.push(c.toLowerCase());
96
- } else {
97
- result.push(c);
98
- needSeparator = true;
99
- }
100
- }
101
- return result.join("");
102
- }
103
-
104
- /**
105
- * Like JSON.stringify but targets well-formed JS and is slightly more readable.
106
- */
107
- export function serialize(value: unknown) {
108
- const visited = new Set();
109
-
110
- function asValidKey(key: string) {
111
- if (key.match(/[a-z_$][\w$]*/i)) {
112
- return key;
113
- }
114
- return JSON.stringify(key);
115
- }
116
-
117
- function serializeOne(value: unknown): string | undefined {
118
- if (value === undefined) {
119
- return;
120
- }
121
- if (value === null) {
122
- return "null";
123
- }
124
- if ((value as { [serialize.SERIALIZE](): string })[serialize.SERIALIZE]) {
125
- return (value as { [serialize.SERIALIZE](): string })[serialize.SERIALIZE]();
126
- }
127
- if (typeof value === "function") {
128
- return;
129
- }
130
- if (typeof value === "bigint" || value instanceof BigInt) {
131
- return value.toString();
132
- }
133
- if (typeof value === "number" || value instanceof Number) {
134
- return value.toString();
135
- }
136
- if (typeof value === "string" || value instanceof String) {
137
- return JSON.stringify(value);
138
- }
139
- if (typeof value === "boolean") {
140
- return value ? "true" : "false";
141
- }
142
- if (Bytes.isBytes(value)) {
143
- return Bytes.toHex(value);
144
- }
145
-
146
- // Composite objects after this
147
- if (visited.has(value)) {
148
- return;
149
- }
150
- if ((value as { toJSON(): string }).toJSON) {
151
- value = JSON.parse(JSON.stringify(value));
152
- }
153
-
154
- try {
155
- visited.add(value);
156
-
157
- if (Array.isArray(value)) {
158
- if (value.length) {
159
- return `[ ${value.map(serializeOne).join(", ")} ]`;
160
- }
161
- return "[]";
162
- }
163
-
164
- const entries = Object.entries(value as {})
165
- .map(([k, v]) => [k, serializeOne(v)])
166
- .filter(([_k, v]) => v !== undefined)
167
- .map(([k, v]) => `${asValidKey(k ?? "")}: ${v}`);
168
-
169
- if (!entries.length) {
170
- return "{}";
171
- }
172
-
173
- return `{ ${entries.join(", ")} }`;
174
- } finally {
175
- visited.delete(value);
176
- }
177
- }
178
-
179
- return serializeOne(value);
180
- }
181
-
182
11
  /**
183
12
  * Like {@link JSON.stringify} but with support for additional standard objects.
184
13
  */
@@ -198,50 +27,6 @@ export function asJson(value: unknown, space?: number) {
198
27
  );
199
28
  }
200
29
 
201
- export namespace serialize {
202
- /**
203
- * Custom serialization function key.
204
- */
205
- export const SERIALIZE = Symbol("SERIALIZE");
206
-
207
- /**
208
- * Mark a value as serialized so the serializer just uses its string
209
- * representation.
210
- */
211
- export function asIs(value: any) {
212
- if (typeof value === "string") {
213
- value = new String(value);
214
- }
215
- if (value !== undefined && value !== null) {
216
- value[SERIALIZE] = function () {
217
- return this.toString();
218
- };
219
- }
220
- return value;
221
- }
222
-
223
- /**
224
- * Test whether a value serializes as a structure or a primitive.
225
- */
226
- export function isPrimitive(value: any) {
227
- if (
228
- value === undefined ||
229
- value === null ||
230
- value instanceof Date ||
231
- ArrayBuffer.isView(value) ||
232
- value[SERIALIZE]
233
- ) {
234
- return true;
235
- }
236
-
237
- if (Array.isArray(value)) {
238
- return false;
239
- }
240
-
241
- return typeof value !== "object";
242
- }
243
- }
244
-
245
30
  /**
246
31
  * Create a human readable version of a list of items.
247
32
  */
@@ -326,3 +111,17 @@ export function serializeToJs(value: unknown) {
326
111
  parts.push("}");
327
112
  return parts.join("");
328
113
  }
114
+
115
+ export namespace hex {
116
+ export function fixed(value: number | bigint, width: number) {
117
+ return value.toString(16).padStart(width, "0");
118
+ }
119
+
120
+ export function byte(value: number | bigint) {
121
+ return fixed(value, 2);
122
+ }
123
+
124
+ export function word(value: number | bigint) {
125
+ return fixed(value, 4);
126
+ }
127
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ /**
8
+ * Make first character uppercase.
9
+ */
10
+ export function capitalize<T extends string>(text: T) {
11
+ return (text[0].toUpperCase() + text.slice(1)) as Capitalize<T>;
12
+ }
13
+
14
+ /**
15
+ * Converts identifiers of the form "foo-bar", "foo_bar", "foo bar", "foo*bar",
16
+ * "fooBar" or "FOOBar" into "fooBar" or "FooBar".
17
+ */
18
+ export function camelize(name: string, upperFirst = false) {
19
+ const pieces = new Array<string>();
20
+ let pieceStart = 0,
21
+ sawUpper = false,
22
+ sawLower = false,
23
+ i = 0;
24
+
25
+ function addPiece(to: number) {
26
+ if (pieceStart < to) pieces.push(name.slice(pieceStart, to));
27
+ sawLower = sawUpper = false;
28
+ }
29
+
30
+ for (; i < name.length; i++) {
31
+ if (name[i] >= "A" && name[i] <= "Z") {
32
+ if (sawLower) {
33
+ addPiece(i);
34
+ pieceStart = i;
35
+ }
36
+ sawUpper = true;
37
+ continue;
38
+ }
39
+
40
+ if (name[i] >= "a" && name[i] <= "z") {
41
+ if (!sawLower) {
42
+ if (sawUpper) {
43
+ addPiece(i - 1);
44
+ pieceStart = i - 1;
45
+ }
46
+ }
47
+ sawLower = true;
48
+ continue;
49
+ }
50
+
51
+ addPiece(i);
52
+
53
+ if ((name[i] >= "0" && name[i] <= "9") || name[i] === "$") {
54
+ pieces.push(name[i]);
55
+ }
56
+
57
+ pieceStart = i + 1;
58
+ continue;
59
+ }
60
+ addPiece(i);
61
+
62
+ let didFirst = false;
63
+ let result = pieces
64
+ .map(piece => {
65
+ let firstChar = piece[0];
66
+ if (upperFirst || didFirst) {
67
+ firstChar = firstChar.toUpperCase();
68
+ } else {
69
+ firstChar = firstChar.toLowerCase();
70
+ didFirst = true;
71
+ }
72
+ return `${firstChar}${piece.slice(1).toLowerCase()}`;
73
+ })
74
+ .join("");
75
+
76
+ // Special case so "100ths" doesn't become "100Ths" which is formally correct but goofy
77
+ result = result.replace(/(\d)Ths/i, "$1ths");
78
+
79
+ return result;
80
+ }
81
+
82
+ /**
83
+ * Converts an identifier from CamelCase to snake_case.
84
+ */
85
+ export function decamelize(name: string, separator = "-") {
86
+ const result = Array<string>();
87
+ let needSeparator = false;
88
+ for (const c of name) {
89
+ if (c >= "A" && c <= "Z") {
90
+ if (needSeparator) {
91
+ result.push(separator);
92
+ needSeparator = false;
93
+ }
94
+ result.push(c.toLowerCase());
95
+ } else {
96
+ result.push(c);
97
+ needSeparator = true;
98
+ }
99
+ }
100
+ return result.join("");
101
+ }