diff --git a/src/common/BaseStateManager.js b/src/common/BaseStateManager.js index 4c42af1f..d5c5e53b 100644 --- a/src/common/BaseStateManager.js +++ b/src/common/BaseStateManager.js @@ -29,12 +29,20 @@ export const kStateManagerClient = Symbol('soundworks:state-manager-client'); /** + * Callback executed when a state is created on the network. + * * @callback stateManagerObserveCallback * @async * @param {string} schemaName - name of the schema * @param {number} stateId - id of the state * @param {number} nodeId - id of the node that created the state */ +/** + * Callback to execute in order to remove a {@link stateManagerObserveCallback} + * from the list of observer. + * + * @callback stateManagerDeleteObserveCallback + */ /** @private */ class BaseStateManager { @@ -50,7 +58,7 @@ class BaseStateManager { this[kStateManagerClient] = null; } - /** @private */ + /** @private */ #filterObserve(observedSchemaName, schemaName, creatorId, options) { let filter = true; // schema name filter filer @@ -137,7 +145,6 @@ class BaseStateManager { // we don't call another callback that may have been registered earlier. const observeInfos = this.#observeRequestCallbacks.get(reqId); const [observedSchemaName, callback, options] = observeInfos; - // move observeInfos from `_observeRequestCallbacks` to `_observeListeners` // to guarantee order of execution, @see not in `.observe` this.#observeRequestCallbacks.delete(reqId); @@ -157,7 +164,6 @@ class BaseStateManager { const unsubscribe = () => { this.#observeListeners.delete(observeInfos); - // no more listeners, we can stop receiving notifications from the server if (this.#observeListeners.size === 0) { this[kStateManagerClient].transport.emit(UNOBSERVE_NOTIFICATION); @@ -214,7 +220,7 @@ class BaseStateManager { * @param {String} schemaName - Name of the schema as given on registration * (cf. ServerStateManager) * @example - * const schema = await client.stateManager.getSchema('my-schema'); + * const schema = await client.stateManager.getSchema('my-class'); */ async getSchema(schemaName) { if (this.#cachedSchemas.has(schemaName)) { @@ -238,7 +244,7 @@ class BaseStateManager { * @param {Object.} [initValues={}] - Default values for the state. * @returns {Promise} * @example - * const state = await client.stateManager.create('my-schema'); + * const state = await client.stateManager.create('my-class'); */ async create(schemaName, initValues = {}) { return new Promise((resolve, reject) => { @@ -249,24 +255,48 @@ class BaseStateManager { } /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class'); */ /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName - Name of the schema * @param {number} stateId - Id of the state + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class', stateId); */ /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName - Name of the schema * @param {string[]} filter - List of parameters of interest + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class', ['some-param']); */ /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName - Name of the schema * @param {number} stateId - Id of the state * @param {string[]} filter - List of parameters of interest + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class', stateId, ['some-param']); */ /** * Attach to an existing `SharedState` instance. @@ -286,7 +316,7 @@ class BaseStateManager { * @returns {Promise} * * @example - * const state = await client.stateManager.attach('my-schema'); + * const state = await client.stateManager.attach('my-class'); */ async attach(schemaName, stateIdOrFilter = null, filter = null) { let stateId = null; @@ -331,17 +361,15 @@ class BaseStateManager { /** * Observe all the `SharedState` instances that are created on the network. - * This can be usefull for clients with some controller role that might want to track - * the state of all other clients of the application, to monitor them and/or take - * control over them from a single point. * * Notes: - * - The order of execution is not guaranted between nodes, i.e. an state attached - * in the `observe` callback could be created before the `async create` method resolves. + * - The order of execution is not guaranted between nodes, i.e. a state attached + * in the `observe` callback can be instantiated before the `async create` method + * resolves on the creator node. * - Filtering, i.e. `observedSchemaName` and `options.excludeLocal` are handled * on the node side, the server just notify all state creation activity and * the node executes the given callbacks according to the different filter rules. - * Such strategy allows to share the observe notifications between all observers. + * Such strategy allows to simply share the observe notifications between all observers. * * Alternative signatures: * - `stateManager.observe(callback)` @@ -356,23 +384,19 @@ class BaseStateManager { * @param {object} options - Options. * @param {boolean} [options.excludeLocal = false] - If set to true, exclude states * created locally, i.e. by the same node, from the collection. - * @returns {Promise} - Returns a Promise that resolves when the given + * @returns {Promise} - Returns a Promise that resolves when the given * callback as been executed on each existing states. The promise value is a * function which allows to stop observing the states on the network. * * @example * client.stateManager.observe(async (schemaName, stateId) => { * if (schemaName === 'something') { - * const state = await this[kStateManagerClient].stateManager.attach(schemaName, stateId); - * console.log(state.getValues()); + * const attached = await client.stateManager.attach(schemaName, stateId); + * console.log(attached.getValues()); * } * }); */ - // note: all filtering is done only on client-side as it is really more simple to - // handle this way and the network overhead is very low for observe notifications: - // i.e. schemaName, stateId, nodeId async observe(...args) { - const defaultOptions = { excludeLocal: false, }; diff --git a/types/client/index.d.ts b/types/client/index.d.ts index 2562147c..bdd4c51e 100644 --- a/types/client/index.d.ts +++ b/types/client/index.d.ts @@ -1,5 +1,5 @@ -export { default as ClientContext } from "./ClientContext.js"; export { default as Client } from "./Client.js"; +export { default as ClientContext } from "./ClientContext.js"; /** * Configuration object for a client running in a browser runtime. */ @@ -9,14 +9,14 @@ export type ClientConfig = { */ role: string; /** - * - Application configration object. + * - Application configuration object. */ app?: { name?: string; author?: string; }; /** - * - Environment configration object. + * - Environment configuration object. */ env: { useHttps: boolean; diff --git a/types/common/BaseStateManager.d.ts b/types/common/BaseStateManager.d.ts index 6676058f..993aaec3 100644 --- a/types/common/BaseStateManager.d.ts +++ b/types/common/BaseStateManager.d.ts @@ -18,7 +18,7 @@ declare class BaseStateManager { * @param {String} schemaName - Name of the schema as given on registration * (cf. ServerStateManager) * @example - * const schema = await client.stateManager.getSchema('my-schema'); + * const schema = await client.stateManager.getSchema('my-class'); */ getSchema(schemaName: string): Promise; /** @@ -29,35 +29,59 @@ declare class BaseStateManager { * @param {Object.} [initValues={}] - Default values for the state. * @returns {Promise} * @example - * const state = await client.stateManager.create('my-schema'); + * const state = await client.stateManager.create('my-class'); */ create(schemaName: string, initValues?: { [x: string]: any; }): Promise; /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class'); */ - attach(schemaName: string): any; + attach(schemaName: string): Promise; /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName - Name of the schema * @param {number} stateId - Id of the state + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class', stateId); */ - attach(schemaName: string, stateId: number): any; + attach(schemaName: string, stateId: number): Promise; /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName - Name of the schema * @param {string[]} filter - List of parameters of interest + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class', ['some-param']); */ - attach(schemaName: string, filter: string[]): any; + attach(schemaName: string, filter: string[]): Promise; /** + * Attach to an existing `SharedState` instance. + * * @overload * @param {string} schemaName - Name of the schema * @param {number} stateId - Id of the state * @param {string[]} filter - List of parameters of interest + * @returns {Promise} + * + * @example + * const state = await client.stateManager.attach('my-class', stateId, ['some-param']); */ - attach(schemaName: string, stateId: number, filter: string[]): any; + attach(schemaName: string, stateId: number, filter: string[]): Promise; /** * Observe all the `SharedState` instances that are created on the network. * This can be usefull for clients with some controller role that might want to track diff --git a/types/server/index.d.ts b/types/server/index.d.ts index 120c42b8..d999bfaa 100644 --- a/types/server/index.d.ts +++ b/types/server/index.d.ts @@ -5,7 +5,7 @@ export { default as ServerContext } from "./ServerContext.js"; */ export type ServerConfig = { /** - * - Application configration object. + * - Application configuration object. */ app?: { clients: object; @@ -13,7 +13,7 @@ export type ServerConfig = { author?: string; }; /** - * - Environment configration object. + * - Environment configuration object. */ env?: { useHttps: boolean;