import { NodeDefinition, NodeLike, Params, StatefulGraphNode, StatefulNodeType } from '../../types/graph'; import { ErrorNodeDefinition } from './error'; import { OkNodeDefinition } from './ok'; /** * An instance of the [[fromPromise]] node. * See the [[fromPromise]] documentation to find out more. */ export interface FromPromiseNode extends StatefulGraphNode<'fromPromise', FromPromiseNodeProperties, FromPromiseNodeState, FromPromiseNodeData> { } /** * A definition of the [[fromPromise]] node. * See the [[fromPromise]] documentation to find out more. */ export interface FromPromiseNodeDefinition extends NodeDefinition<'fromPromise', FromPromiseNodeProperties, FromPromiseNodeState, FromPromiseNodeData> { } export declare type GenericFactory = ((params: Params) => Promise); export declare type SetterFactory = ((params: Params, value: any) => Promise); export interface FromPromiseNodeProperties { clear: GenericFactory | undefined; get: GenericFactory | undefined; set: SetterFactory | undefined; } export interface FromPromiseNodeState { currentValue: NodeDefinition | undefined; pendingUpdate: Promise | undefined; updateError: ErrorNodeDefinition | undefined; } export interface FromPromiseNodeData { isSubscribed: boolean; pendingGet: Promise | undefined; } /** * Implementation of the [[fromPromise]]. * See the [[fromPromise]] documentation for more information. */ export declare const FromPromiseNodeType: StatefulNodeType<'fromPromise', FromPromiseNodeProperties, FromPromiseNodeState>; export interface FromPromiseOperations { clear?: GenericFactory; get?: GenericFactory; set?: SetterFactory; } /** * Creates a new instance of [[fromPromise]] node, which is a type of [[NodeDefinition]] useful when integrating asynchronous code with muster. * This node can be used when making API requests from within muster code. These requests may retrieve or update data * from a remote service. * * The [[fromPromise]] allows for handling `set` requests through a [set](_nodes_graph_set_.html#set) as well as the `clear` requests through a [clear]] node.. * See the "**Handling set requests**" example for more information. * * * @example **Basic promise node** * ```ts * import muster, { fromPromise, ref } from '@dws/muster'; * * const app = muster({ * asyncName: fromPromise(() => Promise.resolve('async name')), * }); * * // Resolving with 'await' * const awaitName = await app.resolve(ref('asyncName')); * // awaitName === 'async name' * * // Resolving with streams * let streamName = 'initial'; * app.resolve(ref('asyncName')).subscribe((name) => { * // name === 'async name' * // streamName === 'initial' * streamName = name; * // streamName === 'async name' * }); * // streamName === 'initial' * ``` * This example demonstrates the asynchronous nature of [[fromPromise]]. When the ref is * requested with `await` it forces the code to wait for the [[fromPromise]] to emit a value. * Internally Muster requires every [[NodeDefinition]] to emit its value synchronously. To get around * that, [[fromPromise]] initially returns a [[pending]], then an updated value when the * promise resolves. * * The reason why in the example code the [[pending]] isn't emitted to the "outside * world" is that these values are internal to muster and are filtered out before returning the * response. * * * @example **Promise factory params** * ```js * import muster, { fromPromise, match, ref, toNode, types } from '@dws/muster'; * * const app = muster({ * user: { * [match(types.string, 'id')]: fromPromise(({ id }) => * // You could make a request to an API endpoint here... * Promise.resolve(toNode({ * id: id, * name: `User ${id}`, * })), * ), * }, * }); * * const user1Name = await app.resolve(ref('user', '1', 'name')); * // user1Name === 'User 1' * * const user2Name = await app.resolve(ref('user', '2', 'name')); * // user2Name === 'User 2' * ``` * This example demonstrates a real-world case of requesting user data based on their ID. Note the * promise factory in [[fromPromise]] receives a parameter with one field: `id`. * * * @example **Implementing set promise factory** * ```ts * import muster, { fromPromise, ref, set } from '@dws/muster'; * * const userSettings = { * homepage: 'https://www.db.com', * }; * * const app = muster({ * homepage: fromPromise({ * // Make an API request instead * get: () => Promise.resolve(userSettings.homepage), * // Make an API request instead * set: (params, newValue) => new Promise((resolve) => { * userSettings.homepage = newValue; * resolve(); * }), * }), * }); * * let setTriggered = false; * * // Subscribe to the 'homepage' * console.log('Requesting homepage'); * app.resolve(ref('homepage')).subscribe((homepage) => { * console.log(`Homepage: ${homepage}`); * !setTriggered && triggerSet(); * }); * * async function triggerSet() { * setTriggered = true; * console.log('Setting homepage'); * await app.resolve(set('homepage', 'https://wwww.github.com')); * } * * // Console output: * // Requesting homepage * // Homepage: https://www.db.com * // Setting homepage * // Homepage: https://www.github.com * ``` * * * @example **Implementing a clear promise factory** * ```javascript * import muster, { clear, fromPromise, ref, set, toNode } from '@dws/muster'; * * const mockSettings = { * homepage: 'https://some.url', * }; * * const app = muster({ * settings: fromPromise({ * // Use a real API instead of mockSettings * get: () => Promise.resolve(toNode(mockSettings)), * set: (params, settings) => { * mockSettings = settings; * return Promise.resolve(ok()); * }, * clear: () => { * mockSettings = { homepage: undefined }; * return Promise.resolve(ok()); * }, * }), * }); * * app.resolve(query(ref('settings'), { homepage: true })).subscribe((settings) => { * console.log('Settings: ', settings); * }); * * console.log('Changing settings'); * await app.resolve(set(ref('settings'), { homepage: 'https://other.url' })); * * console.log('Clearing settings'); * await app.resolve(clear(ref('settings'))); * * // Console output: * // Settings: { homepage: 'https://some.url' } * // Changing settings * // Settings: { homepage: 'https://other.url' } * // Clearing settings * // Settings: { homepage: undefined } * ``` */ export declare function fromPromise(definition: GenericFactory | FromPromiseOperations, setFactory?: SetterFactory): FromPromiseNodeDefinition; export declare function isFromPromiseNodeDefinition(value: NodeDefinition): value is FromPromiseNodeDefinition;