@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,318 @@
1
+ import process from "node:process";
2
+ import { describe, expect, test } from "bun:test";
3
+ import { getCLIConfig } from "../fixtures/CLIConfig.ts";
4
+ import {
5
+ getGlobalCommand,
6
+ getGlobalModifierCommandWithArgument,
7
+ getSubCommandWithComplexOptions,
8
+ getSubCommandWithOption,
9
+ getSubCommandWithPositional,
10
+ } from "../fixtures/Command.ts";
11
+ import {
12
+ getGlobalCommandValueFromEnvVars,
13
+ getSubCommandValuesFromEnvVars,
14
+ } from "../../src/util/envVarHelper.ts";
15
+ import { ArgumentValueTypeName } from "../../src/api/argument/ArgumentValueTypes.ts";
16
+
17
+ describe("envVarHelper Tests", () => {
18
+ test("getGlobalCommandValuesFromEnvVars works", () => {
19
+ try {
20
+ let command = getGlobalCommand("blah", true);
21
+
22
+ expect(
23
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
24
+ ).toBeUndefined();
25
+
26
+ command = getGlobalCommand("blah", true, false, true);
27
+
28
+ expect(
29
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
30
+ ).toBeUndefined();
31
+
32
+ process.env["FOO_BLAH"] = "foo";
33
+
34
+ expect(
35
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
36
+ ).toEqual(
37
+ "foo",
38
+ );
39
+
40
+ command = getGlobalCommand("blah", true, false, true, "FOO_BAR");
41
+
42
+ expect(
43
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
44
+ ).toBeUndefined();
45
+
46
+ process.env["FOO_BAR"] = "foo";
47
+
48
+ expect(
49
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
50
+ ).toEqual(
51
+ "foo",
52
+ );
53
+
54
+ command = getGlobalModifierCommandWithArgument(
55
+ "FOO_BAR",
56
+ "m",
57
+ 1,
58
+ {
59
+ type: ArgumentValueTypeName.BOOLEAN,
60
+ configurationKey: "FOO_BAR",
61
+ },
62
+ true,
63
+ );
64
+
65
+ // any env var value should set boolean option to true
66
+ process.env["FOO_BAR"] = "foo";
67
+
68
+ expect(
69
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
70
+ ).toEqual(
71
+ "true",
72
+ );
73
+
74
+ // empty env var value should set boolean option to false
75
+ process.env["FOO_BAR"] = "";
76
+
77
+ expect(
78
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
79
+ ).toEqual(
80
+ "false",
81
+ );
82
+
83
+ // no env var value should not set boolean option to false
84
+ delete process.env["FOO_BAR"];
85
+
86
+ expect(
87
+ getGlobalCommandValueFromEnvVars(getCLIConfig(), command),
88
+ ).toBeUndefined();
89
+ } finally {
90
+ delete process.env["FOO_BLAH_VALUE"];
91
+ delete process.env["FOO_BAR"];
92
+ }
93
+ });
94
+
95
+ test("getSubCommandValuesFromEnvVars works for simple option", () => {
96
+ try {
97
+ let command = getSubCommandWithOption("blah", true, false);
98
+
99
+ expect(
100
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
101
+ ).toBeUndefined();
102
+
103
+ command = getSubCommandWithOption(
104
+ "blah",
105
+ true,
106
+ false,
107
+ false,
108
+ ArgumentValueTypeName.STRING,
109
+ undefined,
110
+ true,
111
+ );
112
+
113
+ expect(
114
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
115
+ ).toBeUndefined();
116
+
117
+ process.env["FOO_BLAH_FOO"] = "bar";
118
+
119
+ expect(
120
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
121
+ ).toEqual(
122
+ { foo: "bar" },
123
+ );
124
+
125
+ command = getSubCommandWithOption(
126
+ "blah",
127
+ true,
128
+ false,
129
+ false,
130
+ ArgumentValueTypeName.STRING,
131
+ undefined,
132
+ true,
133
+ "FOO_BAR",
134
+ );
135
+
136
+ expect(
137
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
138
+ ).toBeUndefined();
139
+
140
+ process.env["FOO_BAR"] = "bar";
141
+
142
+ expect(
143
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
144
+ ).toEqual(
145
+ { foo: "bar" },
146
+ );
147
+
148
+ command = getSubCommandWithOption(
149
+ "blah",
150
+ true,
151
+ false,
152
+ false,
153
+ ArgumentValueTypeName.BOOLEAN,
154
+ undefined,
155
+ true,
156
+ "FOO_BAR",
157
+ );
158
+
159
+ // any env var value should set boolean option to true
160
+ process.env["FOO_BAR"] = "foo";
161
+
162
+ expect(
163
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
164
+ ).toEqual(
165
+ { foo: "true" },
166
+ );
167
+
168
+ // empty env var value should set boolean option to false
169
+ process.env["FOO_BAR"] = "";
170
+
171
+ expect(
172
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
173
+ ).toEqual(
174
+ { foo: "false" },
175
+ );
176
+
177
+ delete process.env["FOO_BAR"];
178
+
179
+ // no env var value should not set boolean option to false
180
+ expect(
181
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
182
+ ).toBeUndefined();
183
+ } finally {
184
+ delete process.env["FOO_BLAH_FOO"];
185
+ delete process.env["FOO_BAR"];
186
+ }
187
+ });
188
+
189
+ test("getSubCommandValuesFromEnvVars works for positional", () => {
190
+ try {
191
+ let command = getSubCommandWithPositional("blah", true, false);
192
+
193
+ expect(
194
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
195
+ ).toBeUndefined();
196
+
197
+ command = getSubCommandWithPositional(
198
+ "blah",
199
+ true,
200
+ false,
201
+ ArgumentValueTypeName.STRING,
202
+ true,
203
+ );
204
+
205
+ expect(
206
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
207
+ ).toBeUndefined();
208
+
209
+ process.env["FOO_BLAH_FOO"] = "bar";
210
+
211
+ expect(
212
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
213
+ ).toEqual(
214
+ { foo: "bar" },
215
+ );
216
+
217
+ command = getSubCommandWithPositional(
218
+ "blah",
219
+ true,
220
+ false,
221
+ ArgumentValueTypeName.STRING,
222
+ true,
223
+ "FOO_BAR",
224
+ );
225
+
226
+ expect(
227
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
228
+ ).toBeUndefined();
229
+
230
+ process.env["FOO_BAR"] = "bar";
231
+
232
+ expect(
233
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
234
+ ).toEqual(
235
+ { foo: "bar" },
236
+ );
237
+
238
+ command = getSubCommandWithPositional(
239
+ "blah",
240
+ true,
241
+ false,
242
+ ArgumentValueTypeName.BOOLEAN,
243
+ true,
244
+ "FOO_BAR",
245
+ );
246
+
247
+ // any env var value should set boolean option to true
248
+ process.env["FOO_BAR"] = "foo";
249
+
250
+ expect(
251
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
252
+ ).toEqual(
253
+ { foo: "true" },
254
+ );
255
+
256
+ // empty env var value should set boolean option to false
257
+ process.env["FOO_BAR"] = "";
258
+
259
+ expect(
260
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
261
+ ).toEqual(
262
+ { foo: "false" },
263
+ );
264
+
265
+ // no env var value should not set boolean option to false
266
+ delete process.env["FOO_BAR"];
267
+
268
+ expect(
269
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
270
+ ).toBeUndefined();
271
+ } finally {
272
+ delete process.env["FOO_BLAH_FOO"];
273
+ delete process.env["FOO_BAR"];
274
+ }
275
+ });
276
+
277
+ test("getSubCommandValuesFromEnvVars works for complex option", () => {
278
+ try {
279
+ const command = getSubCommandWithComplexOptions(true, true);
280
+
281
+ expect(
282
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
283
+ ).toBeUndefined();
284
+
285
+ process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_GAMMA"] = "bar1";
286
+ process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_DELTA_0"] = "bar2";
287
+
288
+ expect(
289
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
290
+ ).toEqual(
291
+ { alpha: [{ beta: [{ delta: ["bar2"], gamma: "bar1" }] }] },
292
+ );
293
+ } finally {
294
+ delete process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_GAMMA"];
295
+ delete process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_DELTA_0"];
296
+ }
297
+ });
298
+
299
+ test("getSubCommandValuesFromEnvVars ignores partially matched complex option", () => {
300
+ try {
301
+ const command = getSubCommandWithComplexOptions(true);
302
+
303
+ expect(
304
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
305
+ ).toBeUndefined();
306
+
307
+ process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_GAMMA"] = "bar1";
308
+ process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_DELTA_0"] = "bar2";
309
+
310
+ expect(
311
+ getSubCommandValuesFromEnvVars(getCLIConfig(), command),
312
+ ).toBeUndefined();
313
+ } finally {
314
+ delete process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_GAMMA"];
315
+ delete process.env["FOO_SUBCOMMAND_ALPHA_0_BETA_0_DELTA_0"];
316
+ }
317
+ });
318
+ });
@@ -0,0 +1,10 @@
1
+ import { describe, test } from "bun:test";
2
+ import getLogger from "../../src/util/logger.ts";
3
+
4
+ describe("logger Tests", () => {
5
+ test("Can acquire a logger", () => {
6
+ const logger = getLogger("logger test");
7
+
8
+ logger.debug("foobar");
9
+ });
10
+ });