@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.
- package/.github/workflows/check-bun-dependencies.yml +9 -0
- package/.github/workflows/lint-pr-message.yml +11 -0
- package/.github/workflows/release-bun-library.yml +8 -0
- package/.github/workflows/validate-bun-library-pr.yml +8 -0
- package/LICENSE +21 -0
- package/README.md +1475 -0
- package/bun.lock +63 -0
- package/index.ts +89 -0
- package/package.json +23 -0
- package/src/api/CLI.ts +17 -0
- package/src/api/CLIConfig.ts +19 -0
- package/src/api/Context.ts +25 -0
- package/src/api/RunResult.ts +142 -0
- package/src/api/argument/Argument.ts +36 -0
- package/src/api/argument/ArgumentValueTypes.ts +87 -0
- package/src/api/argument/ComplexOption.ts +31 -0
- package/src/api/argument/GlobalCommandArgument.ts +17 -0
- package/src/api/argument/Option.ts +32 -0
- package/src/api/argument/Positional.ts +27 -0
- package/src/api/argument/SubCommandArgument.ts +20 -0
- package/src/api/command/Command.ts +22 -0
- package/src/api/command/GlobalCommand.ts +33 -0
- package/src/api/command/GlobalModifierCommand.ts +12 -0
- package/src/api/command/GroupCommand.ts +20 -0
- package/src/api/command/SubCommand.ts +41 -0
- package/src/api/command/UsageExample.ts +21 -0
- package/src/api/service/ServiceProvider.ts +52 -0
- package/src/api/service/core/AsciiBannerGeneratorService.ts +35 -0
- package/src/api/service/core/KeyValueService.ts +28 -0
- package/src/api/service/core/PrinterService.ts +266 -0
- package/src/api/service/core/ShutdownService.ts +12 -0
- package/src/api/service/core/SyntaxHighlighterService.ts +42 -0
- package/src/cli/BaseCLI.ts +312 -0
- package/src/cli/DefaultRuntimeCLI.ts +54 -0
- package/src/command/MultiCommandCliHelpCommand.ts +394 -0
- package/src/command/SingleCommandCliHelpCommand.ts +183 -0
- package/src/command/UsageCommand.ts +35 -0
- package/src/command/VersionCommand.ts +22 -0
- package/src/launcher.ts +127 -0
- package/src/runtime/DefaultContext.ts +32 -0
- package/src/runtime/argument/ArgumentTypeGuards.ts +8 -0
- package/src/runtime/command/CommandTypeGuards.ts +30 -0
- package/src/runtime/command/CommandValidator.ts +549 -0
- package/src/runtime/parser.ts +219 -0
- package/src/runtime/registry/CommandRegistry.ts +121 -0
- package/src/runtime/registry/DefaultCommandRegistry.ts +318 -0
- package/src/runtime/registry/DefaultServiceProviderRegistry.ts +26 -0
- package/src/runtime/registry/ServiceProviderRegistry.ts +11 -0
- package/src/runtime/runner.ts +697 -0
- package/src/runtime/scanner.ts +417 -0
- package/src/runtime/values/ValuePopulationResult.ts +41 -0
- package/src/runtime/values/argumentValueMerge.ts +201 -0
- package/src/runtime/values/argumentValueValidation.ts +610 -0
- package/src/runtime/values/globalCommandValuePopulation.ts +96 -0
- package/src/runtime/values/subCommandValuePopulation.ts +680 -0
- package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +45 -0
- package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +38 -0
- package/src/service/asciiBannerGenerator/standard.flf.json +3 -0
- package/src/service/banner/BannerServiceProvider.ts +99 -0
- package/src/service/banner/command/NoBannerCommand.ts +42 -0
- package/src/service/configuration/ConfigurationServiceProvider.ts +571 -0
- package/src/service/configuration/DefaultKeyValueService.ts +60 -0
- package/src/service/configuration/command/ConfigCommand.ts +43 -0
- package/src/service/configuration/command/DumpConfigCommand.ts +47 -0
- package/src/service/printer/DefaultPrinterService.ts +256 -0
- package/src/service/printer/PrinterServiceProvider.ts +61 -0
- package/src/service/printer/command/DarkModeCommand.ts +43 -0
- package/src/service/printer/command/LogLevelCommand.ts +68 -0
- package/src/service/printer/command/NoColorCommand.ts +43 -0
- package/src/service/printer/terminal/Ansi.ts +10 -0
- package/src/service/printer/terminal/Color.ts +14 -0
- package/src/service/printer/terminal/Progress.ts +373 -0
- package/src/service/printer/terminal/Spinner.ts +100 -0
- package/src/service/printer/terminal/Styler.ts +5 -0
- package/src/service/printer/terminal/Terminal.ts +8 -0
- package/src/service/printer/terminal/Theme.ts +34 -0
- package/src/service/printer/terminal/TtyStyler.ts +39 -0
- package/src/service/printer/terminal/TtyTerminal.ts +65 -0
- package/src/service/shutdown/DefaultShutdownService.ts +9 -0
- package/src/service/shutdown/ShutdownServiceProvider.ts +55 -0
- package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +52 -0
- package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +51 -0
- package/src/util/configHelper.ts +95 -0
- package/src/util/envVarHelper.ts +338 -0
- package/src/util/helpHelper.ts +751 -0
- package/src/util/logger.ts +84 -0
- package/src/util/runnerHelper.ts +112 -0
- package/tests/cli/BaseCLI.test.ts +344 -0
- package/tests/command/MultiCommandCliHelpCommand.test.ts +650 -0
- package/tests/command/SingleCommandCliHelpCommand.test.ts +384 -0
- package/tests/command/UsageCommand.test.ts +53 -0
- package/tests/command/VersionCommand.test.ts +36 -0
- package/tests/fixtures/CLIConfig.ts +9 -0
- package/tests/fixtures/Command.ts +229 -0
- package/tests/fixtures/CommandRegistry.ts +8 -0
- package/tests/fixtures/ConfigurationServiceProvider.ts +28 -0
- package/tests/fixtures/Context.ts +33 -0
- package/tests/fixtures/ServiceProviderRegistry.ts +16 -0
- package/tests/fixtures/StreamString.ts +37 -0
- package/tests/fixtures/util.ts +41 -0
- package/tests/runtime/DefaultContext.test.ts +20 -0
- package/tests/runtime/argument/ArgumentTypeGuards.test.ts +49 -0
- package/tests/runtime/command/CommandTypeGuards.test.ts +43 -0
- package/tests/runtime/command/CommandValidator.test.ts +816 -0
- package/tests/runtime/parser.test.ts +766 -0
- package/tests/runtime/registry/DefaultCommandRegistry.test.ts +166 -0
- package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +42 -0
- package/tests/runtime/runner.test.ts +1298 -0
- package/tests/runtime/scanner.test.ts +1113 -0
- package/tests/runtime/values/argumentValueMerge.test.ts +314 -0
- package/tests/runtime/values/argumentValueValidation.test.ts +1020 -0
- package/tests/runtime/values/globalCommandValuePopulation.test.ts +662 -0
- package/tests/runtime/values/subCommandValuePopulation.test.ts +2658 -0
- package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +22 -0
- package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +70 -0
- package/tests/service/asciiBannerGenerator/__snapshots__/DefaultAsciiBannerGeneratorService.test.ts.snap +22 -0
- package/tests/service/asciiBannerGenerator/small.flf.json +3 -0
- package/tests/service/configuration/ConfigurationServiceProvider.test.ts +249 -0
- package/tests/service/configuration/DefaultKeyValueService.test.ts +65 -0
- package/tests/service/launchBanner/BannerServiceProvider.test.ts +49 -0
- package/tests/service/launchBanner/__snapshots__/BannerServiceProvider.test.ts.snap +3 -0
- package/tests/service/launchBanner/command/NoBannerCommand.test.ts +21 -0
- package/tests/service/printer/DefaultPrinterService.test.ts +409 -0
- package/tests/service/printer/PrinterServiceProvider.test.ts +29 -0
- package/tests/service/printer/command/LogLevelCommand.test.ts +58 -0
- package/tests/service/printer/terminal/Progress.test.ts +40 -0
- package/tests/service/printer/terminal/Spinner.test.ts +57 -0
- package/tests/service/shutdown/ShutdownServiceProvider.test.ts +13 -0
- package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +123 -0
- package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +41 -0
- package/tests/util/configHelper.test.ts +275 -0
- package/tests/util/envVarHelper.test.ts +318 -0
- package/tests/util/logger.test.ts +10 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import DefaultCommandRegistry from "../../../src/runtime/registry/DefaultCommandRegistry.ts";
|
|
3
|
+
import {
|
|
4
|
+
getGlobalCommand,
|
|
5
|
+
getGlobalCommandWithShortAlias,
|
|
6
|
+
getGlobalModifierCommand,
|
|
7
|
+
getGroupCommand,
|
|
8
|
+
} from "../../fixtures/Command.ts";
|
|
9
|
+
import type SubCommand from "../../../src/api/command/SubCommand.ts";
|
|
10
|
+
import type Positional from "../../../src/api/argument/Positional.ts";
|
|
11
|
+
import type Option from "../../../src/api/argument/Option.ts";
|
|
12
|
+
|
|
13
|
+
function getSubCommand(
|
|
14
|
+
name: string,
|
|
15
|
+
options: Option[],
|
|
16
|
+
positionals: Positional[],
|
|
17
|
+
): SubCommand {
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
options,
|
|
21
|
+
positionals,
|
|
22
|
+
execute: async (): Promise<void> => {},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
describe("DefaultCommandRegistry Tests", () => {
|
|
26
|
+
test("Check for duplicate non-global command name", () => {
|
|
27
|
+
const command1 = getSubCommand("c1", [], []);
|
|
28
|
+
const command2 = getSubCommand("c1", [], []);
|
|
29
|
+
const commandRegistry = new DefaultCommandRegistry();
|
|
30
|
+
|
|
31
|
+
commandRegistry.addCommand(command1);
|
|
32
|
+
expect(() => commandRegistry.addCommand(command2)).toThrow();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("Check for duplicate sub-command and group command name", () => {
|
|
36
|
+
const command1 = getGroupCommand("c1");
|
|
37
|
+
const command2 = getSubCommand("c1", [], []);
|
|
38
|
+
const commandRegistry = new DefaultCommandRegistry();
|
|
39
|
+
|
|
40
|
+
commandRegistry.addCommand(command1);
|
|
41
|
+
expect(() => commandRegistry.addCommand(command2)).toThrow();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("Check for duplicate global command name", () => {
|
|
45
|
+
const command1 = getGlobalCommand("c1");
|
|
46
|
+
const command2 = getGlobalCommand("c1");
|
|
47
|
+
const commandRegistry = new DefaultCommandRegistry();
|
|
48
|
+
|
|
49
|
+
commandRegistry.addCommand(command1);
|
|
50
|
+
expect(() => commandRegistry.addCommand(command2)).toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("Allow duplicate command name between sub-command and global command", () => {
|
|
54
|
+
const subCommand = getSubCommand("c1", [], []);
|
|
55
|
+
const globalCommand = getGlobalCommand("c1");
|
|
56
|
+
const commandRegistry = new DefaultCommandRegistry();
|
|
57
|
+
|
|
58
|
+
commandRegistry.addCommand(subCommand);
|
|
59
|
+
commandRegistry.addCommand(globalCommand);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("Getters work as expected", () => {
|
|
63
|
+
const service1Id = "service1";
|
|
64
|
+
const service2Id = "service2";
|
|
65
|
+
const subCommand1 = getSubCommand("sc1", [], []);
|
|
66
|
+
const subCommand2 = getSubCommand("sc2", [], []);
|
|
67
|
+
const memberSubCommand1 = getSubCommand("msc1", [], []);
|
|
68
|
+
const memberSubCommand2 = getSubCommand("msc2", [], []);
|
|
69
|
+
const groupCommand1 = getGroupCommand("gc1", [memberSubCommand1]);
|
|
70
|
+
const groupCommand2 = getGroupCommand("gc2", [memberSubCommand2]);
|
|
71
|
+
const globalCommand1 = getGlobalCommandWithShortAlias("gc1", "1");
|
|
72
|
+
const globalCommand2 = getGlobalCommandWithShortAlias("gc2", "2");
|
|
73
|
+
const globalModifierCommand1 = getGlobalModifierCommand("gmc1", "3");
|
|
74
|
+
const globalModifierCommand2 = getGlobalModifierCommand("gmc2", "4");
|
|
75
|
+
const globalModifierCommand3 = getGlobalModifierCommand("gmc3", "5");
|
|
76
|
+
const globalModifierCommand4 = getGlobalModifierCommand("gmc4", "6");
|
|
77
|
+
|
|
78
|
+
const commandRegistry = new DefaultCommandRegistry();
|
|
79
|
+
|
|
80
|
+
commandRegistry.addCommand(subCommand1);
|
|
81
|
+
commandRegistry.addCommand(subCommand2);
|
|
82
|
+
commandRegistry.addCommand(groupCommand1);
|
|
83
|
+
commandRegistry.addCommand(groupCommand2);
|
|
84
|
+
commandRegistry.addCommand(globalCommand1);
|
|
85
|
+
commandRegistry.addCommand(globalCommand2);
|
|
86
|
+
commandRegistry.addCommand(globalModifierCommand1);
|
|
87
|
+
commandRegistry.addCommand(globalModifierCommand2);
|
|
88
|
+
commandRegistry.addCommand(globalModifierCommand3, service1Id);
|
|
89
|
+
commandRegistry.addCommand(globalModifierCommand4, service2Id);
|
|
90
|
+
|
|
91
|
+
expect(
|
|
92
|
+
commandRegistry.getSubCommandByName(subCommand2.name)!.name,
|
|
93
|
+
).toEqual(
|
|
94
|
+
subCommand2.name,
|
|
95
|
+
);
|
|
96
|
+
expect(
|
|
97
|
+
commandRegistry.getGroupCommandByName(groupCommand2.name)!.name,
|
|
98
|
+
).toEqual(
|
|
99
|
+
groupCommand2.name,
|
|
100
|
+
);
|
|
101
|
+
expect(
|
|
102
|
+
commandRegistry.getGlobalCommandByName(globalCommand2.name)!.name,
|
|
103
|
+
).toEqual(
|
|
104
|
+
globalCommand2.name,
|
|
105
|
+
);
|
|
106
|
+
expect(
|
|
107
|
+
commandRegistry.getGlobalModifierCommandByName(
|
|
108
|
+
globalModifierCommand2.name,
|
|
109
|
+
)!.name,
|
|
110
|
+
).toEqual(
|
|
111
|
+
globalModifierCommand2.name,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const result1 = commandRegistry
|
|
115
|
+
.getGroupCommandAndMemberSubCommandByJoinedName(
|
|
116
|
+
`${groupCommand2.name}:${memberSubCommand2.name}`,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
expect(result1!.groupCommand.name).toEqual(groupCommand2.name);
|
|
120
|
+
expect(result1!.command.name).toEqual(memberSubCommand2.name);
|
|
121
|
+
|
|
122
|
+
const result2 = commandRegistry.getGroupAndMemberCommandsByJoinedName();
|
|
123
|
+
const result3 = result2!.get(
|
|
124
|
+
`${groupCommand2.name}:${memberSubCommand2.name}`,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
expect(result3!.groupCommand.name).toEqual(groupCommand2.name);
|
|
128
|
+
expect(result3!.command.name).toEqual(memberSubCommand2.name);
|
|
129
|
+
|
|
130
|
+
const result4 = commandRegistry
|
|
131
|
+
.getGlobalModifierCommandsByNameNotProvidedByService();
|
|
132
|
+
const result5 = result4!.get(globalModifierCommand2.name);
|
|
133
|
+
|
|
134
|
+
expect(result5!.name).toEqual(globalModifierCommand2.name);
|
|
135
|
+
|
|
136
|
+
const result6 = commandRegistry
|
|
137
|
+
.getGlobalModifierCommandsByShortAliasNotProvidedByService();
|
|
138
|
+
const result7 = result6!.get(globalModifierCommand2.shortAlias!);
|
|
139
|
+
|
|
140
|
+
expect(result7!.name).toEqual(globalModifierCommand2.name);
|
|
141
|
+
|
|
142
|
+
const result8 = commandRegistry.getGlobalCommandsByShortAlias();
|
|
143
|
+
const result9 = result8!.get(globalCommand2.shortAlias!);
|
|
144
|
+
|
|
145
|
+
expect(result9!.name).toEqual(globalCommand2.name);
|
|
146
|
+
|
|
147
|
+
const result10 = commandRegistry.getNonModifierCommandsByName();
|
|
148
|
+
const result11 = result10!.get(subCommand2.name);
|
|
149
|
+
const result12 = result10!.get(globalCommand2.name);
|
|
150
|
+
|
|
151
|
+
expect(result11!.name).toEqual(subCommand2.name);
|
|
152
|
+
expect(result12!.name).toEqual(globalCommand2.name);
|
|
153
|
+
|
|
154
|
+
const result13 = commandRegistry
|
|
155
|
+
.getGlobalModifierCommandsByNameProvidedByService(service1Id);
|
|
156
|
+
const result14 = result13!.get(globalModifierCommand3.name);
|
|
157
|
+
|
|
158
|
+
expect(result14!.name).toEqual(globalModifierCommand3.name);
|
|
159
|
+
|
|
160
|
+
const result15 = commandRegistry
|
|
161
|
+
.getGlobalModifierCommandsByShortAliasProvidedByService(service2Id);
|
|
162
|
+
const result16 = result15!.get(globalModifierCommand4.shortAlias!);
|
|
163
|
+
|
|
164
|
+
expect(result16!.name).toEqual(globalModifierCommand4.name);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import type {
|
|
3
|
+
ServiceInfo,
|
|
4
|
+
ServiceProvider,
|
|
5
|
+
} from "../../../src/api/service/ServiceProvider.ts";
|
|
6
|
+
import DefaultServiceProviderRegistry from "../../../src/runtime/registry/DefaultServiceProviderRegistry.ts";
|
|
7
|
+
import type Context from "../../../src/api/Context.ts";
|
|
8
|
+
import type CLIConfig from "../../../src/api/CLIConfig.ts";
|
|
9
|
+
|
|
10
|
+
function getServiceProvider(
|
|
11
|
+
serviceId: string,
|
|
12
|
+
servicePriority: number,
|
|
13
|
+
): ServiceProvider {
|
|
14
|
+
return {
|
|
15
|
+
serviceId,
|
|
16
|
+
servicePriority,
|
|
17
|
+
provide(_cliConfig: CLIConfig): Promise<ServiceInfo> {
|
|
18
|
+
return Promise.resolve({
|
|
19
|
+
service: {},
|
|
20
|
+
commands: [],
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
initService(_context: Context): Promise<void> {
|
|
24
|
+
return Promise.resolve(undefined);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("DefaultServiceProviderRegistry Tests", () => {
|
|
30
|
+
test("Check for ordering of service providers", () => {
|
|
31
|
+
const serviceProvider1 = getServiceProvider("foo1", 1);
|
|
32
|
+
const serviceProvider2 = getServiceProvider("foo2", 2);
|
|
33
|
+
const serviceProviderRegistry = new DefaultServiceProviderRegistry();
|
|
34
|
+
|
|
35
|
+
serviceProviderRegistry.addServiceProvider(serviceProvider1);
|
|
36
|
+
serviceProviderRegistry.addServiceProvider(serviceProvider2);
|
|
37
|
+
|
|
38
|
+
const orderedServices = serviceProviderRegistry.getServiceProviders();
|
|
39
|
+
expect(orderedServices[0].servicePriority).toEqual(2);
|
|
40
|
+
expect(orderedServices[1].servicePriority).toEqual(1);
|
|
41
|
+
});
|
|
42
|
+
});
|