### Execute a BPMN Process Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md This example shows how to instantiate and execute a BPMN process using the Engine. It includes a simple process definition with a start event, an exclusive gateway, and end events. ```javascript import { Engine } from 'bpmn-engine'; const id = Math.floor(Math.random() * 10000); const source = ` true `; const engine = new Engine({ name: 'execution example', source, variables: { id, }, }); engine.execute((err, execution) => { console.log('Execution completed with id', execution.environment.variables.id); }); ``` -------------------------------- ### engine.execute([options[, callback]]) Source: https://context7.com/paed01/bpmn-engine/llms.txt Starts process execution by parsing BPMN sources, instantiating definitions, and executing all processes. It supports both Promise-based and Node.js-style callback usage. ```APIDOC ## engine.execute([options[, callback]]) — Start process execution Parses pending BPMN sources, instantiates definitions, and begins executing all executable processes. Options passed here override the engine-level options for this run. Returns a `Promise` and also accepts a Node.js-style callback. ### Parameters - **options** (object) - Optional. Options for this execution run. - **listener** (EventEmitter) - Optional. An EventEmitter instance to listen for engine events. - **variables** (object) - Optional. Variables to use for this execution. - **callback** (function) - Optional. A Node.js-style callback function `(err, execution)`. ### Returns - **Promise** - A promise that resolves with the execution object upon completion. ### Request Example ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ name: 'order-engine', source }); const listener = new EventEmitter(); listener.once('activity.wait', (elementApi) => { console.log(`Waiting at: ${elementApi.id}`); elementApi.signal({ approved: true }); }); // callback style engine.execute({ listener, variables: { orderId: 'ORD-42' } }, (err, execution) => { if (err) throw err; console.log('completed:', execution.environment.output); }); // -- OR -- promise style const execution = await engine.execute({ listener }); await engine.waitFor('end'); console.log('done, variables:', execution.environment.variables); ``` ``` -------------------------------- ### Start Process Execution with bpmn-engine Source: https://context7.com/paed01/bpmn-engine/llms.txt Initiate process execution using the `execute` method, supporting both Promise and callback styles. An EventEmitter can be used to listen for process events. ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ name: 'order-engine', source }); const listener = new EventEmitter(); // Signal the user task as soon as it waits listener.once('activity.wait', (elementApi) => { console.log(`Waiting at: ${elementApi.id}`); elementApi.signal({ approved: true }); }); // callback style engine.execute({ listener, variables: { orderId: 'ORD-42' } }, (err, execution) => { if (err) throw err; console.log('completed:', execution.environment.output); }); // -- OR -- promise style const execution = await engine.execute({ listener }); await engine.waitFor('end'); console.log('done, variables:', execution.environment.variables); ``` -------------------------------- ### Execution Listener Setup Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Set up an EventEmitter listener to react to BPMN activity events like 'activity.enter' and 'activity.wait'. This allows for custom logic during process execution. ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ name: 'first listener', source, }); const listener = new EventEmitter(); listener.on('activity.enter', (elementApi, engineApi) => { console.log(`${elementApi.type} <${elementApi.id}> of ${engineApi.name} is entered`); }); listener.on('activity.wait', (elemntApi, instance) => { console.log(`${elemntApi.type} <${elemntApi.id}> of ${instance.name} is waiting for input`); elemntApi.signal('don´t wait for me'); }); engine.execute({ listener, }); ``` -------------------------------- ### Script Task Example Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md Illustrates a script task that executes JavaScript code, including making HTTP requests using the 'bent' module. The 'next' callback must be invoked to complete the task. Services like 'get' and 'set' need to be provided. ```javascript import { Engine } from 'bpmn-engine'; import bent from 'bent'; const source = ` `; const engine = new Engine({ name: 'script task example', source, }); engine.execute({ variables: { scriptTaskCompleted: false, }, services: { get: bent('json'), set, }, }); engine.on('end', (execution) => { console.log('Output:', execution.environment.output); }); function set(activity, name, value) { activity.logger.debug('set', name, 'to', value); } ``` -------------------------------- ### Retrieve All BPMN Definitions Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Retrieve all loaded BPMN definitions from the engine. This example shows how to access the definition ID and its processes after fetching them. ```javascript import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ source, }); engine.getDefinitions().then((definitions) => { console.log('Loaded', definitions[0].id); console.log('The definition comes with process', definitions[0].getProcesses()[0].id); }); ``` -------------------------------- ### Execution Services Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Demonstrates how to expose and use services within a BPMN process. The `environment.services` object allows access to functions like `get` which can be used to fetch external resources. ```APIDOC ## Execution `services` A service is a function exposed on `environment.services`. ```javascript import { Engine } from 'bpmn-engine'; import bent from 'bent'; const source = ` `; const engine = new Engine({ name: 'services doc', source, }); engine.execute( { services: { get: bent('json'), }, }, (err, engineApi) => { if (err) throw err; console.log('completed', engineApi.name, engineApi.environment.variables); } ); ``` ``` -------------------------------- ### Exclusive Gateway Example Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md Demonstrates an exclusive gateway that routes process flow based on conditions evaluated against process variables. Ensure input variable is set before execution. ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` 50); ]]> `; const engine = new Engine({ name: 'exclusive gateway example', source, }); const listener = new EventEmitter(); listener.on('activity.start', (api) => { if (api.id === 'end1') throw new Error(`<${api.id}> was not supposed to be taken, check your input`); if (api.id === 'end2') console.log(`<${api.id}> correct decision was taken`); }); engine.execute({ listener, variables: { input: 51, }, }); engine.on('end', () => { console.log('completed'); }); ``` -------------------------------- ### User Task Example Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md Demonstrates a user task that pauses process execution until signaled. The 'wait' event listener is used to signal the task completion with specific data. Ensure the listener is set up to handle the 'wait' event. ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ name: 'user task example 1', source, }); const listener = new EventEmitter(); listener.once('wait', (elementApi) => { elementApi.signal({ sirname: 'von Rosen', }); }); listener.on('activity.end', (elementApi, engineApi) => { if (elementApi.content.output) engineApi.environment.output[elementApi.id] = elementApi.content.output; }); engine.execute( { listener, }, (err, execution) => { if (err) throw err; console.log(`User sirname is ${execution.environment.output.task.sirname}`); } ); ``` -------------------------------- ### Extend Form Behavior with Camunda Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md Extends BPMN form behavior using Camunda model extensions. This example shows how to define and interact with form fields within a BPMN process. Ensure 'camunda-bpmn-moddle' is installed. ```javascript import { EventEmitter } from 'node:events'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; const camunda = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json'); const source = ` `; const engine = new Engine({ name: 'Pending game', source, moddleOptions: { camunda, }, extensions: { camunda: camundaExt, }, }); const listener = new EventEmitter(); listener.on('wait', (elementApi) => { if (elementApi.content.form) { console.log(elementApi.content.form); return elementApi.signal( elementApi.content.form.fields.reduce((result, field) => { if (field.label === 'Surname') result[field.id] = 'von Rosen'; if (field.label === 'Given name') result[field.id] = 'Sebastian'; return result; }, {}) ); } elementApi.signal(); }); engine.execute({ listener, }); function camundaExt(activity) { if (!activity.behaviour.extensionElements) return; let form; for (const extn of activity.behaviour.extensionElements.values) { if (extn.$type === 'camunda:FormData') { form = { fields: extn.fields.map((f) => ({ ...f })), }; } } activity.on('enter', () => { activity.broker.publish('format', 'run.form', { form }); }); } ``` -------------------------------- ### Add BPMN Definition Source Dynamically Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Add a BPMN definition source to the engine at runtime. This example demonstrates using `addSource` with a dynamically generated source context and executing the process with a listener. ```javascript import { EventEmitter } from 'node:events'; import BpmnModdle from 'bpmn-moddle'; import * as elements from 'bpmn-elements'; import { Engine } from 'bpmn-engine'; import Serializer, { TypeResolver } from 'moddle-context-serializer'; const engine = new Engine({ name: 'add source', }); (async function IIFE(source) { const sourceContext = await getContext(source); engine.addSource({ sourceContext, }); const listener = new EventEmitter(); listener.once('activity.wait', (api) => { console.log(api.name, 'is waiting'); api.signal(); }); await engine.execute({ listener, }); await engine.waitFor('end'); })(` `); async function getContext(source, options) { const moddleContext = await getModdleContext(source, options); if (moddleContext.warnings) { moddleContext.warnings.forEach(({ error, message, element, property }) => { if (error) return console.error(message); console.error(`<${element.id}> ${property}:`, message); }); } const types = TypeResolver({ ...elements, ...options?.elements, }); return Serializer(moddleContext, types, options?.extendFn); } function getModdleContext(source, options) { const bpmnModdle = new BpmnModdle(options); return bpmnModdle.fromXML(source); } ``` -------------------------------- ### Execute BPMN with Custom Services Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Execute a BPMN process and provide custom services that can be invoked from within script tasks. The `get` service is used here to fetch data from a URL. ```javascript import { Engine } from 'bpmn-engine'; import bent from 'bent'; const source = ` `; const engine = new Engine({ name: 'services doc', source, }); engine.execute( { services: { get: bent('json'), }, }, (err, engineApi) => { if (err) throw err; console.log('completed', engineApi.name, engineApi.environment.variables); } ); ``` -------------------------------- ### Persist State on Events using Listeners Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md Subscribe to engine and activity events using a listener to persist the execution state. This example publishes state updates to a message broker. ```javascript import { randomUUID } from 'node:crypto'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; import { EventEmitter } from 'ndoe:events'; import { publish } from './dbbroker.js'; import { getSourceSync, getAllowedServices, getExtensions } from './utils.js'; const camundaModdle = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json') function ignite(executionId, options = {}) { const { name, settings } = options; const listener = new EventEmitter(); listener.on('activity.wait', (_, execution) => { return publishEvent('bpmn.state.update', {state: execution.getState()}); }); listener.on('activity.end', (_, execution) => { return publishEvent('bpmn.state.update', {state: execution.getState()}); }); listener.on('activity.timer', (api, execution) => { return publishEvent('bpmn.state.expires', { expires: new Date(api.content.startedAt + api.content.timeout), state: execution.getState(), }); }); listener.on('activity.timeout', (_, execution) => { return publishEvent('bpmn.state.expired', { expired: new Date(), state: execution.getState(), }); }); const engine = BpmnEngine({ moddleOptions: { camunda, }, ...options, settings: { ...settings, executionId, enableDummyService: false, } }); engine.once('end', () => { publishEvent('bpmn.completed'); }); engine.once('error', (err) => { publishEvent('bpmn.error', {message: err.message, error: err}); }); return { engine, listener }; function publishEvent(routingKey, message) { publish('events', routingKey, { name, executionId, ...message, }); } } const {engine} = ignite(randomUUID(), { name: 'persisted engine #1', source: getSourceSync('./mother-of-all.bpmn'), services: getAllowedServices(), extensions: getExtensions(), }); engine.execute(); ``` -------------------------------- ### Execute Service Task with Expression Function Call Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md This example shows how to invoke a service task using an expression that calls a function. The function itself returns another function, which is then executed by the engine. This pattern is useful for dynamic service invocation or when services require specific initialization. ```javascript import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ name: 'service task example 3', source, }); engine.execute({ services: { getService(defaultScope) { if (!defaultScope.content.id === 'serviceTask') return; return (executionContext, callback) => { callback(null, executionContext.environment.variables.input); }; }, }, variables: { input: 1, }, extensions: { saveToEnvironmentOutput(activity, { environment }) { activity.on('end', (api) => { environment.output[api.id] = api.content.output; }); }, }, }); engine.once('end', (execution) => { console.log(execution.name, execution.environment.output); }); ``` -------------------------------- ### Handle Human Performer and Potential Owner Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md This snippet demonstrates how to publish events for human involvement in BPMN processes. It configures a user task to identify human performers and potential owners, publishing their details for external handling. Ensure 'camunda-bpmn-moddle' is installed. ```javascript import { EventEmitter } from 'node:events'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; const camunda = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json'); const source = ` ${environment.services.getUser()} user(pal), group(users) `; function humanInvolvement(activity) { if (!activity.behaviour.resources || !activity.behaviour.resources.length) return; const humanPerformer = activity.behaviour.resources.find((resource) => resource.type === 'bpmn:HumanPerformer'); const potentialOwner = activity.behaviour.resources.find((resource) => resource.type === 'bpmn:PotentialOwner'); activity.on('enter', (api) => { activity.broker.publish('format', 'run.call.humans', { humanPerformer: api.resolveExpression(humanPerformer.expression), potentialOwner: api.resolveExpression(potentialOwner.expression), }); }); activity.on('wait', (api) => { api.owner.broker.publish('event', 'activity.call', { ...api.content }); }); } const listener = new EventEmitter(); const engine = new Engine({ name: 'call humans', source, moddleOptions: { camunda, }, services: { getUser() { return 'pal'; }, }, extensions: { humanInvolvement, }, }); listener.on('activity.call', (api) => { console.log('Make call to', api.content.humanPerformer); console.log('Owner:', api.content.potentialOwner); api.signal(); }); engine.execute({ listener }, (err, instance) => { if (err) throw err; console.log(instance.name, 'completed'); }); ``` -------------------------------- ### Custom extensions for augmenting element behavior Source: https://context7.com/paed01/bpmn-engine/llms.txt Allows hooking into the activity lifecycle to read vendor-specific attributes, publish custom events, or inject data into the execution context. This example demonstrates injecting form data for a user task. ```javascript import { EventEmitter } from 'node:events'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; const camunda = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json'); const source = ` `; function camundaFormExtension(activity) { if (!activity.behaviour.extensionElements) return; let form; for (const ext of activity.behaviour.extensionElements.values) { if (ext.$type === 'camunda:FormData') { form = { fields: ext.fields.map((f) => ({ id: f.id, label: f.label, type: f.type })) }; } } if (!form) return; // Inject form data into the run.enter message so it appears in content activity.on('enter', () => { activity.broker.publish('format', 'run.form', { form }); }); } const engine = new Engine({ source, moddleOptions: { camunda }, extensions: { camundaForm: camundaFormExtension } }); const listener = new EventEmitter(); listener.once('activity.wait', (api) => { console.log('Form fields:', api.content.form.fields); // [{ id: 'email', label: 'Email', type: 'string' }, { id: 'age', label: 'Age', type: 'long' }] // Fill form and signal api.signal({ email: 'alice@example.com', age: 30 }); }); engine.execute({ listener }, (err, execution) => { if (err) throw err; console.log('Output:', execution.environment.output.formTask); }); ``` -------------------------------- ### new Engine([options]) Source: https://context7.com/paed01/bpmn-engine/llms.txt Creates a new Engine instance. This constructor can be called with or without the `new` keyword and accepts an options object for configuration. ```APIDOC ## new Engine([options]) — Create an engine instance Creates a new Engine. Can be called with or without `new`. Accepts an options object that configures the BPMN source, environment variables, services, extensions, logger, moddle options, and more. ### Parameters - **options** (object) - Optional. Configuration options for the engine. - **name** (string) - Optional. Name of the workflow. - **source** (Buffer | string) - Required. BPMN XML content. - **moddleOptions** (object) - Optional. Options for the moddle parser, e.g., to enable Camunda extensions. - **variables** (object) - Optional. Initial environment variables for the workflow. - **services** (object) - Optional. An object mapping service names to their implementation functions. - **extensions** (object) - Optional. Behaviour extensions for BPMN elements. - **Logger** (function) - Optional. A factory function for creating custom loggers. - **scripts** (object) - Optional. Handler for executing scripts. ### Request Example ```javascript import fs from 'node:fs'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; const camunda = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json'); const engine = new Engine({ name: 'my-workflow', source: fs.readFileSync('./process.bpmn'), // BPMN XML as Buffer or string moddleOptions: { camunda }, // enable Camunda extension attributes variables: { orderId: 'ORD-001' }, // initial environment variables services: { fetchOrder: async (scope, callback) => { const order = await db.getOrder(scope.environment.variables.orderId); callback(null, order); }, }, extensions: {}, Logger: (prefix) => console, scripts: undefined, }); console.log(engine.name); console.log(engine.state); console.log(engine.activityStatus); ``` ``` -------------------------------- ### Serialise execution state with engine.getState() Source: https://context7.com/paed01/bpmn-engine/llms.txt Use `engine.getState()` to asynchronously get a plain JSON-serialisable object representing the engine's complete state. This is useful for persisting state to a database or file. The example demonstrates capturing state when a user task is encountered. ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ source, name: 'stateful-engine' }); const listener = new EventEmitter(); listener.once('activity.wait', async (api) => { const state = await engine.getState(); // state shape: // { // name: 'stateful-engine', // engineVersion: '25.0.1', // state: 'running', // stopped: false, // environment: { variables: {}, settings: {}, ... }, // definitions: [{ id: 'Definition_...', state: 'running', ... }] // } console.log('state.state:', state.state); // 'running' console.log('engineVersion:', state.engineVersion); // '25.0.1' await require('fs/promises').writeFile('/tmp/state.json', JSON.stringify(state)); api.signal(); }); await engine.execute({ listener }); ``` -------------------------------- ### Engine Instantiation Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Creates a new BPMN Engine instance with optional configuration options. The options allow customization of various aspects like script handling, element mapping, expression management, logging, and more. ```APIDOC ## `new Engine([options])` Creates a new Engine. Arguments: - `options`: Optional options, passed to [environment](https://github.com/paed01/bpmn-elements/blob/master/docs/Environment.md): - `disableDummyScript`: optional boolean to disable dummy script supplied to empty ScriptTask - `elements`: optional object with element type mapping override - `expressions`: optional override [expressions](#expressions) handler - `extendFn`: optional extend [serializer](https://github.com/paed01/moddle-context-serializer/blob/master/API.md) function - `Logger`: optional [Logger factory](https://github.com/paed01/bpmn-elements/blob/master/docs/Environment.md#logger), defaults to [debug](https://www.npmjs.com/package/debug) logger - `moddleContext`: optional BPMN 2.0 definition moddle context - `moddleOptions`: optional bpmn-moddle options to be passed to bpmn-moddle - `name`: optional name of engine, - `scripts`: optional [inline script handler](https://github.com/paed01/bpmn-elements/blob/master/docs/Scripts.md), defaults to nodejs vm module handling, i.e. JavaScript - `source`: optional BPMN 2.0 definition source as string - `sourceContext`: optional serialized context supplied by [moddle-context-serializer](https://github.com/paed01/moddle-context-serializer) - `timers`: [Timers instance](https://github.com/paed01/bpmn-elements/blob/master/docs/Timers.md) - `typeResolver`: optional type resolver function passed to moddle-context-serializer - `extensions`: optional behavior [extensions](https://github.com/paed01/bpmn-elements/blob/master/docs/Extension.md) Returns: - `name`: engine name - `broker`: engine [broker](https://github.com/paed01/smqp) - `state`: engine state - `activityStatus`: string, activity status - `executing`: at least one activity is executing, e.g. a service task making a asynchronous request - `timer`: at least one activity is waiting for a timer to complete, usually only TimerEventDefinition's - `wait`: at least one activity is waiting for a signal of some sort, e.g. user tasks, intermediate catch events, etc - `idle`: idle, no activities are running - `stopped`: boolean stopped - `execution`: current engine execution - `environment`: engine [environment](https://github.com/paed01/bpmn-elements/blob/master/docs/Environment.md) - `logger`: engine logger - `async execute()`: execute definition - `async getDefinitionById()`: get definition by id - `async getDefinitions()`: get all definitions - `async getState()`: get execution serialized state - `recover()`: recover from state - `async resume()`: resume execution - `async stop()`: stop execution - `waitFor()`: wait for engine events, returns Promise ```javascript import fs from 'node:fs'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; const camunda = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json'); const engine = new Engine({ name: 'mother of all', source: fs.readFileSync('./test/resources/mother-of-all.bpmn'), moddleOptions: { camunda, }, }); ``` ``` -------------------------------- ### Create and Configure BPMN Engine Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Instantiate a new BPMN Engine with custom options, including loading a BPMN definition from a file and configuring moddle options for Camunda extensions. ```javascript import fs from 'node:fs'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { Engine } from 'bpmn-engine'; const camunda = createRequire(fileURLToPath(import.meta.url))('camunda-bpmn-moddle/resources/camunda.json'); const engine = new Engine({ name: 'mother of all', source: fs.readFileSync('./test/resources/mother-of-all.bpmn'), moddleOptions: { camunda, }, }); ``` -------------------------------- ### Definition Management Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Provides methods to retrieve BPMN definitions by ID or get all available definitions. ```APIDOC ## `async getDefinitionById(id)` Retrieves a BPMN definition by its unique identifier. Arguments: - `id` (string): The ID of the definition to retrieve. Returns: A Promise that resolves with the definition object. ``` ```APIDOC ## `getDefinitions()` Retrieves all available BPMN definitions. Returns: An object containing all definitions. ``` -------------------------------- ### Filter Debug Output Source: https://github.com/paed01/bpmn-engine/blob/master/README.md Use the DEBUG environment variable to filter debug messages. Examples are provided for different operating systems. ```sh DEBUG=*scripttask*,*:error:* ``` ```powershell $env:DEBUG='bpmn-engine:*' ``` ```powershell $env:DEBUG='' ``` -------------------------------- ### Listen for BPMN Events Source: https://github.com/paed01/bpmn-engine/blob/master/docs/Examples.md Demonstrates how to listen for various events emitted by the BPMN engine, such as 'wait' for tasks and 'flow.take' for sequence flows. It also shows how to signal a user task with output data. ```javascript import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const source = ` `; const engine = new Engine({ name: 'listen example', source, }); const listener = new EventEmitter(); listener.once('wait', (task) => { task.signal({ ioSpecification: { dataOutputs: [ { id: 'userInput', value: 'von Rosen', }, ], }, }); }); listener.on('flow.take', (flow) => { console.log(`flow <${flow.id}> was taken`); }); engine.once('end', (execution) => { console.log(execution.environment.variables); console.log(`User sirname is ${execution.environment.output.data.inputFromUser}`); }); engine.execute( { listener, }, (err) => { if (err) throw err; } ); ``` -------------------------------- ### Get Engine State and Save Source: https://github.com/paed01/bpmn-engine/blob/master/docs/API.md Asynchronously retrieves the current state of a running BPMN execution and saves it to a file. This is useful for debugging or persistence. ```javascript import fs from 'node:fs/promises'; import { EventEmitter } from 'node:events'; import { Engine } from 'bpmn-engine'; const processXml = ` `; const engine = new Engine({ source: processXml, }); const listener = new EventEmitter(); let state; listener.once('activity.wait', async () => { state = await engine.getState(); await fs.writeFile('./tmp/some-random-id.json', JSON.stringify(state, null, 2)); }); listener.once('activity.start', async () => { state = await engine.getState(); await fs.writeFile('./tmp/some-random-id.json', JSON.stringify(state, null, 2)); }); engine.execute({ listener, }); ```