Complete Plugin Examples and Troubleshooting
Enterprise 3.3.0+. The examples below share the executable fixtures used to test startup manifests, HTTP results, callback composition and output posting. They use local test fixtures and an ephemeral HTTP mock.
Complete deployment
Place the entries shown in Quickstart, Scopes and Author types in basic/entry.js, scoped-routes/entry.js and mock-api/entry.ts. Place the user mapping shown in Scopes under user-mappings/customerTransform.fume. Bundle each entry with ncc 0.38.4 and move its output to the corresponding dist/*.cjs path below.
version: 1
workers: 1
maxConcurrencyPerWorker: 1
plugins:
- id: basic
path: ./dist/basic.cjs
- id: scoped-routes
path: ./dist/scoped-routes.cjs
- id: mock-api
path: ./dist/mock-api.cjs
config:
endpoint: http://127.0.0.1:8787/
timeoutMs: 1500
rootAliases:
- path: /customer-transform
mappingId: customerTransform
For repository fixtures, npm run build:plugin-examples performs that build. In your project, repeat npx ncc build for each entry and use the exact artifact names in the deployment. Start your local mock service at http://127.0.0.1:8787/: POST /transform must return {"transformed": <request body>}, and POST /output must accept that result and return {"posted":true}. The adapter awaits both calls and returns the transformed result. It is an example contract, not a server-provided external endpoint.
$env:FUME_PLUGINS_CONFIG = 'C:\plugins\deployment.yaml'
$env:MAPPINGS_FOLDER = 'C:\plugins\user-mappings'
node dist/server/fume-server.js
'{"name":"Ada"}' | curl.exe http://localhost:42420/basic-greet -H 'Content-Type: application/json' --data-binary '@-'
'[false,0,"",null]' | curl.exe http://localhost:42420/mock-api -H 'Content-Type: application/json' --data-binary '@-'
Keep normal license/auth settings and send a bearer token when required. For Docker, mount the whole directory read-only and use a mock endpoint reachable from inside the container, not its loopback address.
Requests and expected results
Each record supplies a POST path, JSON body in input and JSON response in result. / records use the ordinary ad-hoc evaluation envelope. The mock's /output receives exactly the transformed result.
[
{ "path": "/basic-greet", "input": { "name": "Ada" }, "result": "Hello ADA" },
{ "path": "/scoped-wrap", "input": { "name": "Ada" }, "result": { "customer": "Ada", "wrapped": true } },
{ "path": "/customer-transform", "input": { "name": "Ada" }, "result": { "customer": "Ada" } },
{ "path": "/mock-api", "input": [false, 0, "", null], "result": { "transformed": [false, 0, "", null] } },
{ "path": "/", "input": { "input": null, "fume": "$basicAdd(2, 3)" }, "result": 5 },
{ "path": "/", "input": { "input": null, "fume": "$map([\"a\", \"b\"], $basicUpper)" }, "result": ["A", "B"] },
{ "path": "/", "input": { "input": null, "fume": "$scopedCallback(\"ada\")" }, "result": "ADA" },
{ "path": "/", "input": { "input": null, "fume": "$basicGreet({\"name\": \"Ada\"}, {\"prefix\": \"Hi \"})" }, "result": "Hi ADA" }
]
The Enterprise fixture runner is:
npm run build:plugin-examples
npm run test:plugins:packaged -- --testPathPatterns=plugin-runtime.integration.test.ts --testNamePattern='documentation contract'
Run this in an Enterprise development checkout with a coherently built server/worker pair. This runner starts an ephemeral local mock automatically and shuts down its test processes; it does not contact the endpoint in the sample YAML. Copy-ready project authoring must still pass your own type checks and runtime tests.
Troubleshooting
Safe plugin errors do not reveal raw artifact paths, config/secrets or worker exception text. For evaluation errors inspect the response code or normal verbose report; startup failures emit a closed safe error. Signature input-validation errors may instead be evaluator signature codes.
| Code | Action |
|---|---|
PLUGIN_CONFIG_INVALID | Check strict schema, real .cjs path, IDs/version, declared callable exports, collisions and required configEnv values. |
PLUGIN_SIGNATURE_INVALID | Fix declaration syntax, unsupported function arguments or mapping arity/bindings shape. |
PLUGIN_DATA_INVALID | Return only supported plain data; remove executable/accessor/proxy/class/nonfinite values. |
PLUGIN_PAYLOAD_TOO_LARGE | Bound result/page count and depth; account for tagged encoding overhead. |
PLUGIN_QUEUE_FULL | Reduce admission/concurrency pressure or choose a justified queue budget. |
PLUGIN_TIMEOUT | Bound native/callback I/O; include queue time in the deadline; never blindly retry a write. |
PLUGIN_WORKER_UNAVAILABLE | Check worker recovery and shared-worker collateral failure; failed requests are not replayed. |
PLUGIN_EXECUTION_FAILED | Reproduce and test the native implementation locally; thrown raw messages are intentionally hidden. |
PLUGIN_CALL_INACTIVE | Call only during an active native invocation, not factory initialization or detached work. |
PLUGIN_MAPPING_NOT_ALLOWED | Use an own mapping's declared localName, not global/private/route identity. |
PLUGIN_MAPPING_FAILED | Validate callback signature/input and pure/FHIR mapping behavior/configuration. |
PLUGIN_REENTRANCY_FORBIDDEN | Remove every native call reachable from the callback mapping. |
PLUGIN_CALLBACK_LIMIT | Bound total calls and simultaneous Promise.all fan-out. |
PLUGIN_CALLBACKS_PENDING | Await every callback before the native function settles. |
Author checklist
- Check types with only the public declarations and validate your manifest/config at real startup.
- Test every intended exposure, isolated/opted-in scope, binding override, auth path and read-only route.
- Test omitted/null input, missing data, falsy results, payload/depth boundaries and unsupported values.
- Await callbacks; test errors, reentry denial, queue/full/deadline/crash/recovery and shutdown.
- Pin dependencies; bound external I/O and validate application result schemas independently.
- Deploy read-only artifacts under the actual Node/OS/container permissions and keep a tested rollback pair.
The runtime has a deterministic tested contract. That does not prove an arbitrary third-party artifact correct, secure, idempotent or suitable for your application without artifact-specific testing.