jssm 5.141.4 → 5.141.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/fsl.cjs CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var fs=require("fs");var path=require("path");var child_process=require("child_process");const IS_WINDOWS=process.platform==="win32";const PATH_SEP=IS_WINDOWS?";":":";const PATHEXT=IS_WINDOWS?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(s=>s.toLowerCase()):[""];async function findPluginOnPath(subcommand,pathEnv){if(!pathEnv)return null;const dirs=pathEnv.split(PATH_SEP).filter(d=>d.length>0);const baseName=`fsl-${subcommand}`;const NODE_EXTS=[".cjs",".mjs",".js"];const exts=IS_WINDOWS?[...PATHEXT,...NODE_EXTS]:["",...NODE_EXTS];for(const dir of dirs){for(const ext of exts){const candidate=path.join(dir,baseName+ext);try{const st=await fs.promises.stat(candidate);if(st.isFile())return candidate}catch{}}}return null}function isInProcessEligible(resolvedPath){const ext=path.extname(resolvedPath).toLowerCase();if(ext!==".js"&&ext!==".mjs"&&ext!==".cjs")return false;const norm=resolvedPath.replace(/\\/g,"/");return norm.includes("/node_modules/")}async function invokeInProcess(pluginPath,argv){const originalExit=process.exit;const originalArgv=process.argv;let interceptedExit=null;const ExitInterception=Symbol("ExitInterception");process.exit=code=>{interceptedExit=typeof code==="number"?code:0;throw ExitInterception};process.argv=[originalArgv[0],pluginPath,...argv];let result;try{const mod=await import(pluginPath);const cli=mod&&(mod.default??mod);if(typeof cli!=="function"){process.stderr.write(`fsl: error: plugin ${pluginPath} is missing default cli() export\n`);result=2}else{const r=await cli(argv);result=typeof r==="number"?r:0}}catch(e){if(e===ExitInterception){result=interceptedExit}else{process.stderr.write(`fsl: error: plugin threw: ${e.message??String(e)}\n`);result=2}}process.exit=originalExit;process.argv=originalArgv;return result}async function invokeBySpawn(pluginPath,argv){return new Promise(res=>{const ext=path.extname(pluginPath).toLowerCase();const isCmdScript=IS_WINDOWS&&(ext===".cmd"||ext===".bat");const isNodeScript=ext===".cjs"||ext===".mjs"||ext===".js";const[spawnCmd,spawnArgs]=isCmdScript?["cmd.exe",["/c",pluginPath,...argv]]:isNodeScript?[process.execPath,[pluginPath,...argv]]:[pluginPath,argv];const child=child_process.spawn(spawnCmd,spawnArgs,{stdio:"inherit"});child.on("exit",code=>res(code));child.on("error",err=>{process.stderr.write(`fsl: error: failed to spawn plugin: ${err.message}\n`);res(2)})})}const RESERVED_FLAGS=new Set(["--help","-h","--version","-V"]);const RESERVED_NAMES=new Set(["help","version"]);const getDispatcherVersion=()=>"5.141.4";const printDispatcherHelp=()=>{process.stdout.write(`fsl — finite-state language toolchain dispatcher\n\nUsage:\n fsl <subcommand> [options] [args...]\n fsl [--help|--version]\n\nBuilt-in subcommands (resolved via PATH):\n render Render FSL machines to SVG, DOT, PNG, JPEG, or HTML\n\nDiscovery:\n Any \`fsl-<name>\` executable on PATH is dispatched when you run\n \`fsl <name>\`. Third-party plugins follow the same contract as\n first-party ones.\n\n See: https://github.com/StoneCypher/jssm\n`)};async function dispatch(argv){let verbose=false;if(argv[0]==="--verbose"){verbose=true;argv=argv.slice(1)}if(argv.length===0||RESERVED_FLAGS.has(argv[0])){if(argv[0]==="--version"||argv[0]==="-V"){process.stdout.write(`fsl ${getDispatcherVersion()}\n`);return 0}printDispatcherHelp();return 0}const subcommand=argv[0];const rest=argv.slice(1);if(RESERVED_NAMES.has(subcommand)){if(subcommand==="version"){process.stdout.write(`fsl ${getDispatcherVersion()}\n`);return 0}printDispatcherHelp();return 0}const pluginPath=await findPluginOnPath(subcommand,process.env.PATH);if(!pluginPath){process.stderr.write(`fsl: '${subcommand}' is not a known subcommand and no \`fsl-${subcommand}\` was found on PATH\n`);return 1}if(verbose){process.stderr.write(`fsl: resolved '${subcommand}' to ${pluginPath}\n`)}if(isInProcessEligible(pluginPath)){return invokeInProcess(pluginPath,rest)}return invokeBySpawn(pluginPath,rest)}async function main(){const argv=process.argv.slice(2);const code=await dispatch(argv);process.exit(code)}void main();
2
+ "use strict";var fs=require("fs");var path=require("path");var child_process=require("child_process");const IS_WINDOWS=process.platform==="win32";const PATH_SEP=IS_WINDOWS?";":":";const PATHEXT=IS_WINDOWS?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(s=>s.toLowerCase()):[""];async function findPluginOnPath(subcommand,pathEnv){if(!pathEnv)return null;const dirs=pathEnv.split(PATH_SEP).filter(d=>d.length>0);const baseName=`fsl-${subcommand}`;const NODE_EXTS=[".cjs",".mjs",".js"];const exts=IS_WINDOWS?[...PATHEXT,...NODE_EXTS]:["",...NODE_EXTS];for(const dir of dirs){for(const ext of exts){const candidate=path.join(dir,baseName+ext);try{const st=await fs.promises.stat(candidate);if(st.isFile())return candidate}catch{}}}return null}function isInProcessEligible(resolvedPath){const ext=path.extname(resolvedPath).toLowerCase();if(ext!==".js"&&ext!==".mjs"&&ext!==".cjs")return false;const norm=resolvedPath.replace(/\\/g,"/");return norm.includes("/node_modules/")}async function invokeInProcess(pluginPath,argv){const originalExit=process.exit;const originalArgv=process.argv;let interceptedExit=null;const ExitInterception=Symbol("ExitInterception");process.exit=code=>{interceptedExit=typeof code==="number"?code:0;throw ExitInterception};process.argv=[originalArgv[0],pluginPath,...argv];let result;try{const mod=await import(pluginPath);const cli=mod&&(mod.default??mod);if(typeof cli!=="function"){process.stderr.write(`fsl: error: plugin ${pluginPath} is missing default cli() export\n`);result=2}else{const r=await cli(argv);result=typeof r==="number"?r:0}}catch(e){if(e===ExitInterception){result=interceptedExit}else{process.stderr.write(`fsl: error: plugin threw: ${e.message??String(e)}\n`);result=2}}process.exit=originalExit;process.argv=originalArgv;return result}async function invokeBySpawn(pluginPath,argv){return new Promise(res=>{const ext=path.extname(pluginPath).toLowerCase();const isCmdScript=IS_WINDOWS&&(ext===".cmd"||ext===".bat");const isNodeScript=ext===".cjs"||ext===".mjs"||ext===".js";const[spawnCmd,spawnArgs]=isCmdScript?["cmd.exe",["/c",pluginPath,...argv]]:isNodeScript?[process.execPath,[pluginPath,...argv]]:[pluginPath,argv];const child=child_process.spawn(spawnCmd,spawnArgs,{stdio:"inherit"});child.on("exit",code=>res(code));child.on("error",err=>{process.stderr.write(`fsl: error: failed to spawn plugin: ${err.message}\n`);res(2)})})}const RESERVED_FLAGS=new Set(["--help","-h","--version","-V"]);const RESERVED_NAMES=new Set(["help","version"]);const getDispatcherVersion=()=>"5.141.6";const printDispatcherHelp=()=>{process.stdout.write(`fsl — finite-state language toolchain dispatcher\n\nUsage:\n fsl <subcommand> [options] [args...]\n fsl [--help|--version]\n\nBuilt-in subcommands (resolved via PATH):\n render Render FSL machines to SVG, DOT, PNG, JPEG, or HTML\n\nDiscovery:\n Any \`fsl-<name>\` executable on PATH is dispatched when you run\n \`fsl <name>\`. Third-party plugins follow the same contract as\n first-party ones.\n\n See: https://github.com/StoneCypher/jssm\n`)};async function dispatch(argv){let verbose=false;if(argv[0]==="--verbose"){verbose=true;argv=argv.slice(1)}if(argv.length===0||RESERVED_FLAGS.has(argv[0])){if(argv[0]==="--version"||argv[0]==="-V"){process.stdout.write(`fsl ${getDispatcherVersion()}\n`);return 0}printDispatcherHelp();return 0}const subcommand=argv[0];const rest=argv.slice(1);if(RESERVED_NAMES.has(subcommand)){if(subcommand==="version"){process.stdout.write(`fsl ${getDispatcherVersion()}\n`);return 0}printDispatcherHelp();return 0}const pluginPath=await findPluginOnPath(subcommand,process.env.PATH);if(!pluginPath){process.stderr.write(`fsl: '${subcommand}' is not a known subcommand and no \`fsl-${subcommand}\` was found on PATH\n`);return 1}if(verbose){process.stderr.write(`fsl: resolved '${subcommand}' to ${pluginPath}\n`)}if(isInProcessEligible(pluginPath)){return invokeInProcess(pluginPath,rest)}return invokeBySpawn(pluginPath,rest)}async function main(){const argv=process.argv.slice(2);const code=await dispatch(argv);process.exit(code)}void main();
@@ -18,10 +18,10 @@ Please edit the file it's derived from, instead: `./src/md/readme_base.md`
18
18
 
19
19
 
20
20
 
21
- * Generated for version 5.141.4 at 6/2/2026, 10:32:57 AM
21
+ * Generated for version 5.141.6 at 6/4/2026, 4:19:34 PM
22
22
 
23
23
  -->
24
- # jssm 5.141.4
24
+ # jssm 5.141.6
25
25
 
26
26
  [**Try the live editor**](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) ·
27
27
  [Documentation](https://stonecypher.github.io/jssm/docs/) ·
@@ -418,7 +418,7 @@ If your contribution is missing here, please open an issue.
418
418
 
419
419
  - 5,971 specs with 100.0% coverage
420
420
  - 513 fuzz tests with 3.4% coverage
421
- - 5,573 TypeScript lines - 1.2 tests per line, 10.3 generated tests per line
421
+ - 5,590 TypeScript lines - 1.2 tests per line, 10.2 generated tests per line
422
422
 
423
423
  [![Actions Status](https://github.com/StoneCypher/jssm/workflows/Node%20CI/badge.svg)](https://github.com/StoneCypher/jssm/actions)
424
424
  [![NPM version](https://img.shields.io/npm/v/jssm.svg)](https://www.npmjs.com/package/jssm)
@@ -1103,6 +1103,20 @@ declare class Machine<mDT> {
1103
1103
  * @internal
1104
1104
  */
1105
1105
  _subscribe<Ev extends JssmEventName>(name: Ev, filterOrFn: JssmEventFilter<mDT, Ev> | JssmEventHandler<mDT, Ev>, maybeFn: JssmEventHandler<mDT, Ev> | undefined, once: boolean): JssmUnsubscribe;
1106
+ /**
1107
+ * Invoke a single event-handler entry, respecting its filter, once-removal
1108
+ * semantics, and the error re-fire / recursion-guard logic. Extracted so
1109
+ * {@link _fire} can share identical behavior between the size-1 fast-path
1110
+ * and the general snapshotted loop.
1111
+ *
1112
+ * @param entry - The subscriber descriptor to invoke.
1113
+ * @param set - The live Set that owns `entry`; needed for once-removal.
1114
+ * @param name - The event name being dispatched (used in error re-fires).
1115
+ * @param detail - The event payload forwarded to the handler.
1116
+ *
1117
+ * @internal
1118
+ */
1119
+ _fire_one<Ev extends JssmEventName>(entry: JssmEventEntry<mDT, Ev>, set: Set<JssmEventEntry<any, any>>, name: Ev, detail: JssmEventDetailMap<mDT>[Ev]): void;
1106
1120
  /**
1107
1121
  * Dispatch an event to every registered subscriber in registration
1108
1122
  * order. Filters are checked first; non-matching handlers are skipped
@@ -1114,6 +1128,11 @@ declare class Machine<mDT> {
1114
1128
  * handler throws, the new exception is swallowed rather than rebroadcast
1115
1129
  * to avoid an infinite loop.
1116
1130
  *
1131
+ * When exactly one subscriber is registered the common case avoids the
1132
+ * `Array.from(set)` snapshot allocation by capturing the lone entry into a
1133
+ * local first — equivalent to a 1-element snapshot but allocation-free.
1134
+ * The general path still snapshots for re-entrancy safety.
1135
+ *
1117
1136
  * @internal
1118
1137
  */
1119
1138
  _fire<Ev extends JssmEventName>(name: Ev, detail: JssmEventDetailMap<mDT>[Ev]): void;
@@ -1380,6 +1399,33 @@ declare class Machine<mDT> {
1380
1399
  *
1381
1400
  */
1382
1401
  override(newState: StateType, newData?: mDT | undefined): void;
1402
+ /*********
1403
+ *
1404
+ * Fire a `'rejection'` event caused by a hook vetoing a pending transition.
1405
+ * Extracted from the per-call closures inside {@link transition_impl} so
1406
+ * that it is allocated once at class-definition time rather than on every
1407
+ * hooked transition.
1408
+ *
1409
+ * @param hook_name Name of the hook that rejected (e.g. `'exit'`).
1410
+ * @param fromState State the machine was in when the transition was
1411
+ * attempted; used as the `from` field of the rejection event.
1412
+ * @param newState State that would have been entered had the hook
1413
+ * passed; used as the `to` field of the rejection event.
1414
+ * @param fromAction Action name when the transition was initiated by an
1415
+ * action call; `undefined` for plain state transitions.
1416
+ * @param oldData Machine data at the moment the transition was
1417
+ * attempted, before any hook mutations.
1418
+ * @param newData The `next_data` value passed to the transition call.
1419
+ * @param wasForced Whether the transition was attempted via
1420
+ * `force_transition`.
1421
+ *
1422
+ * @see transition_impl
1423
+ * @see _fire
1424
+ *
1425
+ * @internal
1426
+ *
1427
+ */
1428
+ _fire_hook_rejection(hook_name: string, fromState: StateType, newState: StateType, fromAction: StateType | undefined, oldData: mDT, newData: mDT | undefined, wasForced: boolean): void;
1383
1429
  /*********
1384
1430
  *
1385
1431
  * Shared transition core used by {@link transition}, {@link force_transition},