@flowscripter/dynamic-cli-framework 1.0.0

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 (133) hide show
  1. package/.github/workflows/check-bun-dependencies.yml +9 -0
  2. package/.github/workflows/lint-pr-message.yml +11 -0
  3. package/.github/workflows/release-bun-library.yml +8 -0
  4. package/.github/workflows/validate-bun-library-pr.yml +8 -0
  5. package/LICENSE +21 -0
  6. package/README.md +1475 -0
  7. package/bun.lock +63 -0
  8. package/index.ts +89 -0
  9. package/package.json +23 -0
  10. package/src/api/CLI.ts +17 -0
  11. package/src/api/CLIConfig.ts +19 -0
  12. package/src/api/Context.ts +25 -0
  13. package/src/api/RunResult.ts +142 -0
  14. package/src/api/argument/Argument.ts +36 -0
  15. package/src/api/argument/ArgumentValueTypes.ts +87 -0
  16. package/src/api/argument/ComplexOption.ts +31 -0
  17. package/src/api/argument/GlobalCommandArgument.ts +17 -0
  18. package/src/api/argument/Option.ts +32 -0
  19. package/src/api/argument/Positional.ts +27 -0
  20. package/src/api/argument/SubCommandArgument.ts +20 -0
  21. package/src/api/command/Command.ts +22 -0
  22. package/src/api/command/GlobalCommand.ts +33 -0
  23. package/src/api/command/GlobalModifierCommand.ts +12 -0
  24. package/src/api/command/GroupCommand.ts +20 -0
  25. package/src/api/command/SubCommand.ts +41 -0
  26. package/src/api/command/UsageExample.ts +21 -0
  27. package/src/api/service/ServiceProvider.ts +52 -0
  28. package/src/api/service/core/AsciiBannerGeneratorService.ts +35 -0
  29. package/src/api/service/core/KeyValueService.ts +28 -0
  30. package/src/api/service/core/PrinterService.ts +266 -0
  31. package/src/api/service/core/ShutdownService.ts +12 -0
  32. package/src/api/service/core/SyntaxHighlighterService.ts +42 -0
  33. package/src/cli/BaseCLI.ts +312 -0
  34. package/src/cli/DefaultRuntimeCLI.ts +54 -0
  35. package/src/command/MultiCommandCliHelpCommand.ts +394 -0
  36. package/src/command/SingleCommandCliHelpCommand.ts +183 -0
  37. package/src/command/UsageCommand.ts +35 -0
  38. package/src/command/VersionCommand.ts +22 -0
  39. package/src/launcher.ts +127 -0
  40. package/src/runtime/DefaultContext.ts +32 -0
  41. package/src/runtime/argument/ArgumentTypeGuards.ts +8 -0
  42. package/src/runtime/command/CommandTypeGuards.ts +30 -0
  43. package/src/runtime/command/CommandValidator.ts +549 -0
  44. package/src/runtime/parser.ts +219 -0
  45. package/src/runtime/registry/CommandRegistry.ts +121 -0
  46. package/src/runtime/registry/DefaultCommandRegistry.ts +318 -0
  47. package/src/runtime/registry/DefaultServiceProviderRegistry.ts +26 -0
  48. package/src/runtime/registry/ServiceProviderRegistry.ts +11 -0
  49. package/src/runtime/runner.ts +697 -0
  50. package/src/runtime/scanner.ts +417 -0
  51. package/src/runtime/values/ValuePopulationResult.ts +41 -0
  52. package/src/runtime/values/argumentValueMerge.ts +201 -0
  53. package/src/runtime/values/argumentValueValidation.ts +610 -0
  54. package/src/runtime/values/globalCommandValuePopulation.ts +96 -0
  55. package/src/runtime/values/subCommandValuePopulation.ts +680 -0
  56. package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +45 -0
  57. package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +38 -0
  58. package/src/service/asciiBannerGenerator/standard.flf.json +3 -0
  59. package/src/service/banner/BannerServiceProvider.ts +99 -0
  60. package/src/service/banner/command/NoBannerCommand.ts +42 -0
  61. package/src/service/configuration/ConfigurationServiceProvider.ts +571 -0
  62. package/src/service/configuration/DefaultKeyValueService.ts +60 -0
  63. package/src/service/configuration/command/ConfigCommand.ts +43 -0
  64. package/src/service/configuration/command/DumpConfigCommand.ts +47 -0
  65. package/src/service/printer/DefaultPrinterService.ts +256 -0
  66. package/src/service/printer/PrinterServiceProvider.ts +61 -0
  67. package/src/service/printer/command/DarkModeCommand.ts +43 -0
  68. package/src/service/printer/command/LogLevelCommand.ts +68 -0
  69. package/src/service/printer/command/NoColorCommand.ts +43 -0
  70. package/src/service/printer/terminal/Ansi.ts +10 -0
  71. package/src/service/printer/terminal/Color.ts +14 -0
  72. package/src/service/printer/terminal/Progress.ts +373 -0
  73. package/src/service/printer/terminal/Spinner.ts +100 -0
  74. package/src/service/printer/terminal/Styler.ts +5 -0
  75. package/src/service/printer/terminal/Terminal.ts +8 -0
  76. package/src/service/printer/terminal/Theme.ts +34 -0
  77. package/src/service/printer/terminal/TtyStyler.ts +39 -0
  78. package/src/service/printer/terminal/TtyTerminal.ts +65 -0
  79. package/src/service/shutdown/DefaultShutdownService.ts +9 -0
  80. package/src/service/shutdown/ShutdownServiceProvider.ts +55 -0
  81. package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +52 -0
  82. package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +51 -0
  83. package/src/util/configHelper.ts +95 -0
  84. package/src/util/envVarHelper.ts +338 -0
  85. package/src/util/helpHelper.ts +751 -0
  86. package/src/util/logger.ts +84 -0
  87. package/src/util/runnerHelper.ts +112 -0
  88. package/tests/cli/BaseCLI.test.ts +344 -0
  89. package/tests/command/MultiCommandCliHelpCommand.test.ts +650 -0
  90. package/tests/command/SingleCommandCliHelpCommand.test.ts +384 -0
  91. package/tests/command/UsageCommand.test.ts +53 -0
  92. package/tests/command/VersionCommand.test.ts +36 -0
  93. package/tests/fixtures/CLIConfig.ts +9 -0
  94. package/tests/fixtures/Command.ts +229 -0
  95. package/tests/fixtures/CommandRegistry.ts +8 -0
  96. package/tests/fixtures/ConfigurationServiceProvider.ts +28 -0
  97. package/tests/fixtures/Context.ts +33 -0
  98. package/tests/fixtures/ServiceProviderRegistry.ts +16 -0
  99. package/tests/fixtures/StreamString.ts +37 -0
  100. package/tests/fixtures/util.ts +41 -0
  101. package/tests/runtime/DefaultContext.test.ts +20 -0
  102. package/tests/runtime/argument/ArgumentTypeGuards.test.ts +49 -0
  103. package/tests/runtime/command/CommandTypeGuards.test.ts +43 -0
  104. package/tests/runtime/command/CommandValidator.test.ts +816 -0
  105. package/tests/runtime/parser.test.ts +766 -0
  106. package/tests/runtime/registry/DefaultCommandRegistry.test.ts +166 -0
  107. package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +42 -0
  108. package/tests/runtime/runner.test.ts +1298 -0
  109. package/tests/runtime/scanner.test.ts +1113 -0
  110. package/tests/runtime/values/argumentValueMerge.test.ts +314 -0
  111. package/tests/runtime/values/argumentValueValidation.test.ts +1020 -0
  112. package/tests/runtime/values/globalCommandValuePopulation.test.ts +662 -0
  113. package/tests/runtime/values/subCommandValuePopulation.test.ts +2658 -0
  114. package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +22 -0
  115. package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +70 -0
  116. package/tests/service/asciiBannerGenerator/__snapshots__/DefaultAsciiBannerGeneratorService.test.ts.snap +22 -0
  117. package/tests/service/asciiBannerGenerator/small.flf.json +3 -0
  118. package/tests/service/configuration/ConfigurationServiceProvider.test.ts +249 -0
  119. package/tests/service/configuration/DefaultKeyValueService.test.ts +65 -0
  120. package/tests/service/launchBanner/BannerServiceProvider.test.ts +49 -0
  121. package/tests/service/launchBanner/__snapshots__/BannerServiceProvider.test.ts.snap +3 -0
  122. package/tests/service/launchBanner/command/NoBannerCommand.test.ts +21 -0
  123. package/tests/service/printer/DefaultPrinterService.test.ts +409 -0
  124. package/tests/service/printer/PrinterServiceProvider.test.ts +29 -0
  125. package/tests/service/printer/command/LogLevelCommand.test.ts +58 -0
  126. package/tests/service/printer/terminal/Progress.test.ts +40 -0
  127. package/tests/service/printer/terminal/Spinner.test.ts +57 -0
  128. package/tests/service/shutdown/ShutdownServiceProvider.test.ts +13 -0
  129. package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +123 -0
  130. package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +41 -0
  131. package/tests/util/configHelper.test.ts +275 -0
  132. package/tests/util/envVarHelper.test.ts +318 -0
  133. package/tests/util/logger.test.ts +10 -0
@@ -0,0 +1,314 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import argumentValueMerge from "../../../src/runtime/values/argumentValueMerge.ts";
3
+ import { MAXIMUM_ARGUMENT_ARRAY_SIZE } from "../../../src/api/argument/SubCommandArgument.ts";
4
+
5
+ describe("argumentValueMerge Tests", () => {
6
+ test("One layer merge", () => {
7
+ let result = argumentValueMerge({ a: 1 }, { b: 2 });
8
+ expect(result).toEqual({ a: 1, b: 2 });
9
+
10
+ result = argumentValueMerge({ a: "foo" }, { b: "bar" });
11
+ expect(result).toEqual({ a: "foo", b: "bar" });
12
+
13
+ result = argumentValueMerge({ a: true }, { b: false });
14
+ expect(result).toEqual({ a: true, b: false });
15
+ });
16
+
17
+ test("One layer merge and override", () => {
18
+ let result = argumentValueMerge({ a: 1 }, { a: 2 });
19
+ expect(result).toEqual({ a: 1 });
20
+
21
+ result = argumentValueMerge({ a: "foo" }, { a: "bar" });
22
+ expect(result).toEqual({ a: "foo" });
23
+
24
+ result = argumentValueMerge({ a: true }, { a: false });
25
+ expect(result).toEqual({ a: true });
26
+ });
27
+
28
+ test("One layer merge with no defaults", () => {
29
+ let result = argumentValueMerge({ a: 1 }, {});
30
+ expect(result).toEqual({ a: 1 });
31
+
32
+ result = argumentValueMerge({ a: "foo" }, {});
33
+ expect(result).toEqual({ a: "foo" });
34
+
35
+ result = argumentValueMerge({ a: true }, {});
36
+ expect(result).toEqual({ a: true });
37
+ });
38
+
39
+ test("One layer merge with no overrides", () => {
40
+ let result = argumentValueMerge({}, { a: 1 });
41
+ expect(result).toEqual({ a: 1 });
42
+
43
+ result = argumentValueMerge({}, { a: "foo" });
44
+ expect(result).toEqual({ a: "foo" });
45
+
46
+ result = argumentValueMerge({}, { a: true });
47
+ expect(result).toEqual({ a: true });
48
+ });
49
+
50
+ test("Override from configured number to parsed string", () => {
51
+ const result = argumentValueMerge({ a: "1" }, { a: 2 });
52
+ expect(result).toEqual({ a: "1" });
53
+ });
54
+
55
+ test("Override from configured boolean to parsed string", () => {
56
+ const result = argumentValueMerge({ a: "true" }, { a: false });
57
+ expect(result).toEqual({ a: "true" });
58
+ });
59
+
60
+ test("Override from configured single value to parsed array", () => {
61
+ const result = argumentValueMerge({ a: [1, 2] }, { a: 2 });
62
+ expect(result).toEqual({ a: [1, 2] });
63
+ });
64
+
65
+ test("Override from configured single number value to parsed string array", () => {
66
+ const result = argumentValueMerge({ a: ["1", "2"] }, { a: 2 });
67
+ expect(result).toEqual({ a: ["1", "2"] });
68
+ });
69
+
70
+ test("Override configured array value with parsed single value", () => {
71
+ const result = argumentValueMerge({ a: 3 }, { a: [1, 2] });
72
+ expect(result).toEqual({ a: [3, 2] });
73
+ });
74
+
75
+ test("Override configured number array value with parsed single string value", () => {
76
+ const result = argumentValueMerge({ a: "3" }, { a: [1, 2] });
77
+ expect(result).toEqual({ a: ["3", 2] });
78
+ });
79
+
80
+ test("Complex object and arrays merge", () => {
81
+ const result = argumentValueMerge({ a: { b: { c: "foo" } } }, {
82
+ d: [{ e: [{ f: 1 }] }],
83
+ });
84
+ expect(result).toEqual({ a: { b: { c: "foo" } }, d: [{ e: [{ f: 1 }] }] });
85
+ });
86
+
87
+ test("Complex object and arrays merge and override", () => {
88
+ let result = argumentValueMerge({
89
+ a: { b: { c: "foo", c1: "bar", c2: "car" } },
90
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g2: 3 }] }],
91
+ }, {
92
+ a: { b: { c: "boo", c1: "bar" } },
93
+ d: [{ e: [{ f: 0 }, { g: 0 }, { g1: 2 }] }],
94
+ });
95
+ expect(result).toEqual({
96
+ a: { b: { c: "foo", c1: "bar", c2: "car" } },
97
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g1: 2, g2: 3 }] }],
98
+ });
99
+
100
+ result = argumentValueMerge({
101
+ a: { b: { c: "foo", c1: "bar", c2: "car" } },
102
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g2: 3 }] }],
103
+ }, {
104
+ a: { b: { c: "boo", c1: "bar" } },
105
+ d: [{ e: [{ f: 0 }, { g: 0 }, { g1: 2 }, { g3: 4 }] }],
106
+ });
107
+ expect(result).toEqual({
108
+ a: { b: { c: "foo", c1: "bar", c2: "car" } },
109
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g1: 2, g2: 3 }, { g3: 4 }] }],
110
+ });
111
+
112
+ result = argumentValueMerge({
113
+ a: { b: { c: "foo", c1: "bar", c2: "car" } },
114
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g2: 3 }] }],
115
+ }, {
116
+ a: { b: { c: "boo", c1: "bar" } },
117
+ d: [{ e: [{ f: 0 }, { g: 0 }, { g2: 2 }, { g3: 4 }] }],
118
+ });
119
+ expect(result).toEqual({
120
+ a: { b: { c: "foo", c1: "bar", c2: "car" } },
121
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g2: 3 }, { g3: 4 }] }],
122
+ });
123
+ });
124
+
125
+ test("Primitive array merge and insert", () => {
126
+ let result = argumentValueMerge({ a: [1, 2, 3] }, { a: [1, 2, 3] });
127
+ expect(result).toEqual({ a: [1, 2, 3] });
128
+
129
+ result = argumentValueMerge({ a: [1, 2, 3, 4] }, { a: [1, 2, 3] });
130
+ expect(result).toEqual({ a: [1, 2, 3, 4] });
131
+
132
+ result = argumentValueMerge({ a: [1, 2, 3] }, { a: [1, 2, 3, 4] });
133
+ expect(result).toEqual({ a: [1, 2, 3, 4] });
134
+
135
+ result = argumentValueMerge({ a: [1, 2, 3] }, { a: [4, 5, 6, 7] });
136
+ expect(result).toEqual({ a: [1, 2, 3, 7] });
137
+ });
138
+
139
+ test("Complex object array merge and insert", () => {
140
+ let result = argumentValueMerge({ a: [{ b: 1 }, { c: 2 }, { d: 3 }] }, {
141
+ a: [{ b: 1 }, { c: 2 }, { d: 3 }],
142
+ });
143
+ expect(result).toEqual({ a: [{ b: 1 }, { c: 2 }, { d: 3 }] });
144
+
145
+ result = argumentValueMerge({
146
+ a: [{ b: 1 }, { c: 2 }, { d: 3 }, { e: 4 }],
147
+ }, { a: [{ b: 1 }, { c: 2 }, { d: 3 }] });
148
+ expect(result).toEqual({ a: [{ b: 1 }, { c: 2 }, { d: 3 }, { e: 4 }] });
149
+
150
+ result = argumentValueMerge({ a: [{ b: 1 }, { c: 2 }, { d: 3 }] }, {
151
+ a: [{ b: 1 }, { c: 2 }, { d: 3 }, { e: 4 }],
152
+ });
153
+ expect(result).toEqual({ a: [{ b: 1 }, { c: 2 }, { d: 3 }, { e: 4 }] });
154
+
155
+ result = argumentValueMerge({ a: [{ b: 1 }, { c: 2 }, { d: 3 }] }, {
156
+ a: [{ b: 4 }, { c: 5 }, { d: 6 }, { e: 7 }],
157
+ });
158
+ expect(result).toEqual({ a: [{ b: 1 }, { c: 2 }, { d: 3 }, { e: 7 }] });
159
+
160
+ result = argumentValueMerge({ a: [{ b: 1 }, { c: 2 }, { d: 3 }] }, {
161
+ a: [{ b1: 4 }, { c1: 5 }, { d1: 6 }, { e1: 7 }],
162
+ });
163
+ expect(result).toEqual({
164
+ a: [{ b: 1, b1: 4 }, { c: 2, c1: 5 }, { d: 3, d1: 6 }, { e1: 7 }],
165
+ });
166
+
167
+ result = argumentValueMerge({ a: [{ a: 1 }, { a: 2 }, { a: 3 }] }, {
168
+ a: [{ a: 4 }, { a: 5 }, { a: 6 }, { a: 7 }],
169
+ });
170
+ expect(result).toEqual({
171
+ a: [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }],
172
+ });
173
+ });
174
+
175
+ test("Complex object and arrays merge with no defaults", () => {
176
+ const result = argumentValueMerge({
177
+ a: { b: { c: "foo" } },
178
+ d: [{ e: [{ f: 1 }] }],
179
+ }, {});
180
+ expect(result).toEqual({ a: { b: { c: "foo" } }, d: [{ e: [{ f: 1 }] }] });
181
+ });
182
+
183
+ test("Complex object and arrays merge with no overrides", () => {
184
+ const result = argumentValueMerge({}, {
185
+ a: { b: { c: "foo" } },
186
+ d: [{ e: [{ f: 1 }] }],
187
+ });
188
+ expect(result).toEqual({ a: { b: { c: "foo" } }, d: [{ e: [{ f: 1 }] }] });
189
+ });
190
+
191
+ test("One layer merge with undefined values", () => {
192
+ let result = argumentValueMerge({ a: undefined }, { b: 1 });
193
+ expect(result).toEqual({ a: undefined, b: 1 });
194
+
195
+ result = argumentValueMerge({ a: undefined }, { b: "foo" });
196
+ expect(result).toEqual({ a: undefined, b: "foo" });
197
+
198
+ result = argumentValueMerge({ a: undefined }, { b: true });
199
+ expect(result).toEqual({ a: undefined, b: true });
200
+ });
201
+
202
+ test("One layer merge and override with undefined values", () => {
203
+ let result = argumentValueMerge({ a: undefined }, { a: 1 });
204
+ expect(result).toEqual({ a: 1 });
205
+
206
+ result = argumentValueMerge({ a: undefined }, { a: "foo" });
207
+ expect(result).toEqual({ a: "foo" });
208
+
209
+ result = argumentValueMerge({ a: undefined }, { a: true });
210
+ expect(result).toEqual({ a: true });
211
+ });
212
+
213
+ test("Primitive array merge with undefined values", () => {
214
+ const result = argumentValueMerge({ a: [1, 2, 3, undefined] }, {
215
+ a: [1, 2, 3],
216
+ });
217
+ expect(result).toEqual({ a: [1, 2, 3, undefined] });
218
+ });
219
+
220
+ test("Primitive array merge and override with undefined values", () => {
221
+ const result = argumentValueMerge({ a: [1, 2, undefined] }, {
222
+ a: [1, 2, 3],
223
+ });
224
+ expect(result).toEqual({ a: [1, 2, 3] });
225
+ });
226
+
227
+ test("Complex object and arrays merge undefined values", () => {
228
+ const result = argumentValueMerge({
229
+ a: { b: { c: undefined } },
230
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g2: 3 }, undefined] }],
231
+ }, {
232
+ a: { b: { c1: "foo" } },
233
+ d: [{ e: [{ f: 0 }, { g: 2 }, { g1: 2 }] }],
234
+ });
235
+ expect(result).toEqual({
236
+ a: { b: { c: undefined, c1: "foo" } },
237
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g1: 2, g2: 3 }, undefined] }],
238
+ });
239
+ });
240
+
241
+ test("Complex object and arrays merge and override with undefined values", () => {
242
+ const result = argumentValueMerge({
243
+ a: { b: { c: undefined } },
244
+ d: [{ e: [{ f: 1 }, undefined, { g2: 3 }] }],
245
+ }, { a: { b: { c: "foo" } }, d: [{ e: [{ f: 0 }, { g: 2 }, { g1: 2 }] }] });
246
+ expect(result).toEqual({
247
+ a: { b: { c: "foo" } },
248
+ d: [{ e: [{ f: 1 }, { g: 2 }, { g1: 2, g2: 3 }] }],
249
+ });
250
+ });
251
+
252
+ test("Complex object merge with undefined objects", () => {
253
+ const result = argumentValueMerge({ a: { b1: undefined } }, {
254
+ a: { b2: { c: "foo" } },
255
+ });
256
+ expect(result).toEqual({ a: { b1: undefined, b2: { c: "foo" } } });
257
+ });
258
+
259
+ test("Complex object merge and override with undefined objects", () => {
260
+ const result = argumentValueMerge({ a: { b: undefined } }, {
261
+ a: { b: { c: "foo" } },
262
+ });
263
+ expect(result).toEqual({ a: { b: { c: "foo" } } });
264
+ });
265
+
266
+ test("Maximum array size asserted", () => {
267
+ const illegal = new Array<number>();
268
+ for (let i = 0; i <= MAXIMUM_ARGUMENT_ARRAY_SIZE; i++) {
269
+ illegal.push(i);
270
+ }
271
+ expect(() => argumentValueMerge({ a: illegal }, { a: [1, 2] }))
272
+ .toThrowError(
273
+ "Maximum array size exceeded: 256",
274
+ );
275
+ expect(() => argumentValueMerge({ a: [1, 2] }, { a: illegal }))
276
+ .toThrowError(
277
+ "Maximum array size exceeded:",
278
+ );
279
+ });
280
+
281
+ test("Maximum nesting depth asserted", () => {
282
+ const illegal = {
283
+ a: {
284
+ b: {
285
+ c: {
286
+ d: {
287
+ e: {
288
+ f: {
289
+ g: {
290
+ h: {
291
+ i: {
292
+ j: {
293
+ k: {
294
+ l: 1,
295
+ },
296
+ },
297
+ },
298
+ },
299
+ },
300
+ },
301
+ },
302
+ },
303
+ },
304
+ },
305
+ },
306
+ };
307
+ expect(() => argumentValueMerge(illegal, {})).toThrowError(
308
+ "Maximum complex option nesting depth exceeded: 11",
309
+ );
310
+ expect(() => argumentValueMerge({}, illegal)).toThrowError(
311
+ "Maximum complex option nesting depth exceeded: 11",
312
+ );
313
+ });
314
+ });