All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
.broadcast.once and .broadcast.onceBy. Works just like .once or .onceBy, but sends the request to multiple nodes just like .broadcast..broadcast{.once,.onceBy,}.orThrow(): aggregate method that throws if any node failed and returns the array of results otherwise.nodes property in the third ("tools") argument of procedure implementations, containing the set of all available node IDs.Client#destroy to terminate workers and disconnect event listeners.Client:options.nodeIds to specify the list of node IDs to use instead of generating them automatically.RequestCancelledError instead of just a Error. Useful to specifically catch cancellation errors.onceBy, destroy). The complete list is available on the exported constant RESERVED_PROCEDURE_NAMES.BREAKING: Hooks now receive a single object argument instead of two positional arguments. This greatly helps with type narrowing if you check for the procedure name.
Before:
Client(procedures, {
hooks: {
success(procedure, data) {
if (procedure === "getUser") {
// `data` is not narrowed down to the type returned by `getUser` :(
}
},
},
});
After:
Client(procedures, {
hooks: {
success({ procedure, data }) {
if (procedure === "getUser") {
// `data` is now correctly narrowed down to the type returned by `getUser` :)
}
},
},
});
To update, simply change your hook implementations to use a single object argument and destructure (or not) the properties you need from it.
Type of procedure implementations' input argument was incorrectly specified as Schema.InferInput<InputSchema>, it is now Schema.InferOutput<InputSchema>, as the server receives the transformed input object.
For example, if you had the following procedure declaration:
export const procedures = {
...
foo: {
input: type('string.date.parse').
...
}
}
Before, the implementation would show this type
server.foo((input, onProgress) => {
// ^?: string
...
})
It now correctly shows
server.foo((input, onProgress) => {
// ^?: Date
...
})
BREAKING: The logger options in the third argument of procedure implementations has been removed. Just use console.log instead:
- server.myProcedure(async (args, onProgress, { logger }) => {
+ server.myProcedure(async (args, onProgress) => {
- logger.info("Doing something")
+ console.log("Doing something")
});
Functions and types for internal things have been removed from the public API. The only remaining API surface is the one documented in the README (Server, Client and their related types).
BREAKING: Client#(method name).broadcast:onProgress now receives a map of nodeId to progress values, which makes aggregating individual nodes' progress data into a single coherent progress value easier:
import { sum } from "./utils";
await client.thing.broadcast(67, (ps) =>
console.log((sum(ps.values()) / ps.size) * 100 + "% done"),
);
nodeId, the ID of the node executing the request, in the tools argument.Client:option.nodes, to control the number of nodes (worker instances) to spin upClient#(method name).broadcastClient:options.worker is now either a string (path to the worker's source code) or a class, not an instanceClient:options.worker is set, the Client now launches by default navigator.hardwareConcurrency nodes (worker instances) and dispatches requests to them in a balanced way.Client:options.localStorage to define a Server-accessible polyfilled localStorage with data (See #32)Server#start is now asynchronous, but does not take an argument anymore.Server:options.worker is correctly typedClient:options.restartListener, mostly for testing purposesProcedureImplementation:tools.loggerServer#start's self parameter now correctly accepts both Window and Worker contexts.autotransfer property on procedure declarations