jssm 5.142.2 → 5.142.3

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.142.2";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.142.3";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.142.2 at 6/8/2026, 1:43:56 AM
21
+ * Generated for version 5.142.3 at 6/8/2026, 2:03:37 AM
22
22
 
23
23
  -->
24
- # jssm 5.142.2
24
+ # jssm 5.142.3
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/) ·
@@ -281,7 +281,7 @@ That decision shows up everywhere downstream:
281
281
  or run `npm run benny` against your own machine.
282
282
 
283
283
  - **More thoroughly tested than any other JavaScript state-machine
284
- library.** 6,645 tests at 100.0% line coverage
284
+ library.** 6,657 tests at 100.0% line coverage
285
285
  ([report](https://coveralls.io/github/StoneCypher/jssm)), plus
286
286
  fuzz testing via `fast-check`, with parser test data across ten natural
287
287
  languages and Emoji.
@@ -414,11 +414,11 @@ If your contribution is missing here, please open an issue.
414
414
 
415
415
  <br/>
416
416
 
417
- ***6,645 tests***, run 57,927 times.
417
+ ***6,657 tests***, run 57,939 times.
418
418
 
419
- - 6,127 specs with 100.0% coverage
419
+ - 6,139 specs with 100.0% coverage
420
420
  - 518 fuzz tests with 3.3% coverage
421
- - 5,659 TypeScript lines - 1.2 tests per line, 10.2 generated tests per line
421
+ - 5,719 TypeScript lines - 1.2 tests per line, 10.1 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)
@@ -1,6 +1,6 @@
1
1
  declare type StateType = string;
2
2
  import { JssmGenericState, JssmGenericConfig, JssmStateConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
3
- JssmMachineInternalState, JssmAllowsOverride, JssmStateDeclaration, JssmStateStyleKeyList, JssmLayout, JssmHistory, JssmSerialization, FslDirection, FslDirections, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult, EverythingHookContext, EverythingHookHandler, PostEverythingHookHandler, JssmEventName, JssmEventDetailMap, JssmEventFilter, JssmEventHandler, JssmUnsubscribe, JssmRng } from './jssm_types';
3
+ JssmMachineInternalState, JssmAllowsOverride, JssmAllowIslands, JssmStateDeclaration, JssmStateStyleKeyList, JssmLayout, JssmHistory, JssmSerialization, FslDirection, FslDirections, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult, EverythingHookContext, EverythingHookHandler, PostEverythingHookHandler, JssmEventName, JssmEventDetailMap, JssmEventFilter, JssmEventHandler, JssmUnsubscribe, JssmRng } from './jssm_types';
4
4
  import { arrow_direction, arrow_left_kind, arrow_right_kind } from './jssm_arrow';
5
5
  import { compile, make, wrap_parse } from './jssm_compiler';
6
6
  import { seq, unique, find_repeated, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, gen_splitmix32, sleep } from './jssm_util';
@@ -81,26 +81,6 @@ declare function transfer_state_properties(state_decl: JssmStateDeclaration): Js
81
81
  *
82
82
  */
83
83
  declare function state_style_condense(jssk: JssmStateStyleKeyList, machine?: any): JssmStateConfig;
84
- /*******
85
- *
86
- * Core finite state machine class. Holds the full graph of states and
87
- * transitions, the current state, hooks, data, properties, and all runtime
88
- * behavior. Typically created via the {@link sm} tagged template literal
89
- * rather than constructed directly.
90
- *
91
- * ```typescript
92
- * import { sm } from 'jssm';
93
- *
94
- * const light = sm`Red 'next' => Green 'next' => Yellow 'next' => Red;`;
95
- * light.state(); // 'Red'
96
- * light.action('next'); // true
97
- * light.state(); // 'Green'
98
- * ```
99
- *
100
- * @typeparam mDT The machine data type — the type of the value stored in
101
- * `.data()`. Defaults to `undefined` when no data is used.
102
- *
103
- */
104
84
  declare class Machine<mDT> {
105
85
  _state: StateType;
106
86
  _states: Map<StateType, JssmGenericState>;
@@ -166,6 +146,7 @@ declare class Machine<mDT> {
166
146
  _has_post_transition_hooks: boolean;
167
147
  _code_allows_override: JssmAllowsOverride;
168
148
  _config_allows_override: JssmAllowsOverride;
149
+ _allow_islands: JssmAllowIslands;
169
150
  _post_hooks: Map<string, Map<string, HookHandler<mDT>>>;
170
151
  _post_named_hooks: Map<string, Map<string, Map<string, HookHandler<mDT>>>>;
171
152
  _post_entry_hooks: Map<string, HookHandler<mDT>>;
@@ -205,7 +186,7 @@ declare class Machine<mDT> {
205
186
  _event_handlers: Map<JssmEventName, Set<JssmEventEntry<any, any>>>;
206
187
  _event_listener_count: number;
207
188
  _firing_error: boolean;
208
- constructor({ start_states, end_states, failed_outputs, initial_state, start_states_no_enforce, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, npm_name, state_declaration, property_definition, state_property, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, theme, flow, graph_layout, instance_name, history, data, default_state_config, default_active_state_config, default_hooked_state_config, default_terminal_state_config, default_start_state_config, default_end_state_config, allows_override, config_allows_override, rng_seed, time_source, timeout_source, clear_timeout_source }: JssmGenericConfig<StateType, mDT>);
189
+ constructor({ start_states, end_states, failed_outputs, initial_state, start_states_no_enforce, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, npm_name, state_declaration, property_definition, state_property, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, theme, flow, graph_layout, instance_name, history, data, default_state_config, default_active_state_config, default_hooked_state_config, default_terminal_state_config, default_start_state_config, default_end_state_config, allows_override, config_allows_override, allow_islands, rng_seed, time_source, timeout_source, clear_timeout_source }: JssmGenericConfig<StateType, mDT>);
209
190
  /********
210
191
  *
211
192
  * Internal method for fabricating states. Not meant for external use.
@@ -748,6 +729,17 @@ declare class Machine<mDT> {
748
729
  *
749
730
  */
750
731
  get allows_override(): JssmAllowsOverride;
732
+ /*********
733
+ *
734
+ * Return the effective island policy for this machine. `true` means
735
+ * disconnected components are allowed (the default), `false` requires a
736
+ * single connected component, and `'with_start'` allows islands only when
737
+ * every component contains at least one start state.
738
+ *
739
+ * @returns The island policy stored in the machine.
740
+ *
741
+ */
742
+ get allow_islands(): JssmAllowIslands;
751
743
  /** List all available theme names.
752
744
  * @returns An array of theme name strings.
753
745
  */