Improve configurability and initialization
Adds two new features:
- A generalized schema-driven "cast" that converts arbitrary JS values to the form described by schema
- Configuration-driven endpoint initialization with that may set the initial value of any state property
Implementation details:
- Moves the old metatype "cast" implementation to FieldValue. This is used to create the FieldValues that serve as default values and is not a general purpose cast.
- Adds new Metatype.cast object that contains a "cast" function for each metatype. These functions convert the input value to the appropriate JS type for the corresponding metatype, or throw an error.
- Adds a fourth utility function to RootSupervisor, "cast". This generated function converts the input value to the proper JS type implied by schema. It is designed to take semi-formal input such as may be input via environment variables, shell or UI. It converts the input to match the JS types implied by the schema or throws an error.
- Adds a new "EndpointVariableService". This service extracts state values from VariableService into an object that may be used as initial state values.
- Wires EndpointVariableService into behavior initialization. This makes all state values "configurable" such that initial values may come from environment variables, command line arguments or configuration file.
The comments in EndpointVariableService.ts detail the naming convention for mapping variables to state fields.
Makes a number of changes to construction infrastructure:
- Renames AsyncConstruction to Construction.
- Adds "ready" and "closed" promises to construction interface. These trigger when the subject is initialized and closed, respectively, and throw if the subject crashes.
- Awaiting the construction object directly still throws a "crashed dependency" error so dependents receive logical stack traces and do not repeat the primary error.
- asyncNew now awaits construction.ready and thus throws the primary error if construction fails.
- Errors in AsyncConstruction listeners are logged but no longer crash the component.
- Deferred construction is now formalized and effected via [Construction.construct] method on subject. This allows derivatives to override construction as they might a constructor.
- Destruction is optional but formalized and implemented via [Construction.destruct] method on subject.
- Adds support for error.cause and AggregateError.errors to logging formatter.
The construction changes support various updates to node and endpoint logic to make error handling cleaner:
- Node.start is now asynchronous and throws root cause if construction or network initialization crashes.
- Node.bringOnline is now an alias for Node.start and deprecated.
- Renames "tree ready" to "parts ready". Old corresponding method names are deprecated.
- Behavior errors now throw with a cause and node initialization throws an AggregateError with details for each behavior.
- Endpoint.create fails via throw of root cause if behavior initialization crashes.
- Endpoints may now be marked as "essential". Only essential endpoints crash the node if they do not initialize cleanly.
- Endpoint.add fails via throw if initialization of essential endpoints fails and the endpoint is not added.
- Part initialization errors are still logged but initialization of the parent fails if any parts fail. The failure is normal error that lists the failed endpoints in the message.
- Various other streamlining and removal of dead code.
- Fixes a bug related to PASE sessions that would trigger redundant server resets.
- Transitions of node state are now logged more comprehensively and uniformly.
- Adds more test coverage for these code paths.
- Some node initialization logic from ServerNode applicable to ClientNode is moved to Node.
Also includes some tooling improvements:
- Also includes a new "--trace-unhandled" option to matter-test that displays the source line that generated a promise when a rejection is unhandled. Node by itself only displays the source of the error.
- Adds support for properly interleaving log messages with status updates.
- Ongoing activity now has a spinner if asynchronous.