jspurefix 5.11.2 → 5.11.4

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 (104) hide show
  1. package/.gitattributes +4 -0
  2. package/dist/buffer/index.d.ts +6 -0
  3. package/dist/buffer/index.js +6 -0
  4. package/dist/buffer/index.js.map +1 -1
  5. package/dist/collections/index.d.ts +1 -0
  6. package/dist/collections/index.js +16 -0
  7. package/dist/collections/index.js.map +1 -1
  8. package/dist/config/winston-logger.js +2 -0
  9. package/dist/config/winston-logger.js.map +1 -1
  10. package/dist/dictionary/contained/index.d.ts +3 -0
  11. package/dist/dictionary/contained/index.js +3 -0
  12. package/dist/dictionary/contained/index.js.map +1 -1
  13. package/dist/dictionary/index.d.ts +5 -0
  14. package/dist/dictionary/index.js +5 -0
  15. package/dist/dictionary/index.js.map +1 -1
  16. package/dist/generator/applicability.d.ts +3 -0
  17. package/dist/generator/applicability.js +48 -0
  18. package/dist/generator/applicability.js.map +1 -0
  19. package/dist/generator/case-builder.d.ts +34 -0
  20. package/dist/generator/case-builder.js +111 -0
  21. package/dist/generator/case-builder.js.map +1 -0
  22. package/dist/generator/corpus-store.d.ts +43 -0
  23. package/dist/generator/corpus-store.js +115 -0
  24. package/dist/generator/corpus-store.js.map +1 -0
  25. package/dist/generator/index.d.ts +12 -0
  26. package/dist/generator/index.js +29 -0
  27. package/dist/generator/index.js.map +1 -0
  28. package/dist/generator/instrument-universe.d.ts +54 -0
  29. package/dist/generator/instrument-universe.js +286 -0
  30. package/dist/generator/instrument-universe.js.map +1 -0
  31. package/dist/generator/layout.d.ts +46 -0
  32. package/dist/generator/layout.js +208 -0
  33. package/dist/generator/layout.js.map +1 -0
  34. package/dist/generator/market-context.d.ts +64 -0
  35. package/dist/generator/market-context.js +119 -0
  36. package/dist/generator/market-context.js.map +1 -0
  37. package/dist/generator/outcome.d.ts +16 -0
  38. package/dist/generator/outcome.js +71 -0
  39. package/dist/generator/outcome.js.map +1 -0
  40. package/dist/generator/realistic-generator.d.ts +53 -0
  41. package/dist/generator/realistic-generator.js +275 -0
  42. package/dist/generator/realistic-generator.js.map +1 -0
  43. package/dist/generator/rng.d.ts +12 -0
  44. package/dist/generator/rng.js +60 -0
  45. package/dist/generator/rng.js.map +1 -0
  46. package/dist/generator/scatter.d.ts +50 -0
  47. package/dist/generator/scatter.js +285 -0
  48. package/dist/generator/scatter.js.map +1 -0
  49. package/dist/generator/scenarios.d.ts +13 -0
  50. package/dist/generator/scenarios.js +139 -0
  51. package/dist/generator/scenarios.js.map +1 -0
  52. package/dist/generator/value-conventions.d.ts +15 -0
  53. package/dist/generator/value-conventions.js +217 -0
  54. package/dist/generator/value-conventions.js.map +1 -0
  55. package/dist/index.d.ts +6 -0
  56. package/dist/index.js +4 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/jsfix-cmd.d.ts +5 -0
  59. package/dist/jsfix-cmd.js +161 -0
  60. package/dist/jsfix-cmd.js.map +1 -1
  61. package/dist/store/fix-msg-ascii-store-resend.js +2 -2
  62. package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
  63. package/dist/store/fix-msg-store-record.d.ts +1 -1
  64. package/dist/store/fix-msg-store-record.js.map +1 -1
  65. package/dist/store/index.d.ts +1 -0
  66. package/dist/store/index.js +1 -0
  67. package/dist/store/index.js.map +1 -1
  68. package/dist/transport/index.d.ts +7 -0
  69. package/dist/transport/index.js +7 -0
  70. package/dist/transport/index.js.map +1 -1
  71. package/dist/transport/session/index.d.ts +1 -0
  72. package/dist/transport/session/index.js +1 -0
  73. package/dist/transport/session/index.js.map +1 -1
  74. package/docs/generated-cases.md +237 -0
  75. package/docs/instrumentation.md +14 -0
  76. package/docs/scattered-components.md +60 -5
  77. package/jsfix.test_client.txt +62 -62
  78. package/jsfix.test_server.txt +72 -72
  79. package/package.json +5 -2
  80. package/src/buffer/index.ts +6 -0
  81. package/src/collections/index.ts +1 -1
  82. package/src/config/winston-logger.ts +8 -0
  83. package/src/dictionary/contained/index.ts +3 -0
  84. package/src/dictionary/index.ts +5 -0
  85. package/src/generator/applicability.ts +87 -0
  86. package/src/generator/case-builder.ts +167 -0
  87. package/src/generator/corpus-store.ts +166 -0
  88. package/src/generator/index.ts +12 -0
  89. package/src/generator/instrument-universe.ts +347 -0
  90. package/src/generator/layout.ts +279 -0
  91. package/src/generator/market-context.ts +207 -0
  92. package/src/generator/outcome.ts +102 -0
  93. package/src/generator/realistic-generator.ts +404 -0
  94. package/src/generator/rng.ts +92 -0
  95. package/src/generator/scatter.ts +432 -0
  96. package/src/generator/scenarios.ts +167 -0
  97. package/src/generator/value-conventions.ts +295 -0
  98. package/src/index.ts +12 -0
  99. package/src/jsfix-cmd.ts +204 -0
  100. package/src/store/fix-msg-ascii-store-resend.ts +2 -1
  101. package/src/store/fix-msg-store-record.ts +4 -1
  102. package/src/store/index.ts +1 -0
  103. package/src/transport/index.ts +10 -0
  104. package/src/transport/session/index.ts +1 -0
@@ -1,75 +1,75 @@
1
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:27.902|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
2
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:27.907|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=157|
3
- 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:15:27.908|7=1|16=1|10=245|
4
- 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260816-15:15:27.912|122=20260816-15:15:27.912|123=Y|36=2|10=111|
5
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:15:29.910|58=test_client initiate logout|10=105|
6
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:15:29.912|58=test_server confirming logout|10=089|
7
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:32.610|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=096|
8
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:32.612|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=146|
9
- 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:15:32.612|7=1|16=0|10=232|
10
- 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260816-15:15:32.615|122=20260816-15:15:32.614|123=Y|36=2|10=102|
11
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:15:34.612|58=test_client initiate logout|10=100|
12
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:15:34.613|58=test_server confirming logout|10=083|
13
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:37.013|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=098|
14
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:37.014|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=147|
15
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:15:37.014|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=100|
16
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:37.469|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=113|
17
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:37.470|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
18
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:15:38.471|58=test_client initiate logout|10=106|
19
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:15:38.472|58=test_server confirming logout|10=090|
20
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:41.185|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
21
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:41.186|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=152|
22
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:15:42.187|58=test_client initiate logout|10=105|
23
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:15:42.188|58=test_server confirming logout|10=089|
24
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:44.802|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=102|
25
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:44.804|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=152|
26
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260816-15:15:45.805|58=test_client initiate logout|10=103|
27
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:48.213|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=102|
28
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260816-15:15:48.214|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
29
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:15:49.214|58=test_client initiate logout|10=103|
30
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:15:49.215|58=test_server confirming logout|10=087|
31
- 8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:51.610|98=0|141=Y|553=js-client|554=pwd-client|10=165|
32
- 8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:51.611|45=1|372=A|373=1|58=msgType A missing required tag 108|10=255|
33
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:15:56.099|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=113|
34
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:15:56.100|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=144|
1
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:32.252|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
2
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:32.257|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=156|
3
+ 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:32.258|7=1|16=1|10=244|
4
+ 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260827-17:34:32.262|122=20260827-17:34:32.261|123=Y|36=2|10=108|
5
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:34:34.260|58=test_client initiate logout|10=104|
6
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:34.261|58=test_server confirming logout|10=087|
7
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:36.884|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=118|
8
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:36.886|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=168|
9
+ 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:36.887|7=1|16=0|10=255|
10
+ 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260827-17:34:36.889|122=20260827-17:34:36.889|123=Y|36=2|10=147|
11
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:34:38.887|58=test_client initiate logout|10=123|
12
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:38.888|58=test_server confirming logout|10=106|
13
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:41.290|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=105|
14
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:41.292|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
15
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:41.292|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=108|
16
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:41.720|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
17
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:41.721|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=152|
18
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:42.722|58=test_client initiate logout|10=105|
19
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:42.723|58=test_server confirming logout|10=089|
20
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:45.431|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
21
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:45.432|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
22
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:46.433|58=test_client initiate logout|10=108|
23
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:46.434|58=test_server confirming logout|10=092|
24
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:49.031|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
25
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:49.032|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
26
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260827-17:34:50.033|58=test_client initiate logout|10=097|
27
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:52.431|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
28
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260827-17:34:52.432|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=157|
29
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:53.433|58=test_client initiate logout|10=106|
30
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:53.434|58=test_server confirming logout|10=090|
31
+ 8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:55.818|98=0|141=Y|553=js-client|554=pwd-client|10=184|
32
+ 8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:55.819|45=1|372=A|373=1|58=msgType A missing required tag 108|10=018|
33
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:00.292|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
34
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:00.294|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
35
35
  8=FIX4.4|9=0000136|35=ZZ|49=init-comp|56=accept-comp|34=2|57=fix|52=20180902-12:25:28.980|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=177|
36
- 8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:15:56.102|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=147|
37
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:15:58.101|58=test_client initiate logout|10=099|
38
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260816-15:15:58.102|58=test_server confirming logout|10=083|
39
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:16:00.723|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=097|
40
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:16:00.724|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=146|
36
+ 8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:00.295|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=155|
37
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:02.294|58=test_client initiate logout|10=107|
38
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:02.295|58=test_server confirming logout|10=091|
39
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:04.876|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=115|
40
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:04.877|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=164|
41
41
  8=FIX4.4|9=0000123|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20180902-12:25:59.161|999=Sun, 02 Sep 2018 12:25:59 GMT|10=95|
42
- 8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:16:00.725|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=069|
43
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:16:02.725|58=test_client initiate logout|10=101|
44
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260816-15:16:02.726|58=test_server confirming logout|10=085|
45
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:16:09.141|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=100|
46
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:16:09.142|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=149|
42
+ 8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:04.878|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=087|
43
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:06.878|58=test_client initiate logout|10=119|
44
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:06.878|58=test_server confirming logout|10=102|
45
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:13.271|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
46
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:13.272|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
47
47
  8=FIX4.4|9=0000123|35=0|49=init-not!|56=accept-comp|34=2|57=fix|52=20180902-12:25:59.161|112=Sun, 02 Sep 2018 12:25:59 GMT|10=95|
48
- 8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:16:09.143|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=029|
49
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:16:11.142|58=test_client initiate logout|10=094|
50
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260816-15:16:11.143|58=test_server confirming logout|10=078|
51
- 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:16:13.538|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=055|
52
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:16:13.539|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
53
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:16:15.542|112=Sun, 16 Aug 2026 15:16:15 GMT|10=154|
54
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:16:17.546|112=Sun, 16 Aug 2026 15:16:17 GMT|10=163|
55
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=4|57=fix|52=20260816-15:16:19.538|58=test_client initiate logout|10=112|
56
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:16:19.539|58=test_server confirming logout|10=094|
57
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:16:21.932|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=102|
58
- 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:16:21.933|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=101|
59
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:16:23.938|112=Sun, 16 Aug 2026 15:16:23 GMT|10=161|
60
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260816-15:16:25.940|112=Sun, 16 Aug 2026 15:16:25 GMT|10=159|
61
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260816-15:16:27.942|112=Sun, 16 Aug 2026 15:16:27 GMT|10=166|
62
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:16:29.934|58=test_client initiate logout|10=111|
63
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260816-15:16:29.935|58=test_server confirming logout|10=098|
64
- 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:16:32.535|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=053|
65
- 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:16:32.536|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=105|
66
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:16:34.540|112=Sun, 16 Aug 2026 15:16:34 GMT|10=154|
67
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260816-15:16:36.543|112=Sun, 16 Aug 2026 15:16:36 GMT|10=162|
68
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:16:37.546|112=Sun, 16 Aug 2026 15:16:37 GMT|10=166|
69
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260816-15:16:38.550|112=Sun, 16 Aug 2026 15:16:38 GMT|10=165|
70
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=5|57=fix|52=20260816-15:16:40.537|58=test_client initiate logout|10=106|
71
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260816-15:16:40.538|58=test_server confirming logout|10=088|
72
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260816-15:18:33.776|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=113|
73
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260816-15:18:33.784|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=160|
74
- 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260816-15:18:34.787|58=test_client initiate logout|10=115|
75
- 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260816-15:18:34.788|58=test_server confirming logout|10=099|
48
+ 8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:13.273|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=033|
49
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:15.274|58=test_client initiate logout|10=109|
50
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:15.275|58=test_server confirming logout|10=093|
51
+ 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:17.650|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=059|
52
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:17.651|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=158|
53
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:35:19.656|112=Thu, 27 Aug 2026 17:35:19 GMT|10=173|
54
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:21.658|112=Thu, 27 Aug 2026 17:35:21 GMT|10=162|
55
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=4|57=fix|52=20260827-17:35:23.653|58=test_client initiate logout|10=110|
56
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:23.654|58=test_server confirming logout|10=092|
57
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:26.141|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
58
+ 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:26.146|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=107|
59
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:28.150|112=Thu, 27 Aug 2026 17:35:28 GMT|10=162|
60
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:30.153|112=Thu, 27 Aug 2026 17:35:30 GMT|10=152|
61
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260827-17:35:32.156|112=Thu, 27 Aug 2026 17:35:32 GMT|10=160|
62
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:35:34.147|58=test_client initiate logout|10=108|
63
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260827-17:35:34.148|58=test_server confirming logout|10=095|
64
+ 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:36.520|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=056|
65
+ 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:36.521|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=108|
66
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:35:38.525|112=Thu, 27 Aug 2026 17:35:38 GMT|10=170|
67
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:40.526|112=Thu, 27 Aug 2026 17:35:40 GMT|10=158|
68
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:41.531|112=Thu, 27 Aug 2026 17:35:41 GMT|10=155|
69
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260827-17:35:42.529|112=Thu, 27 Aug 2026 17:35:42 GMT|10=166|
70
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=5|57=fix|52=20260827-17:35:44.521|58=test_client initiate logout|10=108|
71
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:44.522|58=test_server confirming logout|10=090|
72
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:37:54.447|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=116|
73
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:37:54.455|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=163|
74
+ 8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:37:55.457|58=test_client initiate logout|10=117|
75
+ 8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:37:55.459|58=test_server confirming logout|10=102|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jspurefix",
3
- "version": "5.11.2",
3
+ "version": "5.11.4",
4
4
  "description": "pure node js fix engine",
5
5
  "keywords": [
6
6
  "typescript",
@@ -33,6 +33,9 @@
33
33
  "cmd": "node dist/jsfix-cmd",
34
34
  "trim44": "node dist/jsfix-cmd --dict=qf44 --trim --type=\"0,1,2,3,4,5,AE\"",
35
35
  "repo44": "node dist/jsfix-cmd --dict=repo44",
36
+ "scenarios": "node dist/jsfix-cmd --dict=repo44 --generate --scenarios --session=\"data/session/test-initiator.json\"",
37
+ "scenario": "node dist/jsfix-cmd --dict=repo44 --generate --delimiter=\"|\" --session=\"data/session/test-initiator.json\"",
38
+ "doll": "node dist/jsfix-cmd --dict=repo44 --generate --delimiter=\"|\" --session=\"data/session/test-initiator.json\"",
36
39
  "repo44-unit": "node dist/jsfix-cmd --dict=repo44 --generate --density=0.8 --unit --delimiter=\"|\" --type=\"AE\" --session=\"data/session/test-initiator.json\"",
37
40
  "repo44-script": "node dist/jsfix-cmd --dict=repo44 --generate --density=0.8 --script --delimiter=\"|\" --repeats=50 --session=\"data/session/test-initiator.json\"",
38
41
  "repo44-replay": "node dist/jsfix-cmd --dict=repo44 --fix=data/examples/FIX.4.4/fix.txt --delimiter=\"|\" --stats--delimiter=\"|\" --objects",
@@ -113,7 +116,7 @@
113
116
  "@types/sax": "^1.2.7",
114
117
  "@types/winston": "^2.4.4",
115
118
  "eslint": "^9.39.5",
116
- "eslint-config-love": "^154.1.0",
119
+ "eslint-config-love": "^155.0.0",
117
120
  "jest": "^30.4.2",
118
121
  "madge": "^8.0.0",
119
122
  "standard": "^17.1.2",
@@ -9,3 +9,9 @@ export * from './segment/segment-summary'
9
9
  export * from './structure'
10
10
  export * from './tag/tag-pos'
11
11
  export * from './tag/tags'
12
+ export * from './segment/segment-view'
13
+ export * from './segment/segment-type'
14
+ export * from './tag/tag-type'
15
+ export * from './ascii/ascii-parser'
16
+ export * from './ascii/ascii-parser-state'
17
+ export * from './ascii/parse-state'
@@ -1 +1 @@
1
-
1
+ export * from './collection'
@@ -37,9 +37,17 @@ export class WinstonLogger {
37
37
  info['log.level'] = info.level
38
38
  info['service.name'] = 'jspurefix'
39
39
  delete info.timestamp
40
+ // winston sets its own level, and emitting it beside the ECS name puts the same
41
+ // value on every line twice. the transport filters on Symbol.for('level'), not
42
+ // this property, so dropping it changes nothing about what gets logged
43
+ delete info.level
40
44
  if (err) {
41
45
  info['error.message'] = err.message
42
46
  info['error.stack_trace'] = err.stack
47
+ // the record composed for the console carries the stack inside the message,
48
+ // because that is what has always been rendered there. here the stack has a
49
+ // field of its own, so repeating it in the message only doubles the line
50
+ info.message = err.message
43
51
  }
44
52
  for (const key of Object.keys(context)) {
45
53
  info[`fix.${key}`] = context[key]
@@ -9,3 +9,6 @@ export * from './contained-group-field'
9
9
  export * from './contained-simple-field'
10
10
  export * from './fields-dispatch'
11
11
  export * from './contained-set-builder'
12
+ export * from './contained-field-set'
13
+ export * from './contained-field-dispatcher'
14
+ export * from './field-dispatcher'
@@ -5,3 +5,8 @@ export * from './fix-parser'
5
5
  export * from './fix-versions'
6
6
  export * from './fragment-safety'
7
7
  export * from './set-reduce'
8
+ export * from './definition'
9
+ export * from './contained'
10
+ export * from './type-dispatcher'
11
+ export * from './contained-set-type'
12
+ export * from './fix-definition-source'
@@ -0,0 +1,87 @@
1
+ import { AssetClass } from './instrument-universe'
2
+
3
+ /**
4
+ * Which optional fields belong on which kind of instrument.
5
+ *
6
+ * FIX puts every asset class through one `Instrument` component, so the dictionary is
7
+ * perfectly happy for a Brent future to carry a repurchase rate, a credit rating and a
8
+ * coupon payment date. Nothing rejects it and nothing in the engine cares - but it is
9
+ * the single loudest tell that a message was generated rather than captured, and it
10
+ * makes a fixture harder to read than a dense one, because the eye keeps stopping on
11
+ * fields that should not be there.
12
+ *
13
+ * The gate is written over field *names* rather than tags, and that is the whole trick.
14
+ * FIX mirrors the instrument block for legs and underlyings by prefixing it -
15
+ * `CouponRate`, `LegCouponRate`, `UnderlyingCouponRate` - so one pattern covers all
16
+ * three, and covers the same field in a dictionary that renumbered it. A tag list would
17
+ * have to be recited three times and would still miss whatever the next version adds.
18
+ *
19
+ * The gate is advisory. A field the dictionary marks required is emitted whatever this
20
+ * says, and so is anything the caller has explicitly asked for - a house dialect is
21
+ * entitled to put a coupon on a future, and refusing to generate that would be worse
22
+ * than generating it by accident.
23
+ */
24
+
25
+ const bond = [AssetClass.Bond]
26
+ const option = [AssetClass.Option]
27
+ const listed = [AssetClass.Future, AssetClass.Option, AssetClass.Spread]
28
+ const multileg = [AssetClass.Spread]
29
+
30
+ interface IRestriction {
31
+ readonly test: RegExp
32
+ readonly classes: readonly AssetClass[]
33
+ }
34
+
35
+ const fieldRestrictions: readonly IRestriction[] = [
36
+ {
37
+ // coupon, issuance, redemption, rating and registry - the fixed income half of the
38
+ // instrument block, plus its repo and financing neighbours
39
+ test: /Coupon|Repurchase|RepoCollateral|Redemption|CreditRating|Issuer|IssueDate|DatedDate|InterestAccrual|AccruedInterest|NumDaysInterest|Factor$|Pool$|InstrRegistry|CountryOfIssue|StateOrProvinceOfIssue|LocaleOfIssue|CPProgram|CPRegType|MarginRatio|TerminationType|DeliveryForm|(Start|End)Cash$/,
40
+ classes: bond
41
+ },
42
+ {
43
+ // yield, benchmark spread, stipulations and the new issue economics
44
+ test: /Yield|BenchmarkCurve|BenchmarkPrice|BenchmarkSecurity|Stipulation|Concession|TotalTakedown/,
45
+ classes: bond
46
+ },
47
+ {
48
+ test: /StrikePrice$|StrikeCurrency$|StrikeMultiplier$|StrikeValue$|PutOrCall$|OptAttribute$|ExerciseStyle$/,
49
+ classes: option
50
+ },
51
+ {
52
+ // a listed contract has an expiry and a multiplier; cash equity and spot FX do not
53
+ test: /MaturityMonthYear$|MaturityDate$|MaturityDay$|ContractMultiplier$|ContractSettlMonth$/,
54
+ classes: listed
55
+ }
56
+ ]
57
+
58
+ const setRestrictions: readonly IRestriction[] = [
59
+ { test: /^(YieldData|SpreadOrBenchmarkCurveData|FinancingDetails)$/, classes: bond },
60
+ { test: /Stipulations|Stips/, classes: bond },
61
+ // legs describe a strategy, so they belong to an instrument that has one
62
+ { test: /Leg(s|Grp|$|[A-Z])|InstrmtLeg/, classes: multileg },
63
+ { test: /Und(erlying|Instrmt)/, classes: [AssetClass.Spread, AssetClass.Option] }
64
+ ]
65
+
66
+ function applies (restrictions: readonly IRestriction[], name: string, assetClass: AssetClass): boolean {
67
+ for (const r of restrictions) {
68
+ if (r.test.test(name)) {
69
+ return r.classes.includes(assetClass)
70
+ }
71
+ }
72
+ return true
73
+ }
74
+
75
+ /**
76
+ * whether an optional field of this name is plausible on this kind of instrument
77
+ */
78
+ export function fieldApplies (name: string, assetClass: AssetClass): boolean {
79
+ return applies(fieldRestrictions, name, assetClass)
80
+ }
81
+
82
+ /**
83
+ * whether an optional component or group of this name is plausible here
84
+ */
85
+ export function setApplies (name: string, assetClass: AssetClass): boolean {
86
+ return applies(setRestrictions, name, assetClass)
87
+ }
@@ -0,0 +1,167 @@
1
+ import { ILooseObject } from '../collections/collection'
2
+ import { FixDefinitions } from '../dictionary/definition'
3
+ import { FragmentSafety, IFragmentSafetyFinding, describeFinding } from '../dictionary/fragment-safety'
4
+ import { Layout, tokenise } from './layout'
5
+ import { IScatterPlan, Scatterer } from './scatter'
6
+ import { IGeneratorOptions, RealisticGenerator } from './realistic-generator'
7
+ import { Rng } from './rng'
8
+ import { Scenarios } from './scenarios'
9
+
10
+ /**
11
+ * One test case: a message, the canonical encoding of it, and a legal re-ordering of the
12
+ * same bytes with one or more components taken apart.
13
+ *
14
+ * The canonical encoding is the oracle. It is contiguous by construction, because the
15
+ * encoder emits in dictionary order, so today's parser handles it and the object it
16
+ * produces is by definition the right answer. The scattered variant is a permutation of
17
+ * the same body tokens, so it says exactly the same thing - and any difference in what
18
+ * the parser makes of it is a defect, with no hand written expectation to be wrong about.
19
+ *
20
+ * A case also carries the fragment safety findings for the component it took apart. If
21
+ * two children of a set both claim a tag then no repair can attribute it by tag alone,
22
+ * and a case built over that shape is unfair rather than failing - see phase 0 of
23
+ * `docs/scattered-components.md`, and the 57 collisions in the QuickFIX FIX50SP2
24
+ * dictionary that motivated recording it.
25
+ */
26
+
27
+ export interface ICaseOptions {
28
+ /** a named scenario, or a message type with generator options of your own */
29
+ readonly scenario?: string
30
+ readonly msgType?: string
31
+ readonly seed?: number
32
+ /** how many nested scatter sites to ask for; 0 leaves the message canonical */
33
+ readonly depth?: number
34
+ /** how many runs to break each scattered component into */
35
+ readonly fragments?: number
36
+ readonly delimiter: string
37
+ readonly generator?: IGeneratorOptions
38
+ }
39
+
40
+ export interface IGeneratedCase {
41
+ readonly name: string
42
+ readonly msgType: string
43
+ readonly seed: number
44
+ readonly object: ILooseObject
45
+ readonly canonical: string
46
+ readonly scattered: string
47
+ readonly plan: IScatterPlan
48
+ /** what was asked for, which may exceed what the message could express */
49
+ readonly requestedDepth: number
50
+ readonly safety: readonly IFragmentSafetyFinding[]
51
+ }
52
+
53
+ export type Encode = (msgType: string, object: ILooseObject) => string
54
+
55
+ export class CaseBuilder {
56
+ constructor (
57
+ public readonly definitions: FixDefinitions,
58
+ public readonly encode: Encode) {
59
+ }
60
+
61
+ public build (options: ICaseOptions): IGeneratedCase {
62
+ const seed = options.seed ?? 0x5eed
63
+ const scenario = options.scenario ? Scenarios.get(options.scenario) : undefined
64
+ if (options.scenario && !scenario) {
65
+ throw new Error(`no scenario named ${options.scenario} - try one of ${Scenarios.names().join(', ')}`)
66
+ }
67
+ const msgType = options.msgType ?? scenario?.msgType
68
+ if (!msgType) {
69
+ throw new Error('a case needs either a scenario or a message type')
70
+ }
71
+ const generatorOptions: IGeneratorOptions = {
72
+ ...(scenario?.options ?? {}),
73
+ ...(options.generator ?? {}),
74
+ seed
75
+ }
76
+ const generator = new RealisticGenerator(this.definitions, generatorOptions)
77
+ const message = generator.generate(msgType)
78
+ const canonical = this.encode(message.msgType, message.object)
79
+
80
+ const depth = options.depth ?? 0
81
+ if (depth <= 0) {
82
+ return {
83
+ name: scenario?.name ?? message.name,
84
+ msgType: message.msgType,
85
+ seed,
86
+ object: message.object,
87
+ canonical,
88
+ scattered: canonical,
89
+ plan: { depth: 0, sites: [] },
90
+ requestedDepth: 0,
91
+ safety: []
92
+ }
93
+ }
94
+
95
+ const layout = Layout.build(canonical, options.delimiter, message.object, message.definition)
96
+ const scatterer = new Scatterer(layout, new Rng(seed ^ 0x9e37), options.fragments ?? 2)
97
+ const result = scatterer.scatter(depth, options.delimiter)
98
+ return {
99
+ name: scenario?.name ?? message.name,
100
+ msgType: message.msgType,
101
+ seed,
102
+ object: message.object,
103
+ canonical,
104
+ scattered: result.wire,
105
+ plan: result.plan,
106
+ requestedDepth: depth,
107
+ safety: this.safetyOf(result.plan)
108
+ }
109
+ }
110
+
111
+ /**
112
+ * findings for the sets the plan actually touched, rather than for the whole
113
+ * dictionary - a collision three components away is not this case's problem
114
+ */
115
+ private safetyOf (plan: IScatterPlan): IFragmentSafetyFinding[] {
116
+ const out: IFragmentSafetyFinding[] = []
117
+ for (const site of plan.sites) {
118
+ const leaf = site.component.split('.').pop() ?? ''
119
+ const name = leaf.replace(/\[[0-9]+\]$/, '')
120
+ const set = this.definitions.component.get(name)
121
+ if (!set) continue
122
+ for (const f of FragmentSafety.analyseSet(set, site.component)) {
123
+ out.push(f)
124
+ }
125
+ }
126
+ return out
127
+ }
128
+ }
129
+
130
+ /**
131
+ * A human readable account of what was done to a message, for the header of a fixture
132
+ * file. A scattered message is hard to read precisely because it is scattered, so
133
+ * something has to say which tags moved and where they went.
134
+ */
135
+ export function describeCase (c: IGeneratedCase, delimiter: string): string {
136
+ const lines: string[] = []
137
+ lines.push(`scenario ${c.name}`)
138
+ lines.push(`msgType ${c.msgType}`)
139
+ lines.push(`seed ${c.seed}`)
140
+ if (c.requestedDepth > 0) {
141
+ const short = c.plan.depth < c.requestedDepth
142
+ ? ` (asked for ${c.requestedDepth}; the message could not express more)`
143
+ : ''
144
+ lines.push(`doll depth ${c.plan.depth}${short}`)
145
+ for (const site of c.plan.sites) {
146
+ lines.push(` ${site.component} (${site.containment})`)
147
+ lines.push(` level ${site.level} (structure depth ${site.structureDepth})`)
148
+ lines.push(` runs ${site.fragments}`)
149
+ lines.push(` tags ${site.tags.join(' ')}`)
150
+ if (site.contendedTags.length > 0) {
151
+ lines.push(` contended ${site.contendedTags.join(' ')} - also claimed by a sibling of this component`)
152
+ }
153
+ }
154
+ if (c.safety.length > 0) {
155
+ lines.push(' fragment safety')
156
+ for (const f of c.safety) {
157
+ lines.push(` ${describeFinding(f)}`)
158
+ }
159
+ }
160
+ } else {
161
+ lines.push('doll depth 0 (canonical, nothing moved)')
162
+ }
163
+ const before = tokenise(c.canonical, delimiter).length
164
+ const after = tokenise(c.scattered, delimiter).length
165
+ lines.push(`tokens ${before} canonical, ${after} scattered`)
166
+ return lines.join('\n')
167
+ }