@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matter/general",
3
- "version": "0.16.0-alpha.0-20251203-aaf94bca8",
3
+ "version": "0.16.0-alpha.0-20251207-37e501b18",
4
4
  "description": "Non-Matter support for Matter.js",
5
5
  "keywords": [
6
6
  "iot",
@@ -36,7 +36,7 @@
36
36
  "@noble/curves": "^2.0.1"
37
37
  },
38
38
  "devDependencies": {
39
- "@matter/testing": "0.16.0-alpha.0-20251203-aaf94bca8"
39
+ "@matter/testing": "0.16.0-alpha.0-20251207-37e501b18"
40
40
  },
41
41
  "files": [
42
42
  "dist/**/*",
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { NodeJsStyleInspectable } from "#log/NodeJsStyleInspectable.js";
8
8
  import type { MaybePromise } from "#util/Promises.js";
9
- import { decamelize } from "#util/String.js";
9
+ import { decamelize } from "#util/identifier-case.js";
10
10
  import { errorOf } from "./util/Error.js";
11
11
 
12
12
  const codes = new WeakMap<{}, string>();
@@ -6,6 +6,7 @@
6
6
 
7
7
  import { InternalError } from "#MatterError.js";
8
8
  import { Bytes } from "#util/Bytes.js";
9
+ import { hex } from "#util/String.js";
9
10
  import {
10
11
  ContextTagged,
11
12
  ContextTaggedBytes,
@@ -112,7 +113,7 @@ export namespace X520 {
112
113
  * Also registers the OID in the reverse lookup map immediately.
113
114
  */
114
115
  const GenericString_X520 = (id: number, fieldName: string) => {
115
- const oidHex = `5504${id.toString(16).padStart(2, "0")}`;
116
+ const oidHex = `5504${hex.byte(id)}`;
116
117
  // Register in reverse lookup map immediately at function creation time
117
118
  if (OID_TO_FIELD_MAP[oidHex] !== undefined && OID_TO_FIELD_MAP[oidHex] !== fieldName) {
118
119
  throw new InternalError(
@@ -7,8 +7,10 @@
7
7
  import { ServiceProvider } from "#environment/ServiceProvider.js";
8
8
  import { SharedEnvironmentServices } from "#environment/SharedEnvironmentServices.js";
9
9
  import { SharedServicesManager } from "#environment/SharedServicesManager.js";
10
+ import { Diagnostic } from "#log/Diagnostic.js";
10
11
  import { InternalError } from "#MatterError.js";
11
12
  import { Instant } from "#time/TimeUnit.js";
13
+ import { Lifetime } from "#util/Lifetime.js";
12
14
  import { MaybePromise } from "#util/Promises.js";
13
15
  import { DiagnosticSource } from "../log/DiagnosticSource.js";
14
16
  import { Logger } from "../log/Logger.js";
@@ -48,10 +50,11 @@ const logger = Logger.get("Environment");
48
50
  *
49
51
  * TODO - could remove global singletons by moving here
50
52
  */
51
- export class Environment implements ServiceProvider {
53
+ export class Environment implements ServiceProvider, Lifetime.Owner {
52
54
  #services?: Map<Environmental.ServiceType, Environmental.Service | null>;
53
55
  #name: string;
54
56
  #parent?: Environment;
57
+ #lifetime: Lifetime;
55
58
  #added = Observable<[type: Environmental.ServiceType, instance: {}]>();
56
59
  #deleted = Observable<[type: Environmental.ServiceType, instance: {}]>();
57
60
  #serviceEvents = new Map<Environmental.ServiceType, Environmental.ServiceEvents<any>>();
@@ -59,6 +62,11 @@ export class Environment implements ServiceProvider {
59
62
  constructor(name: string, parent?: Environment) {
60
63
  this.#name = name;
61
64
  this.#parent = parent;
65
+ this.#lifetime = (parent ?? Lifetime.process).join(Diagnostic.strong(name), "environment");
66
+ }
67
+
68
+ join(...name: unknown[]) {
69
+ return this.#lifetime?.join(...name);
62
70
  }
63
71
 
64
72
  /**
@@ -295,11 +303,21 @@ export class Environment implements ServiceProvider {
295
303
  added(this, existing);
296
304
  }
297
305
 
298
- events.added.on(service => this.runtime.add(() => added(this, service)));
306
+ events.added.on(service =>
307
+ this.runtime.add(async () => {
308
+ using _adding = this.join(`adding ${type.name}`);
309
+ await added(this, service);
310
+ }),
311
+ );
299
312
  }
300
313
 
301
314
  if (deleted) {
302
- events.deleted.on(service => this.runtime.add(() => deleted(this, service)));
315
+ events.deleted.on(service =>
316
+ this.runtime.add(async () => {
317
+ using _deleting = this.join(`adding ${type.name}`);
318
+ await deleted(this, service);
319
+ }),
320
+ );
303
321
  }
304
322
  }
305
323
 
@@ -316,6 +334,8 @@ export class Environment implements ServiceProvider {
316
334
  * Set the default environment.
317
335
  */
318
336
  static set default(env: Environment) {
337
+ global[Symbol.dispose]();
338
+
319
339
  global = env;
320
340
 
321
341
  env.vars.use(() => {
@@ -347,7 +367,7 @@ export class Environment implements ServiceProvider {
347
367
  * Display tasks that supply diagnostics.
348
368
  */
349
369
  diagnose() {
350
- Time.getTimer("Diagnostics", Instant, () => {
370
+ Time.getTimer("diagnostics", Instant, () => {
351
371
  try {
352
372
  logger.notice("Diagnostics follow", DiagnosticSource);
353
373
  } catch (e) {
@@ -359,6 +379,11 @@ export class Environment implements ServiceProvider {
359
379
  protected loadVariables(): Record<string, any> {
360
380
  return {};
361
381
  }
382
+
383
+ [Symbol.dispose]() {
384
+ // Currently this is just a method for terminating our lifetime
385
+ this.#lifetime[Symbol.dispose]();
386
+ }
362
387
  }
363
388
 
364
389
  let global = new Environment("default");
@@ -4,26 +4,29 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { DiagnosticPresentation } from "#log/DiagnosticPresentation.js";
7
8
  import { asError } from "#util/Error.js";
9
+ import { Lifetime } from "#util/Lifetime.js";
8
10
  import { Diagnostic } from "../log/Diagnostic.js";
9
11
  import { DiagnosticSource } from "../log/DiagnosticSource.js";
10
12
  import { Logger } from "../log/Logger.js";
11
- import { Construction, type Constructable } from "../util/Construction.js";
12
- import { Cancellable, Destructable, Lifecycle } from "../util/Lifecycle.js";
13
- import { Multiplex } from "../util/Multiplex.js";
13
+ import { type Constructable } from "../util/Construction.js";
14
+ import { type Destructable, Lifecycle } from "../util/Lifecycle.js";
14
15
  import { Observable } from "../util/Observable.js";
15
16
  import type { Environment } from "./Environment.js";
16
17
  import { Environmental } from "./Environmental.js";
18
+ import type { Worker } from "./Worker.js";
17
19
 
18
20
  const logger = Logger.get("Runtime");
19
21
 
20
22
  /**
21
23
  * Handles lifecycle management of other components.
22
24
  */
23
- export class RuntimeService implements Multiplex {
25
+ export class RuntimeService {
24
26
  #env: Environment;
25
- #workers = new Set<RuntimeService.Worker>();
26
- #cancelled = new Set<RuntimeService.Worker>();
27
+ #lifetime: Lifetime;
28
+ #workers = new Set<Worker>();
29
+ #cancelled = new Set<Worker>();
27
30
  #workerDeleted = Observable<[]>();
28
31
  #canceled = false;
29
32
  #started = Observable<[]>();
@@ -32,6 +35,7 @@ export class RuntimeService implements Multiplex {
32
35
 
33
36
  constructor(environment: Environment) {
34
37
  this.#env = environment;
38
+ this.#lifetime = this.#env.join("runtime");
35
39
  environment.set(RuntimeService, this);
36
40
  DiagnosticSource.add(this);
37
41
  }
@@ -74,7 +78,9 @@ export class RuntimeService implements Multiplex {
74
78
  if (worker.then) {
75
79
  Promise.resolve(worker)
76
80
  .catch(error => this.#crash(error))
77
- .finally(() => this.delete(worker));
81
+ .finally(() => {
82
+ this.delete(worker);
83
+ });
78
84
  return;
79
85
  }
80
86
 
@@ -97,7 +103,7 @@ export class RuntimeService implements Multiplex {
97
103
  /**
98
104
  * Remove a worker.
99
105
  */
100
- delete(worker: RuntimeService.Worker) {
106
+ delete(worker: Worker) {
101
107
  if (!this.#workers.has(worker)) {
102
108
  return;
103
109
  }
@@ -197,6 +203,8 @@ export class RuntimeService implements Multiplex {
197
203
  }
198
204
 
199
205
  async close() {
206
+ using _closing = this.#lifetime.closing();
207
+
200
208
  this.cancel();
201
209
  await this.inactive;
202
210
  this.#env.delete(RuntimeService, this);
@@ -208,9 +216,9 @@ export class RuntimeService implements Multiplex {
208
216
  }
209
217
 
210
218
  get [Diagnostic.value]() {
211
- return Diagnostic.node("🛠", "Workers", {
219
+ return Diagnostic.node("⚙️", "Workers", {
212
220
  children: [...this.#workers].map(worker => {
213
- let diagnostic: unknown = worker[RuntimeService.label];
221
+ let diagnostic: unknown = worker[DiagnosticPresentation.name];
214
222
 
215
223
  if (diagnostic === undefined) {
216
224
  diagnostic = Diagnostic.valueOf(worker);
@@ -225,7 +233,7 @@ export class RuntimeService implements Multiplex {
225
233
  });
226
234
  }
227
235
 
228
- #cancelWorker(worker: RuntimeService.Worker) {
236
+ #cancelWorker(worker: Worker) {
229
237
  if (this.#cancelled.has(worker)) {
230
238
  return;
231
239
  }
@@ -281,50 +289,6 @@ export class RuntimeService implements Multiplex {
281
289
  }
282
290
 
283
291
  export namespace RuntimeService {
284
- export const label = Symbol("label");
285
-
286
- /**
287
- * The runtime tracks individual discrete tasks as "workers".
288
- *
289
- * The state of the runtime is dependent on installed workers. Any JS object may be a worker but the runtime's
290
- * interaction with workers varies as documented here.
291
- *
292
- * If a worker is a {@link PromiseLike} the runtime will delete and/or destroy it on completion.
293
- */
294
- export interface Worker extends Partial<PromiseLike<any>>, Partial<Cancellable>, Partial<Destructable> {
295
- /**
296
- * If the worker supports {@link Construction}, the runtime will monitor the worker's lifecycle:
297
- *
298
- * - If the worker crashed (e.g. experiences an error during initialization) the runtime will cancel all
299
- * workers and exit
300
- *
301
- * - If the worker is destroyed the runtime deletes it from the set of known workers
302
- */
303
- construction?: Construction<any>;
304
-
305
- /**
306
- * If the worker supports {@link Symbol.asyncDispose} the runtime will invoke when the worker is no longer
307
- * needed. This happens if:
308
- *
309
- * - The worker is a {@link PromiseLike} that resolves
310
- *
311
- * - The worker's {@link construction} status changed as noted above
312
- *
313
- * - The runtime is canceled via {@link RuntimeService.cancel}
314
- */
315
- [Symbol.asyncDispose]?: () => void | Promise<void>;
316
-
317
- /**
318
- * Workers may implement {@link Symbol.dispose} to handle disposal. Works the same as the async equivalent.
319
- */
320
- [Symbol.dispose]?: () => void;
321
-
322
- /**
323
- * If label is present, it will be presented in diagnostics. This takes precedence over [Diagnostic.value].
324
- */
325
- [label]?: unknown;
326
- }
327
-
328
292
  /**
329
293
  * A function that initiates work.
330
294
  */
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { DiagnosticPresentation } from "#log/DiagnosticPresentation.js";
8
+ import { Construction } from "#util/Construction.js";
9
+ import { Cancellable, Destructable } from "#util/Lifecycle.js";
10
+ import { Lifetime } from "#util/Lifetime.js";
11
+ import { MaybePromise } from "#util/Promises.js";
12
+
13
+ /**
14
+ * An self-describing object that adheres to matter.js conventions for lifecycle and diagnostics.
15
+ *
16
+ * It's best to track workers as part of other components, but workers with no other home may be installed into
17
+ * {@link RuntimeService}. The state of the runtime is dependent on installed workers. Any JS object may be a worker
18
+ * but the runtime's interaction with workers varies as documented here.
19
+ */
20
+ export interface Worker extends Partial<PromiseLike<any>>, Partial<Cancellable>, Partial<Destructable> {
21
+ /**
22
+ * If the worker supports {@link Construction}, the runtime will monitor the worker's lifecycle:
23
+ *
24
+ * - If the worker crashed (e.g. experiences an error during initialization) the runtime will cancel all
25
+ * workers and exit
26
+ *
27
+ * - If the worker is destroyed the runtime deletes it from the set of known workers
28
+ */
29
+ construction?: Construction<any>;
30
+
31
+ /**
32
+ * If the worker supports {@link Symbol.asyncDispose} the runtime will invoke when the worker is no longer
33
+ * needed. This happens if:
34
+ *
35
+ * - The worker is a {@link PromiseLike} that resolves
36
+ *
37
+ * - The worker's {@link construction} status changed as noted above
38
+ *
39
+ * - The runtime is canceled via {@link RuntimeService.cancel}
40
+ */
41
+ [Symbol.asyncDispose]?: () => void | Promise<void>;
42
+
43
+ /**
44
+ * Workers may implement {@link Symbol.dispose} to handle disposal. Works the same as the async equivalent.
45
+ */
46
+ [Symbol.dispose]?: () => void;
47
+
48
+ /**
49
+ * If label is present, it will be presented in diagnostics. This takes precedence over [Diagnostic.value].
50
+ */
51
+ [DiagnosticPresentation.name]?: unknown;
52
+ }
53
+
54
+ /**
55
+ * Create a {@link Worker} with {@link name} and lifetime that ends when {@link done} resolves.
56
+ */
57
+ export function Worker({
58
+ name,
59
+ done,
60
+ lifetime,
61
+ }: {
62
+ name: string;
63
+ done?: MaybePromise<void>;
64
+ lifetime?: Lifetime.Owner;
65
+ }): Worker | undefined {
66
+ if (!done) {
67
+ return;
68
+ }
69
+
70
+ const ongoing = (lifetime ?? Lifetime.process).join(name);
71
+ const worker = Promise.resolve(done).finally(() => ongoing[Symbol.dispose]()) as Worker;
72
+ worker[DiagnosticPresentation.name] = name;
73
+
74
+ return worker;
75
+ }
@@ -10,3 +10,4 @@ export * from "./RuntimeService.js";
10
10
  export * from "./ServiceBundle.js";
11
11
  export * from "./SharedEnvironmentServices.js";
12
12
  export * from "./VariableService.js";
13
+ export * from "./Worker.js";
@@ -165,6 +165,16 @@ export namespace Diagnostic {
165
165
 
166
166
  /**
167
167
  * Create a value identifying the source of a diagnostic event.
168
+ *
169
+ * Conventions for via:
170
+ *
171
+ * - Use padded hex for random(ish) fixed-width numbers
172
+ *
173
+ * - If there is an ID associated with a name, associate using "name#id"
174
+ *
175
+ * - If there are subcomponents, associate with ":" (e.g. "sessionId:exchangeId:messageId")
176
+ *
177
+ * - Use "/" as a separator if there are distinct subcomponents commonly delineated with ":"
168
178
  */
169
179
  export function via(value: string) {
170
180
  if (Diagnostic.presentationOf(value)) {
@@ -193,7 +203,7 @@ export namespace Diagnostic {
193
203
  * A node in a diagnostic tree. Top-level diagnostic sources registered with DiagnosticSource should present as
194
204
  * nodes.
195
205
  */
196
- export function node(icon: string, label: unknown, detail: { self?: unknown; children?: unknown[] }) {
206
+ export function node(icon: string, label: unknown, detail: { self?: unknown; children?: Iterable<unknown> }) {
197
207
  const result = [icon, Diagnostic.strong(label)] as unknown[];
198
208
  if (detail?.self !== undefined) {
199
209
  result.push(detail.self);
@@ -302,6 +312,10 @@ export namespace Diagnostic {
302
312
  toString() {
303
313
  return Duration.format(this.time);
304
314
  },
315
+
316
+ get [Diagnostic.value]() {
317
+ return this.toString();
318
+ },
305
319
  };
306
320
  }
307
321
 
@@ -68,10 +68,15 @@ export namespace DiagnosticPresentation {
68
68
  /**
69
69
  * Property name allowing objects to indicate their preferred presentation.
70
70
  */
71
- export const presentation: unique symbol = Symbol("presentation");
71
+ export const presentation: unique symbol = Symbol.for("matter.diagnostic.presentation");
72
72
 
73
73
  /**
74
74
  * Property name that redirects diagnostic presentation.
75
75
  */
76
- export const value: unique symbol = Symbol.for("value");
76
+ export const value: unique symbol = Symbol.for("matter.diagnostic.value");
77
+
78
+ /**
79
+ * Property name that assigns a diagnostic segment as the name of an object.
80
+ */
81
+ export const name: unique symbol = Symbol.for("matter.diagnostic.name");
77
82
  }
@@ -27,6 +27,10 @@ export const DiagnosticSource = {
27
27
  },
28
28
 
29
29
  get [DiagnosticPresentation.value]() {
30
- return sources;
30
+ const diagnostic = [];
31
+ for (const source of sources) {
32
+ diagnostic.push("", source);
33
+ }
34
+ return diagnostic;
31
35
  },
32
36
  };
@@ -4,10 +4,10 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { serialize } from "#util/serialize.js";
7
8
  import { ImplementationError, InternalError, MatterError } from "../MatterError.js";
8
9
  import { Bytes } from "../util/Bytes.js";
9
10
  import { Lifecycle } from "../util/Lifecycle.js";
10
- import { serialize } from "../util/String.js";
11
11
  import { isObject } from "../util/Type.js";
12
12
  import { Diagnostic } from "./Diagnostic.js";
13
13
  import { LogLevel } from "./LogLevel.js";
@@ -38,6 +38,6 @@ export interface IpNetworkChannel<T> extends Channel<T> {
38
38
  networkAddress: ServerAddressUdp;
39
39
  }
40
40
 
41
- export function isIpNetworkChannel<T>(channel: Channel<T>): channel is IpNetworkChannel<T> {
42
- return isObject((channel as IpNetworkChannel<T>).networkAddress);
41
+ export function isIpNetworkChannel<T>(channel?: Channel<T>): channel is IpNetworkChannel<T> {
42
+ return isObject((channel as IpNetworkChannel<T> | undefined)?.networkAddress);
43
43
  }
@@ -8,7 +8,7 @@ import { ChannelType } from "#net/Channel.js";
8
8
  import { Bytes } from "#util/Bytes.js";
9
9
  import { NetworkError } from "../Network.js";
10
10
  import { MAX_UDP_MESSAGE_SIZE, UdpChannel, UdpChannelOptions } from "../udp/UdpChannel.js";
11
- import { MockNetwork } from "./MockNetwork.js";
11
+ import type { MockNetwork } from "./MockNetwork.js";
12
12
  import { MockRouter } from "./MockRouter.js";
13
13
 
14
14
  export class MockUdpChannel implements UdpChannel {
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { Bytes } from "#util/Bytes.js";
8
+ import { hex } from "#util/String.js";
8
9
  import { MockNetwork } from "./MockNetwork.js";
9
10
  import { MockRouter } from "./MockRouter.js";
10
11
 
@@ -12,7 +13,7 @@ export class NetworkSimulator {
12
13
  readonly router = MockRouter();
13
14
 
14
15
  addHost(lastIdentifierByte: number) {
15
- const byte = lastIdentifierByte.toString(16).padStart(2, "0");
16
+ const byte = hex.byte(lastIdentifierByte);
16
17
  return new MockNetwork(this, `00:11:22:33:44:${byte}`, [
17
18
  `1111:2222:3333:4444:5555:6666:7777:88${byte}`,
18
19
  `10.10.10.${lastIdentifierByte}`,
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Bytes, MaybePromise } from "#util/index.js";
7
+ import { Bytes, Lifetime, MaybePromise } from "#util/index.js";
8
8
  import { ChannelType } from "../Channel.js";
9
9
  import { ConnectionlessTransport } from "../ConnectionlessTransport.js";
10
10
 
@@ -46,6 +46,11 @@ export interface UdpChannelOptions {
46
46
  */
47
47
  netInterface?: string;
48
48
 
49
+ /**
50
+ * Owning lifetime of the channel.
51
+ */
52
+ lifetime?: Lifetime;
53
+
49
54
  /**
50
55
  * Address+port pairs are normally may normally only be opened by a single socket. This allows shared access to a
51
56
  * port.