state-machine-cat 10.1.2 → 10.1.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.
Files changed (35) hide show
  1. package/bin/smcat.mjs +5 -0
  2. package/dist/commonjs/bundle.js +64 -64
  3. package/package.json +20 -25
  4. package/src/cli/actions.mjs +9 -0
  5. package/src/cli/file-name-to-stream.mjs +5 -6
  6. package/src/cli/make-description.mjs +9 -0
  7. package/src/cli/normalize.mjs +79 -41
  8. package/src/cli/validations.mjs +27 -1
  9. package/src/index-node.mjs +15 -47
  10. package/src/index.mjs +9 -9
  11. package/src/options.mjs +19 -13
  12. package/src/parse/index.mjs +13 -0
  13. package/src/parse/parser-helpers.mjs +70 -6
  14. package/src/parse/scxml/index.mjs +40 -1
  15. package/src/parse/scxml/normalize-machine.mjs +1 -1
  16. package/src/render/dot/attributebuilder.mjs +7 -0
  17. package/src/render/dot/counter.mjs +13 -0
  18. package/src/render/dot/index.mjs +66 -28
  19. package/src/render/dot/render-dot-from-ast.js +37 -15
  20. package/src/render/dot/state-transformers.mjs +4 -2
  21. package/src/render/dot/utl.mjs +20 -0
  22. package/src/render/index-node.mjs +9 -3
  23. package/src/render/index.mjs +3 -3
  24. package/src/render/scjson/index.mjs +6 -0
  25. package/src/render/scjson/make-valid-xml-name.mjs +7 -1
  26. package/src/render/scxml/index.mjs +3 -1
  27. package/src/render/smcat/index.js +48 -14
  28. package/src/render/vector/dot-to-vector-native.mjs +1 -1
  29. package/src/render/vector/vector-native-dot-with-fallback.mjs +3 -2
  30. package/src/render/vector/vector-with-viz-js.mjs +3 -2
  31. package/src/state-machine-model.mjs +46 -4
  32. package/src/transform/desugar.mjs +67 -18
  33. package/src/transform/utl.mjs +8 -0
  34. package/src/version.mjs +1 -1
  35. package/types/state-machine-cat.d.ts +41 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-machine-cat",
3
- "version": "10.1.2",
3
+ "version": "10.1.3",
4
4
  "description": "write beautiful state charts",
5
5
  "main": "./dist/commonjs/index.js",
6
6
  "module": "./src/index.mjs",
@@ -90,11 +90,6 @@
90
90
  "policy": "wanted",
91
91
  "because": "fast-xml-parser 4 has some breaking changes we still need to grok (why? how?)"
92
92
  },
93
- {
94
- "package": "husky",
95
- "policy": "pin",
96
- "because": "(npm7 & husky don't play nice together - and it might be it's not going to be solved satisfactorily) https://github.com/typicode/husky/issues/822 "
97
- },
98
93
  {
99
94
  "package": "viz.js",
100
95
  "policy": "pin",
@@ -244,13 +239,13 @@
244
239
  ]
245
240
  },
246
241
  "depcruise:graph:dev": {
247
- "command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type dot --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ | dot -Tsvg | depcruise-wrap-stream-in-html | browser",
242
+ "command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type dot --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ --highlight \"$(watskeburt develop)\"| dot -Tsvg | depcruise-wrap-stream-in-html | browser",
248
243
  "dependencies": [
249
244
  "depcruise:json"
250
245
  ]
251
246
  },
252
247
  "depcruise:graph:dev:flat": {
253
- "command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type flat --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ | twopi -Tsvg | depcruise-wrap-stream-in-html | browser",
248
+ "command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type flat --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ --highlight \"$(watskeburt develop)\"| twopi -Tsvg | depcruise-wrap-stream-in-html | browser",
254
249
  "dependencies": [
255
250
  "depcruise:json"
256
251
  ]
@@ -301,7 +296,7 @@
301
296
  ]
302
297
  },
303
298
  "lint:prettier": {
304
- "command": "prettier --check \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"types/*.ts\" \"*.{json,yml,md}\" \"docs/{smcat-online-interpreter.js,*.md}\"",
299
+ "command": "prettier --check \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"{src,types}/**/*.{ts,mts}\" \"*.{json,yml,md}\" \"docs/{smcat-online-interpreter.js,*.md}\"",
305
300
  "files": [
306
301
  "bin/*.mjs",
307
302
  "{src,test}/**/*.{js,mjs}",
@@ -319,15 +314,15 @@
319
314
  ]
320
315
  },
321
316
  "lint:types:tsc": {
322
- "command": "tsc --noEmit --strict --types --noUnusedLocals --noUnusedParameters --pretty types/*.d.ts",
317
+ "command": "tsc --noEmit --strict --types --noUnusedLocals --noUnusedParameters --pretty types/*.d.ts src/cli/*.d.mts src/cli/*.d.ts src/parse/scxml/*.d.ts",
323
318
  "files": [
324
319
  "types/*.d.ts"
325
320
  ]
326
321
  },
327
322
  "lint:types:eslint": {
328
- "command": "eslint types/*.d.ts",
323
+ "command": "eslint types/*.d.ts src/cli/*.d.mts src/cli/*.d.ts src/parse/scxml/*.d.ts",
329
324
  "files": [
330
- "types/*.d.ts",
325
+ "{src,types}/**/*.d.{ts,mts}",
331
326
  ".eslintrc.json"
332
327
  ]
333
328
  },
@@ -347,10 +342,10 @@
347
342
  ]
348
343
  },
349
344
  "lint:fix:prettier": {
350
- "command": "prettier --loglevel warn --write \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"types/*.ts\" \"*.{json,yml,md}\" \"docs/{smcat-online-interpreter.js,*.md}\"",
345
+ "command": "prettier --loglevel warn --write \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"{src,types}/**/*.{ts,mts}\" \"*.{json,yml,md}\" \"docs/{smcat-online-interpreter.js,*.md}\"",
351
346
  "files": [
352
347
  "bin/*.mjs",
353
- "{src,test}/**/*.{js,mjs}",
348
+ "{src,test}/**/*.{js,mjs,ts,mts}",
354
349
  "{config,test}/**/*.{js,json}",
355
350
  "tools/*.{js,mjs,json}",
356
351
  "types/*.ts",
@@ -359,9 +354,9 @@
359
354
  ]
360
355
  },
361
356
  "lint:fix:types": {
362
- "command": "eslint --fix types/*.d.ts",
357
+ "command": "eslint --fix types/*.d.ts src/cli/*.d.mts src/cli/*.d.ts src/parse/scxml/*.d.ts",
363
358
  "files": [
364
- "types/*.d.ts",
359
+ "{src,types}/**/*.d.{ts,mts}",
365
360
  ".eslintrc.json"
366
361
  ]
367
362
  },
@@ -372,7 +367,7 @@
372
367
  ]
373
368
  },
374
369
  "test:cover": {
375
- "command": "c8 --all --check-coverage --statements 100 --branches 99.1 --functions 100 --lines 100 --exclude \"{bin/*,config/**/*,coverage/**/*,docs/**/*,public/**/*,test/**/*,tools/**/*,types/**/*,dist/commonjs/*,src/**/*{template,-parser}.{mjs,cjs,js},tmp*}\" --reporter text-summary --reporter html --reporter lcov mocha",
370
+ "command": "c8 --all --check-coverage --statements 100 --branches 99.1 --functions 100 --lines 100 --exclude \"{bin/*,config/**/*,coverage/**/*,docs/**/*,public/**/*,test/**/*,tools/**/*,types/**/*,dist/commonjs/*,src/**/*.d.{ts,mts},src/**/*{template,-parser}.{mjs,cjs,js},tmp*}\" --reporter text-summary --reporter html --reporter lcov mocha",
376
371
  "output": [
377
372
  "coverage/lcov.info"
378
373
  ],
@@ -414,16 +409,16 @@
414
409
  "wrap-ansi": "8.0.1"
415
410
  },
416
411
  "devDependencies": {
417
- "@typescript-eslint/eslint-plugin": "5.40.1",
418
- "@typescript-eslint/parser": "5.40.1",
412
+ "@typescript-eslint/eslint-plugin": "5.42.1",
413
+ "@typescript-eslint/parser": "5.42.1",
419
414
  "c8": "7.12.0",
420
- "chai": "4.3.6",
415
+ "chai": "4.3.7",
421
416
  "chai-as-promised": "7.1.1",
422
417
  "chai-json-schema": "1.5.1",
423
418
  "chai-xml": "0.4.0",
424
- "dependency-cruiser": "11.17.0",
425
- "esbuild": "0.15.12",
426
- "eslint": "8.26.0",
419
+ "dependency-cruiser": "11.18.0",
420
+ "esbuild": "0.15.13",
421
+ "eslint": "8.27.0",
427
422
  "eslint-config-moving-meadow": "4.0.2",
428
423
  "eslint-config-prettier": "8.5.0",
429
424
  "eslint-plugin-budapestian": "5.0.1",
@@ -433,7 +428,7 @@
433
428
  "eslint-plugin-node": "11.1.0",
434
429
  "eslint-plugin-security": "1.5.0",
435
430
  "eslint-plugin-unicorn": "44.0.2",
436
- "husky": "8.0.1",
431
+ "husky": "8.0.2",
437
432
  "is-pdf": "1.0.0",
438
433
  "is-png": "3.0.1",
439
434
  "lint-staged": "13.0.3",
@@ -443,7 +438,7 @@
443
438
  "prettier": "2.7.1",
444
439
  "query-string": "7.1.1",
445
440
  "typescript": "4.8.4",
446
- "upem": "7.3.0",
441
+ "upem": "7.3.1",
447
442
  "watskeburt": "0.8.1",
448
443
  "wireit": "0.7.2",
449
444
  "xml-name-validator": "4.0.0"
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  import getStream from "get-stream";
2
3
  import smcat from "../index-node.mjs";
3
4
  import { getOutStream, getInStream } from "./file-name-to-stream.mjs";
@@ -31,7 +32,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
32
  `;
32
33
 
33
34
  export default {
35
+ /** @type {string} */
34
36
  LICENSE,
37
+ /**
38
+ * @param {import("./cli").ICLIRenderOptions} pOptions
39
+ */
35
40
  transform(pOptions) {
36
41
  return getStream(getInStream(pOptions.inputFrom)).then((pInput) => {
37
42
  const lOutput = smcat.render(pInput, {
@@ -54,6 +59,10 @@ export default {
54
59
  });
55
60
  },
56
61
 
62
+ /**
63
+ * @param {any} pError
64
+ * @returns {string}
65
+ */
57
66
  formatError(pError) {
58
67
  if (Boolean(pError.location)) {
59
68
  return `\n syntax error on line ${pError.location.start.line}, column ${pError.location.start.column}:\n ${pError.message}\n\n`;
@@ -1,11 +1,10 @@
1
+ // @ts-check
1
2
  /* eslint-disable security/detect-non-literal-fs-filename */
2
-
3
- import * as fs from "node:fs";
3
+ import fs from "node:fs";
4
4
 
5
5
  /**
6
- *
7
6
  * @param {string} pOutputTo
8
- * @returns {import("node:fs").WriteStream}
7
+ * @returns {NodeJS.WritableStream}
9
8
  */
10
9
  export function getOutStream(pOutputTo) {
11
10
  if ("-" === pOutputTo) {
@@ -13,10 +12,10 @@ export function getOutStream(pOutputTo) {
13
12
  }
14
13
  return fs.createWriteStream(pOutputTo);
15
14
  }
15
+
16
16
  /**
17
- *
18
17
  * @param {string} pInputFrom
19
- * @returns {import("node:fs").ReadStream}
18
+ * @returns {NodeJS.ReadableStream}
20
19
  */
21
20
  export function getInStream(pInputFrom) {
22
21
  if ("-" === pInputFrom) {
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  // seems eslint-plugin-import and eslint-plugin-node can't handle exports
2
3
  // fields yet. No man overboard not checking against this, because dependency-cruiser
3
4
  // will also find them
@@ -7,6 +8,10 @@ import indentString from "indent-string";
7
8
  import wrapAnsi from "wrap-ansi";
8
9
  import dotToVectorNative from "../render/vector/dot-to-vector-native.mjs";
9
10
 
11
+ /**
12
+ * @param {string} pString
13
+ * @returns {string}
14
+ */
10
15
  function wrapAndIndent(pString) {
11
16
  const lDogmaticMaxConsoleWidth = 78;
12
17
  const lDefaultIndent = 2;
@@ -16,6 +21,10 @@ function wrapAndIndent(pString) {
16
21
  return indentString(wrapAnsi(pString, lMaxWidth), lDefaultIndent);
17
22
  }
18
23
 
24
+ /**
25
+ * @param {boolean} pDotIsAvailable
26
+ * @return {string}
27
+ */
19
28
  export default (pDotIsAvailable = dotToVectorNative.isAvailable({})) => {
20
29
  const lDescription =
21
30
  "Write beautiful state charts - https://github.com/sverweij/state-machine-cat";
@@ -1,8 +1,13 @@
1
- /* eslint-disable security/detect-object-injection */
1
+ // @ts-check
2
+ /* eslint-disable security/detect-object-injection, no-inline-comments */
2
3
  import path from "node:path";
3
4
  import options from "../options.mjs";
4
5
  import { parse as parseAttributes } from "./attributes-parser.mjs";
5
6
 
7
+ /**
8
+ * @typedef {{[extension: string]: string}} DictionaryType
9
+ */
10
+
6
11
  const INPUT_EXTENSIONS = {
7
12
  ".smcat": "smcat",
8
13
  ".scxml": "scxml",
@@ -11,16 +16,18 @@ const INPUT_EXTENSIONS = {
11
16
  ".ast": "json",
12
17
  };
13
18
  const OUTPUT_EXTENSIONS = {
14
- ".smcat": "smcat",
19
+ ".ast": "json",
15
20
  ".dot": "dot",
21
+ ".eps": "eps",
16
22
  ".json": "json",
17
- ".ast": "json",
23
+ ".pdf": "pdf",
24
+ ".png": "png",
25
+ ".ps": "ps",
26
+ ".ps2": "ps2",
18
27
  ".scjson": "scjson",
19
28
  ".scxml": "scxml",
29
+ ".smcat": "smcat",
20
30
  ".svg": "svg",
21
- ".ps": "ps",
22
- ".ps2": "ps2",
23
- ".eps": "eps",
24
31
  };
25
32
 
26
33
  /**
@@ -31,7 +38,7 @@ const OUTPUT_EXTENSIONS = {
31
38
  * When in doubt returns pDefault
32
39
  *
33
40
  * @param {string} pString - filename
34
- * @param {object} pExtensionMap - a dictionary with
41
+ * @param {DictionaryType} pExtensionMap - a dictionary with
35
42
  * extension : classification pairs
36
43
  * @param {string} pDefault - the default to return when the extension
37
44
  * does not occur in the extension map
@@ -42,15 +49,26 @@ function classifyExtension(pString, pExtensionMap, pDefault) {
42
49
  return pExtensionMap[path.extname(pString)] || pDefault;
43
50
  }
44
51
 
52
+ /**
53
+ * @param {import("../../types/state-machine-cat").OutputType} pOutputType
54
+ * @returns {import("../../types/state-machine-cat").OutputType}
55
+ */
45
56
  function outputType2Extension(pOutputType) {
46
57
  const lExceptions = {
47
- oldsvg: "svg",
48
- oldps2: "ps",
49
58
  oldeps: "eps",
59
+ oldps: "ps",
60
+ oldps2: "ps",
61
+ oldsvg: "svg",
50
62
  ps2: "ps",
51
63
  };
52
64
  return lExceptions[pOutputType] || pOutputType;
53
65
  }
66
+
67
+ /**
68
+ * @param {string} pInputFrom
69
+ * @param {import("../../types/state-machine-cat").OutputType} pOutputType
70
+ * @returns {string}
71
+ */
54
72
  function deriveOutputFromInput(pInputFrom, pOutputType) {
55
73
  const lExtension = outputType2Extension(pOutputType);
56
74
 
@@ -66,16 +84,28 @@ function deriveOutputFromInput(pInputFrom, pOutputType) {
66
84
  .concat(lExtension);
67
85
  }
68
86
 
87
+ /**
88
+ * @param {string|undefined} pOutputTo
89
+ * @param {string} pInputFrom
90
+ * @param {import("../../types/state-machine-cat").OutputType} pOutputType
91
+ * @returns {string}
92
+ */
69
93
  function determineOutputTo(pOutputTo, pInputFrom, pOutputType) {
70
- return Boolean(pOutputTo)
71
- ? pOutputTo
72
- : deriveOutputFromInput(pInputFrom, pOutputType);
94
+ return pOutputTo ? pOutputTo : deriveOutputFromInput(pInputFrom, pOutputType);
73
95
  }
74
96
 
97
+ /**
98
+ * @param {import("../../types/state-machine-cat").InputType|undefined} pInputType
99
+ * @param {string} pInputFrom
100
+ * @returns {import("../../types/state-machine-cat").InputType}
101
+ */
75
102
  function determineInputType(pInputType, pInputFrom) {
76
103
  if (pInputType) {
77
104
  return pInputType;
78
105
  }
106
+ // @ts-expect-error we can safely cast this to InputType. classifyExtension
107
+ // can probably use treatment with a generic, but with jsdoc annotations
108
+ // if at all possible would likely be awkward.
79
109
  return classifyExtension(
80
110
  pInputFrom,
81
111
  INPUT_EXTENSIONS,
@@ -103,9 +133,16 @@ function determineParameter(pOptions, pParameter) {
103
133
  : options.getAllowedValues()[pParameter].default;
104
134
  }
105
135
 
136
+ /**
137
+ * @param {Partial<import("./cli").ILooseCLIRenderOptions>} pOptions
138
+ * @param {keyof import("./cli").ILooseCLIRenderOptions} pDotAttributes
139
+ * @returns {import("../../types/state-machine-cat").dotAttributesType}
140
+ */
106
141
  function determineDotAttributes(pOptions, pDotAttributes) {
107
- return Object.prototype.hasOwnProperty.call(pOptions, pDotAttributes)
108
- ? parseAttributes(pOptions[pDotAttributes])
142
+ return Boolean(pOptions?.[pDotAttributes]) &&
143
+ typeof pOptions[pDotAttributes] === "string"
144
+ ? // @ts-expect-error parseAttributes expects a string - which we can guarantee (see above) - but tsc can't/ doesn't see it
145
+ parseAttributes(pOptions[pDotAttributes])
109
146
  : [];
110
147
  }
111
148
 
@@ -114,38 +151,39 @@ function determineDotAttributes(pOptions, pDotAttributes) {
114
151
  *
115
152
  * - guesses the input type when not given
116
153
  * - guesses the output type when not given
117
- * - gueses the filename to output to when not given
154
+ * - guesses the filename to output to when not given
118
155
  * - translates parserOutput to a regular output type
119
156
  *
120
157
  * @param {string} pArgument an argument (containing the filename to parse)
121
- * @param {object} pOptions a commander options object
122
- * @return {object} a commander options object with options 'normalized'
158
+ * @param {import("./cli").ILooseCLIRenderOptions} pLooseOptions
159
+ * @return {import("./cli").ICLIRenderOptions}
160
+ * the passed options object, but normalized
123
161
  */
124
- export default function normalize(pArgument = "-", pOptions = {}) {
125
- const lReturnValue = { ...pOptions };
126
-
127
- lReturnValue.inputFrom = pArgument || "-";
128
- lReturnValue.inputType = determineInputType(
129
- pOptions.inputType,
130
- lReturnValue.inputFrom
131
- );
132
- lReturnValue.outputType = determineOutputType(
133
- pOptions.outputType,
134
- pOptions.outputTo
162
+ export default function normalize(pArgument = "-", pLooseOptions = {}) {
163
+ const lNormalizedInputFrom = pArgument || "-";
164
+ const lNormalizedInputType = determineInputType(
165
+ pLooseOptions.inputType,
166
+ lNormalizedInputFrom
135
167
  );
136
- lReturnValue.outputTo = determineOutputTo(
137
- pOptions.outputTo,
138
- lReturnValue.inputFrom,
139
- lReturnValue.outputType
168
+ const lNormalizedOutputType = determineOutputType(
169
+ pLooseOptions.outputType,
170
+ pLooseOptions.outputTo
140
171
  );
141
- lReturnValue.engine = determineParameter(pOptions, "engine");
142
- lReturnValue.direction = determineParameter(pOptions, "direction");
143
- lReturnValue.dotGraphAttrs = determineDotAttributes(
144
- pOptions,
145
- "dotGraphAttrs"
146
- );
147
- lReturnValue.dotNodeAttrs = determineDotAttributes(pOptions, "dotNodeAttrs");
148
- lReturnValue.dotEdgeAttrs = determineDotAttributes(pOptions, "dotEdgeAttrs");
149
172
 
150
- return lReturnValue;
173
+ return {
174
+ inputFrom: lNormalizedInputFrom,
175
+ inputType: lNormalizedInputType,
176
+ outputType: lNormalizedOutputType,
177
+ outputTo: determineOutputTo(
178
+ pLooseOptions.outputTo,
179
+ lNormalizedInputFrom,
180
+ lNormalizedOutputType
181
+ ),
182
+ engine: determineParameter(pLooseOptions, "engine"),
183
+ direction: determineParameter(pLooseOptions, "direction"),
184
+ dotGraphAttrs: determineDotAttributes(pLooseOptions, "dotGraphAttrs"),
185
+ dotNodeAttrs: determineDotAttributes(pLooseOptions, "dotNodeAttrs"),
186
+ dotEdgeAttrs: determineDotAttributes(pLooseOptions, "dotEdgeAttrs"),
187
+ desugar: pLooseOptions?.desugar ?? false,
188
+ };
151
189
  }
@@ -1,9 +1,14 @@
1
+ // @ts-check
1
2
  import fs from "node:fs";
2
3
  import smcat from "../index-node.mjs";
3
4
  import { parse as parseAttributes } from "./attributes-parser.mjs";
4
5
 
5
6
  const allowedValues = smcat.getAllowedValues();
6
7
 
8
+ /**
9
+ * @param {{name: string}} pValue
10
+ * @returns {string}
11
+ */
7
12
  function getName(pValue) {
8
13
  return pValue.name;
9
14
  }
@@ -13,14 +18,22 @@ const VALID_INPUT_TYPES = allowedValues.inputType.values.map(getName);
13
18
  const VALID_ENGINES = allowedValues.engine.values.map(getName);
14
19
  const VALID_DIRECTIONS = allowedValues.direction.values.map(getName);
15
20
 
21
+ /**
22
+ * @param {string} pFilename
23
+ * @returns {boolean}
24
+ */
16
25
  function isStdout(pFilename) {
17
26
  return "-" === pFilename;
18
27
  }
19
28
 
29
+ /**
30
+ * @param {string} pFilename
31
+ * @returns {boolean}
32
+ */
20
33
  function fileExists(pFilename) {
21
34
  try {
22
35
  if (!isStdout(pFilename)) {
23
- fs.accessSync(pFilename, fs.R_OK);
36
+ fs.accessSync(pFilename, fs.constants.R_OK);
24
37
  }
25
38
  return true;
26
39
  } catch (pError) {
@@ -28,6 +41,15 @@ function fileExists(pFilename) {
28
41
  }
29
42
  }
30
43
 
44
+ /**
45
+ * This function is shaped so it can serve as a validation function in a
46
+ * commander option.
47
+ *
48
+ * @param {keyof import("../../types/state-machine-cat").IRenderOptions} pOption
49
+ * @param {string[]} pValidValues
50
+ * @param {string} pError
51
+ * @returns {never|keyof import("../../types/state-machine-cat").IRenderOptions}
52
+ */
31
53
  function validOption(pOption, pValidValues, pError) {
32
54
  if (pValidValues.includes(pOption)) {
33
55
  return pOption;
@@ -78,6 +100,10 @@ export default {
78
100
  }
79
101
  },
80
102
 
103
+ /**
104
+ * @param {import("./cli").ICLIRenderOptions} pOptions
105
+ * @returns {never|import("./cli").ICLIRenderOptions}
106
+ */
81
107
  validateArguments(pOptions) {
82
108
  if (!pOptions.inputFrom) {
83
109
  throw new Error(`\n error: Please specify an input file.\n\n`);
@@ -1,52 +1,18 @@
1
+ // @ts-check
1
2
  import options from "./options.mjs";
2
3
  import parse from "./parse/index.mjs";
3
4
  import desugar from "./transform/desugar.mjs";
4
5
  import getRenderFunction from "./render/index-node.mjs";
5
6
  import { version } from "./version.mjs";
6
7
 
7
- const KNOWN_OPTIONS = [
8
- "outputType",
9
- "inputType",
10
- "engine",
11
- "direction",
12
- "dotNodeAttrs",
13
- "dotEdgeAttrs",
14
- "desugar",
15
- ];
16
-
17
- function isKnownOption(pKnownOptions) {
18
- return (pCandidateString) => pKnownOptions.includes(pCandidateString);
19
- }
20
-
21
- /**
22
- * Remove all attributes from the input object (which'd typically be
23
- * originating from commander) that are not known options options so
24
- * a clean object can be passed through.
25
- *
26
- * @param {any} pOptions - an options object e.g. as output from commander
27
- * @param {string[]} pKnownOptions - a list of known options
28
- * @return {any} - an options object that only contains stuff we care about
29
- */
30
- function ejectUnknownOptions(pOptions, pKnownOptions) {
31
- return Object.keys(pOptions)
32
- .filter(isKnownOption(pKnownOptions))
33
- .reduce((pAll, pKey) => {
34
- // eslint-disable-next-line security/detect-object-injection
35
- pAll[pKey] = pOptions[pKey];
36
- return pAll;
37
- }, {});
38
- }
39
-
40
8
  export default {
41
9
  /**
42
- * Translates the input script to an outputscript.
10
+ * Translates the input script to an output-script.
43
11
  *
44
- * @param {string} pScript The script to translate
45
- * @param {object} pOptions options influencing parsing & rendering.
46
- * See below for the complete list.
47
- * @return {string|void} nothing if a callback was passed, the
48
- * string with the rendered content if
49
- * no callback was passed and no error was found
12
+ * @param {string|import("../types/state-machine-cat").IStateMachine} pScript
13
+ * The script to translate
14
+ * @param {import("../types/state-machine-cat").IRenderOptions} pOptions
15
+ * options influencing parsing & rendering.
50
16
  * @throws {Error} if an error occurred and no callback
51
17
  * function was passed: the error
52
18
  *
@@ -54,13 +20,15 @@ export default {
54
20
  *
55
21
  */
56
22
  render(pScript, pOptions) {
57
- const lOptions = ejectUnknownOptions(pOptions, KNOWN_OPTIONS);
58
- const lAST = parse.getAST(pScript, lOptions);
59
- const lDesugar = options.getOptionValue(lOptions, "desugar");
23
+ const lStateMachine = parse.getAST(pScript, pOptions);
24
+ const lDesugar = options.getOptionValue(pOptions, "desugar");
60
25
 
61
- return getRenderFunction(options.getOptionValue(lOptions, "outputType"))(
62
- lDesugar ? desugar(lAST) : lAST,
63
- lOptions
26
+ // @ts-expect-error should be cast to OutputTypeType - or the getOptionValue
27
+ // function should be refactored to be more explicit in type it returns
28
+ // when we ask for outputType
29
+ return getRenderFunction(options.getOptionValue(pOptions, "outputType"))(
30
+ lDesugar ? desugar(lStateMachine) : lStateMachine,
31
+ pOptions
64
32
  );
65
33
  },
66
34
 
@@ -79,7 +47,7 @@ export default {
79
47
  * - the possible values in an array of objects, each of which
80
48
  * has the properties:
81
49
  * - name: the value
82
- *
50
+ * @returns {import("../types/state-machine-cat").IAllowedValues}
83
51
  */
84
52
  getAllowedValues() {
85
53
  return options.getAllowedValues();
package/src/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  /* eslint-disable budapestian/global-constant-pattern */
2
3
  import options from "./options.mjs";
3
4
  import parse from "./parse/index.mjs";
@@ -8,12 +9,11 @@ import { version as _version } from "./version.mjs";
8
9
  /**
9
10
  * Translates the input script to an output-script.
10
11
  *
11
- * @param {string} pScript The script to translate
12
- * @param {object} pOptions options influencing parsing & rendering.
13
- * See below for the complete list.
14
- * @return {string|void} nothing if a callback was passed, the
15
- * string with the rendered content if
16
- * no callback was passed and no error was found
12
+ * @param {string|import("../types/state-machine-cat").IStateMachine} pScript
13
+ * The script to translate
14
+ * @param {import("../types/state-machine-cat").IRenderOptions} pOptions
15
+ * options influencing parsing & rendering.
16
+ * @return {string}
17
17
  * @throws {Error} if an error occurred and no callback
18
18
  * function was passed: the error
19
19
  *
@@ -21,11 +21,11 @@ import { version as _version } from "./version.mjs";
21
21
  *
22
22
  */
23
23
  export function render(pScript, pOptions) {
24
- const lAST = parse.getAST(pScript, pOptions);
24
+ const lStateMachine = parse.getAST(pScript, pOptions);
25
25
  const lDesugar = options.getOptionValue(pOptions, "desugar");
26
26
 
27
27
  return getRenderFunction(options.getOptionValue(pOptions, "outputType"))(
28
- lDesugar ? desugar(lAST) : lAST,
28
+ lDesugar ? desugar(lStateMachine) : lStateMachine,
29
29
  pOptions
30
30
  );
31
31
  }
@@ -45,7 +45,7 @@ export const version = _version;
45
45
  * - the possible values in an array of objects, each of which
46
46
  * has the properties:
47
47
  * - name: the value
48
- *
48
+ * @returns {import("../types/state-machine-cat").IAllowedValues}
49
49
  */
50
50
  export function getAllowedValues() {
51
51
  return options.getAllowedValues();
package/src/options.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+ /** @type {import("../types/state-machine-cat").IAllowedValues} */
1
3
  const ALLOWED_VALUES = Object.freeze({
2
4
  inputType: {
3
5
  default: "smcat",
@@ -6,21 +8,22 @@ const ALLOWED_VALUES = Object.freeze({
6
8
  outputType: {
7
9
  default: "svg",
8
10
  values: [
9
- { name: "svg" },
10
- { name: "eps" },
11
- { name: "ps" },
12
- { name: "ps2" },
11
+ { name: "ast" },
13
12
  { name: "dot" },
14
- { name: "smcat" },
13
+ { name: "eps" },
15
14
  { name: "json" },
16
- { name: "ast" },
17
- { name: "scxml" },
18
- { name: "oldsvg" },
19
- { name: "oldps2" },
20
15
  { name: "oldeps" },
21
- { name: "scjson" },
16
+ { name: "oldps" },
17
+ { name: "oldps2" },
18
+ { name: "oldsvg" },
22
19
  { name: "pdf" },
23
20
  { name: "png" },
21
+ { name: "ps" },
22
+ { name: "ps2" },
23
+ { name: "scjson" },
24
+ { name: "scxml" },
25
+ { name: "smcat" },
26
+ { name: "svg" },
24
27
  ],
25
28
  },
26
29
  engine: {
@@ -53,15 +56,18 @@ const ALLOWED_VALUES = Object.freeze({
53
56
  * Returns the value for the option in the pOption object, and the default
54
57
  * for that option in all other cases
55
58
  *
56
- * @param {any} pOptions - the options as passed in the api `render` function
57
- * @param {string} pOptionName - the name of the option
58
- * @return {any} value
59
+ * @param {import("../types/state-machine-cat").IRenderOptions} pOptions - the options as passed in the api `render` function
60
+ * @param {keyof import("../types/state-machine-cat").IRenderOptions} pOptionName - the name of the option
61
+ * @return {string|boolean} value
59
62
  */
60
63
  function getOptionValue(pOptions, pOptionName) {
61
64
  // eslint-disable-next-line security/detect-object-injection
62
65
  return pOptions?.[pOptionName] ?? ALLOWED_VALUES[pOptionName].default;
63
66
  }
64
67
 
68
+ /**
69
+ * @returns {import("../types/state-machine-cat").IAllowedValues}
70
+ */
65
71
  function getAllowedValues() {
66
72
  return ALLOWED_VALUES;
67
73
  }