Registry / web-framework / machine-as-action

machine-as-action

JSON →
library10.3.1jsnpmunverified

machine-as-action is a Node.js utility designed to bridge the gap between 'machines' – a pattern for encapsulating reusable business logic – and standard HTTP/WebSocket request-response cycles. It allows developers to define a machine and then wrap it with `asAction` to automatically handle incoming request parameters as machine inputs and map machine exits to various HTTP response types, including JSON data, rendered views, or redirects. The current stable version is 10.3.1, though recent release notes show significant changes around version 7.x. While there isn't a strict, rapid release cadence apparent from the provided data, updates have been made. Its primary differentiator lies in its deep integration with the 'machine' pattern, providing a structured and convention-over-configuration approach to expose API endpoints, particularly useful in frameworks like Sails.js where machines are a core architectural component. It offers granular control over response status codes and view rendering based on the outcome of a machine's execution, aiming to reduce boilerplate in controller logic.

npm install machine-as-action
INSTALL
IMPORT
SIG · MACHINE-AS-ACTION
M
machine-as-action
web-frameworkjavascriptv10.3.1
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

asAction
const asAction = require('machine-as-action');
import asAction from 'machine-as-action';
This package is primarily CommonJS. Direct ESM import might require bundler configuration or dynamic import.

This quickstart demonstrates how to wrap an inline machine with `asAction` and simulate its execution using mock `req` and `res` objects. It covers basic JSON responses and advanced view rendering, illustrating how machine outputs are mapped to HTTP responses.

const asAction = require('machine-as-action'); // Simulate Express/Sails req/res objects for demonstration const mockReq = (query = {}, body = {}) => ({ query, body }); const mockRes = () => { let _status = 200; let _data = null; let _view = null; let _redirect = null; return { status: function(code) { _status = code; return this; }, json: function(data) { _data = data; console.log(`[Response JSON] Status: ${_status}, Data: ${JSON.stringify(_data)}`); }, send: function(data) { _data = data; console.log(`[Response Send] Status: ${_status}, Data: ${data}`); }, view: function(template, locals) { _view = { template, locals }; console.log(`[Response View] Status: ${_status}, Template: ${_view.template}, Locals: ${JSON.stringify(_view.locals)}`); }, redirect: function(url) { _redirect = url; console.log(`[Response Redirect] Status: ${_status}, URL: ${_redirect}`); }, serverError: function(err) { _status = 500; _data = { error: err.message }; console.error(`[Server Error] Status: ${_status}, Data: ${JSON.stringify(_data)}`); } }; }; // 1. Define an inline machine const greetMachine = { inputs: { name: { type: 'string', required: true, example: 'World' } }, exits: { success: { outputExample: 'Hello World!' }, error: { outputExample: 'Could not greet.' } }, fn: function(inputs, exits) { if (inputs.name) { return exits.success(`Hello, ${inputs.name}!`); } return exits.error(new Error('Name input is missing.')); } }; // 2. Wrap the machine as an action const greetAction = asAction(greetMachine); // 3. Simulate an HTTP request for greetAction console.log('--- Simulating a simple custom action ---'); greetAction(mockReq({ name: 'Registry User' }), mockRes()); // 4. Define an action with a custom responseType (e.g., 'view') const showProfilePageAction = asAction({ inputs: { userId: { type: 'string', required: true, example: 'user-123' } }, exits: { success: { responseType: 'view', viewTemplatePath: 'profile/show', outputExample: { username: 'Alice', id: 'user-123' } } }, fn: function(inputs, exits) { // In a real app, this would fetch user data from a database const userData = { username: `User ${inputs.userId}`, id: inputs.userId }; return exits.success(userData); } }); // 5. Simulate an HTTP request for the view action console.log('\n--- Simulating an action rendering a view ---'); showProfilePageAction(mockReq({ userId: '456' }), mockRes());
Debug
Known issues
breakingAs of v6.1.3, undocumented and experimental tolerance of 'loose functions' (functions not conforming to the machine spec) as machine definitions is no longer supported.
fix
Ensure all machine definitions adhere strictly to the 'machine' specification, providing `inputs`, `exits`, and a `fn` property.
affects: >=6.1.3
breakingVersion 7.0.11 introduced significant changes to custom response types and error handling, potentially altering the default behavior or configuration for `responseType`, `statusCode`, and `viewTemplatePath` in machine exits. Existing custom response logic might require adjustments.
fix
Review the documentation for `responseType`, `statusCode`, and `viewTemplatePath` options within machine exits. Test existing custom response handling thoroughly after upgrading.
affects: >=7.0.11
gotchaWhen generating stub data and not in production mode, `machine-as-action` automatically attaches an `X-Stub` header to responses. This behavior was introduced in v6.1.0.
fix
Be aware of the `X-Stub` header for debugging. In production (`process.env.NODE_ENV==='production'`), a warning will be logged instead. If you want to suppress this header even in development, you may need to intercept or modify responses.
affects: >=6.1.0
gotchaFor non-success exits that do not explicitly configure a `responseType` (e.g., 'view', 'redirect'), `machine-as-action` defaults to using a 500 status code.
fix
Always explicitly define the `responseType` and `statusCode` for non-success exits to ensure predictable HTTP responses, especially for error conditions that should return specific status codes (e.g., 400 Bad Request, 404 Not Found).
affects: >=7.0.0
Errors
Common errors & fixes
Error: E_DOUBLE_WRAP: This action has already been wrapped!
Attempting to wrap a machine with `asAction` more than once, or passing an already-wrapped action to `asAction`.
fix
Ensure `asAction` is called only once for each machine. Store the result of `asAction` and reuse it, rather than calling `asAction` multiple times with the same input.
Error: E_INVALID_MACHINE: The provided machine definition is invalid.
The object passed to `asAction` does not conform to the expected machine specification (missing `fn`, malformed `inputs`/`exits`, etc.).
fix
Verify that the machine definition object has a `fn` property, and correctly structured `inputs` and `exits` objects as per the machine spec.
ReferenceError: require is not defined in ES module scope
Attempting to use `require('machine-as-action')` in an ECMAScript module (ESM) environment without proper transpilation or dynamic import.
fix
If working in a pure ESM project, you might need to use dynamic `import('machine-as-action')` or configure your build system (e.g., Webpack, Rollup) to handle CommonJS modules within an ESM context. This package is primarily CJS.
TypeError: Cannot read properties of undefined (reading 'fn')
The object passed to `asAction` is `undefined` or `null`, or does not have the expected `fn` property, indicating an invalid or missing machine definition.
fix
Double-check that the variable holding your machine definition is correctly imported or defined and is a valid object containing a `fn` function.
Upgrade
Version history
10.3.1latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
8 hits · last 30 days
node
8
Resources