@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,229 @@
|
|
|
1
|
+
import type GroupCommand from "../../src/api/command/GroupCommand.ts";
|
|
2
|
+
import type GlobalCommand from "../../src/api/command/GlobalCommand.ts";
|
|
3
|
+
import type SubCommand from "../../src/api/command/SubCommand.ts";
|
|
4
|
+
import {
|
|
5
|
+
ArgumentValueTypeName,
|
|
6
|
+
ComplexValueTypeName,
|
|
7
|
+
} from "../../src/api/argument/ArgumentValueTypes.ts";
|
|
8
|
+
import type ComplexOption from "../../src/api/argument/ComplexOption.ts";
|
|
9
|
+
import type Positional from "../../src/api/argument/Positional.ts";
|
|
10
|
+
import type GlobalCommandArgument from "../../src/api/argument/GlobalCommandArgument.ts";
|
|
11
|
+
import type GlobalModifierCommand from "../../src/api/command/GlobalModifierCommand.ts";
|
|
12
|
+
import type Option from "../../src/api/argument/Option.ts";
|
|
13
|
+
|
|
14
|
+
export function getGroupCommand(
|
|
15
|
+
name = "groupCommand",
|
|
16
|
+
memberSubCommands = [getSubCommandWithOption("foo")],
|
|
17
|
+
): GroupCommand {
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
memberSubCommands,
|
|
21
|
+
execute: async (): Promise<void> => {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getGlobalModifierCommand(
|
|
26
|
+
name = "globalModifierCommand",
|
|
27
|
+
shortAlias: string | undefined = undefined,
|
|
28
|
+
withArg = false,
|
|
29
|
+
mandatoryArg = false,
|
|
30
|
+
): GlobalModifierCommand {
|
|
31
|
+
return {
|
|
32
|
+
name,
|
|
33
|
+
shortAlias,
|
|
34
|
+
executePriority: 1,
|
|
35
|
+
argument: withArg
|
|
36
|
+
? {
|
|
37
|
+
type: ArgumentValueTypeName.STRING,
|
|
38
|
+
isOptional: !mandatoryArg,
|
|
39
|
+
}
|
|
40
|
+
: undefined,
|
|
41
|
+
execute: async (): Promise<void> => {},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function getGlobalModifierCommandWithArgument(
|
|
46
|
+
name: string,
|
|
47
|
+
shortAlias: string,
|
|
48
|
+
executePriority = 1,
|
|
49
|
+
argument?: GlobalCommandArgument,
|
|
50
|
+
enableConfiguration = false,
|
|
51
|
+
): GlobalModifierCommand {
|
|
52
|
+
return {
|
|
53
|
+
name,
|
|
54
|
+
enableConfiguration,
|
|
55
|
+
shortAlias,
|
|
56
|
+
executePriority,
|
|
57
|
+
argument,
|
|
58
|
+
execute: async (): Promise<void> => {},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getGlobalCommand(
|
|
63
|
+
name = "globalCommand",
|
|
64
|
+
withArg = false,
|
|
65
|
+
mandatoryArg = false,
|
|
66
|
+
enableConfiguration = false,
|
|
67
|
+
configurationKey?: string,
|
|
68
|
+
): GlobalCommand {
|
|
69
|
+
return {
|
|
70
|
+
name,
|
|
71
|
+
enableConfiguration,
|
|
72
|
+
argument: withArg
|
|
73
|
+
? {
|
|
74
|
+
type: ArgumentValueTypeName.STRING,
|
|
75
|
+
isOptional: !mandatoryArg,
|
|
76
|
+
configurationKey,
|
|
77
|
+
}
|
|
78
|
+
: undefined,
|
|
79
|
+
execute: async (): Promise<void> => {},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getGlobalCommandWithShortAlias(
|
|
84
|
+
name: string,
|
|
85
|
+
shortAlias: string,
|
|
86
|
+
argument?: GlobalCommandArgument,
|
|
87
|
+
): GlobalCommand {
|
|
88
|
+
return {
|
|
89
|
+
name,
|
|
90
|
+
shortAlias,
|
|
91
|
+
argument,
|
|
92
|
+
execute: async (): Promise<void> => {},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getSubCommandWithOptionAndPositional(): SubCommand {
|
|
97
|
+
return {
|
|
98
|
+
name: "subCommand",
|
|
99
|
+
options: [{
|
|
100
|
+
name: "goo",
|
|
101
|
+
shortAlias: "g",
|
|
102
|
+
type: ArgumentValueTypeName.STRING,
|
|
103
|
+
}],
|
|
104
|
+
positionals: [{
|
|
105
|
+
name: "foo",
|
|
106
|
+
type: ArgumentValueTypeName.STRING,
|
|
107
|
+
}],
|
|
108
|
+
execute: async (): Promise<void> => {},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getSubCommand(
|
|
113
|
+
name: string,
|
|
114
|
+
options: Array<Option | ComplexOption>,
|
|
115
|
+
positionals: Array<Positional> = [],
|
|
116
|
+
enableConfiguration = false,
|
|
117
|
+
): SubCommand {
|
|
118
|
+
return {
|
|
119
|
+
name,
|
|
120
|
+
options,
|
|
121
|
+
positionals,
|
|
122
|
+
enableConfiguration,
|
|
123
|
+
execute: async (): Promise<void> => {},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function getSubCommandWithOption(
|
|
128
|
+
name = "subCommand",
|
|
129
|
+
withArg = false,
|
|
130
|
+
mandatoryArg = false,
|
|
131
|
+
multiple = false,
|
|
132
|
+
type: ArgumentValueTypeName = ArgumentValueTypeName.STRING,
|
|
133
|
+
defaultValue?: string,
|
|
134
|
+
enableConfiguration = false,
|
|
135
|
+
configurationKey?: string,
|
|
136
|
+
): SubCommand {
|
|
137
|
+
return {
|
|
138
|
+
name,
|
|
139
|
+
description: "good",
|
|
140
|
+
enableConfiguration,
|
|
141
|
+
options: withArg
|
|
142
|
+
? [{
|
|
143
|
+
name: "foo",
|
|
144
|
+
type,
|
|
145
|
+
isOptional: !mandatoryArg,
|
|
146
|
+
isArray: multiple,
|
|
147
|
+
defaultValue,
|
|
148
|
+
configurationKey,
|
|
149
|
+
}]
|
|
150
|
+
: [],
|
|
151
|
+
positionals: [],
|
|
152
|
+
execute: async (): Promise<void> => {},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function getSubCommandWithPositional(
|
|
157
|
+
name: string,
|
|
158
|
+
optional = false,
|
|
159
|
+
multiple = false,
|
|
160
|
+
type: ArgumentValueTypeName = ArgumentValueTypeName.STRING,
|
|
161
|
+
enableConfiguration = false,
|
|
162
|
+
configurationKey?: string,
|
|
163
|
+
): SubCommand {
|
|
164
|
+
return {
|
|
165
|
+
name,
|
|
166
|
+
description: "good",
|
|
167
|
+
enableConfiguration,
|
|
168
|
+
options: [],
|
|
169
|
+
positionals: [{
|
|
170
|
+
name: "foo",
|
|
171
|
+
type,
|
|
172
|
+
isVarargOptional: optional,
|
|
173
|
+
isVarargMultiple: multiple,
|
|
174
|
+
configurationKey,
|
|
175
|
+
}],
|
|
176
|
+
execute: async (): Promise<void> => {},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function getSubCommandWithComplexOptions(
|
|
181
|
+
enableConfiguration = false,
|
|
182
|
+
betaIsArray = false,
|
|
183
|
+
deltaIsArray = false,
|
|
184
|
+
): SubCommand {
|
|
185
|
+
return {
|
|
186
|
+
name: "subCommand",
|
|
187
|
+
enableConfiguration,
|
|
188
|
+
options: [{
|
|
189
|
+
name: "alpha",
|
|
190
|
+
shortAlias: "a",
|
|
191
|
+
type: ComplexValueTypeName.COMPLEX,
|
|
192
|
+
isArray: true,
|
|
193
|
+
properties: [{
|
|
194
|
+
name: "beta",
|
|
195
|
+
shortAlias: "b",
|
|
196
|
+
type: ComplexValueTypeName.COMPLEX,
|
|
197
|
+
isArray: betaIsArray,
|
|
198
|
+
properties: [{
|
|
199
|
+
name: "gamma",
|
|
200
|
+
shortAlias: "g",
|
|
201
|
+
type: ArgumentValueTypeName.STRING,
|
|
202
|
+
}, {
|
|
203
|
+
name: "delta",
|
|
204
|
+
shortAlias: "d",
|
|
205
|
+
type: ArgumentValueTypeName.NUMBER,
|
|
206
|
+
isArray: true,
|
|
207
|
+
}],
|
|
208
|
+
}],
|
|
209
|
+
}, {
|
|
210
|
+
name: "epsilon",
|
|
211
|
+
shortAlias: "e",
|
|
212
|
+
type: ComplexValueTypeName.COMPLEX,
|
|
213
|
+
properties: [{
|
|
214
|
+
name: "gamma",
|
|
215
|
+
shortAlias: "g",
|
|
216
|
+
type: ArgumentValueTypeName.STRING,
|
|
217
|
+
configurationKey: "FOO_BAR_A",
|
|
218
|
+
}, {
|
|
219
|
+
name: "delta",
|
|
220
|
+
shortAlias: "d",
|
|
221
|
+
type: ArgumentValueTypeName.NUMBER,
|
|
222
|
+
configurationKey: "FOO_BAR_B",
|
|
223
|
+
isArray: deltaIsArray,
|
|
224
|
+
}],
|
|
225
|
+
}],
|
|
226
|
+
positionals: [],
|
|
227
|
+
execute: async (): Promise<void> => {},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import DefaultCommandRegistry from "../../src/runtime/registry/DefaultCommandRegistry.ts";
|
|
2
|
+
import type Command from "../../src/api/command/Command.ts";
|
|
3
|
+
|
|
4
|
+
export function getCommandRegistry(
|
|
5
|
+
commands?: Array<Command>,
|
|
6
|
+
): DefaultCommandRegistry {
|
|
7
|
+
return new DefaultCommandRegistry(commands);
|
|
8
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import ConfigurationServiceProvider from "../../src/service/configuration/ConfigurationServiceProvider.ts";
|
|
2
|
+
import type {
|
|
3
|
+
ArgumentSingleValueType,
|
|
4
|
+
ArgumentValues,
|
|
5
|
+
} from "../../src/api/argument/ArgumentValueTypes.ts";
|
|
6
|
+
import type Context from "../../src/api/Context.ts";
|
|
7
|
+
|
|
8
|
+
class DummyConfigurationServiceProvider extends ConfigurationServiceProvider {
|
|
9
|
+
constructor(
|
|
10
|
+
servicePriority: number,
|
|
11
|
+
defaultsData: Map<string, ArgumentValues | ArgumentSingleValueType>,
|
|
12
|
+
) {
|
|
13
|
+
super(servicePriority, false, true);
|
|
14
|
+
|
|
15
|
+
this.defaultsData = defaultsData;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public override initService(_context: Context): Promise<void> {
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getConfigurationServiceProvider(
|
|
24
|
+
servicePriority: number,
|
|
25
|
+
defaultsData: Map<string, ArgumentValues | ArgumentSingleValueType>,
|
|
26
|
+
) {
|
|
27
|
+
return new DummyConfigurationServiceProvider(servicePriority, defaultsData);
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import DefaultContext from "../../src/runtime/DefaultContext.ts";
|
|
2
|
+
import { getCLIConfig } from "./CLIConfig.ts";
|
|
3
|
+
import { PRINTER_SERVICE_ID } from "../../src/api/service/core/PrinterService.ts";
|
|
4
|
+
import DefaultPrinterService from "../../src/service/printer/DefaultPrinterService.ts";
|
|
5
|
+
import DefaultKeyValueService from "../../src/service/configuration/DefaultKeyValueService.ts";
|
|
6
|
+
import { KEY_VALUE_SERVICE_ID } from "../../src/api/service/core/KeyValueService.ts";
|
|
7
|
+
import type Context from "../../src/api/Context.ts";
|
|
8
|
+
import WritableStreamString from "./StreamString.ts";
|
|
9
|
+
import TtyTerminal from "../../src/service/printer/terminal/TtyTerminal.ts";
|
|
10
|
+
import TtyStyler from "../../src/service/printer/terminal/TtyStyler.ts";
|
|
11
|
+
|
|
12
|
+
export function getContext(
|
|
13
|
+
streamString: WritableStreamString,
|
|
14
|
+
): Context {
|
|
15
|
+
const defaultContext = new DefaultContext(getCLIConfig());
|
|
16
|
+
const defaultPrinterService = new DefaultPrinterService(
|
|
17
|
+
streamString.writableStream,
|
|
18
|
+
streamString.writableStream,
|
|
19
|
+
false,
|
|
20
|
+
false,
|
|
21
|
+
new TtyTerminal(streamString.writeStream),
|
|
22
|
+
new TtyStyler(3),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
defaultPrinterService.colorEnabled = false;
|
|
26
|
+
defaultContext.addServiceInstance(PRINTER_SERVICE_ID, defaultPrinterService);
|
|
27
|
+
defaultContext.addServiceInstance(
|
|
28
|
+
KEY_VALUE_SERVICE_ID,
|
|
29
|
+
new DefaultKeyValueService(),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return defaultContext;
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import DefaultServiceProviderRegistry from "../../src/runtime/registry/DefaultServiceProviderRegistry.ts";
|
|
2
|
+
import type ServiceProviderRegistry from "../../src/runtime/registry/ServiceProviderRegistry.ts";
|
|
3
|
+
import type { ServiceProvider } from "../../src/api/service/ServiceProvider.ts";
|
|
4
|
+
|
|
5
|
+
export function getServiceProviderRegistry(
|
|
6
|
+
serviceProviders?: Array<ServiceProvider>,
|
|
7
|
+
): ServiceProviderRegistry {
|
|
8
|
+
const serviceProviderRegistry = new DefaultServiceProviderRegistry([]);
|
|
9
|
+
|
|
10
|
+
if (serviceProviders) {
|
|
11
|
+
serviceProviders.forEach((serviceProvider) =>
|
|
12
|
+
serviceProviderRegistry.addServiceProvider(serviceProvider)
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return serviceProviderRegistry;
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { WriteStream } from "node:tty";
|
|
3
|
+
import { PassThrough } from "node:stream";
|
|
4
|
+
import { WritableStream } from "node:stream/web";
|
|
5
|
+
|
|
6
|
+
export default class WritableStreamString {
|
|
7
|
+
private chunks: string[];
|
|
8
|
+
writableStream: WritableStream<Uint8Array>;
|
|
9
|
+
writeStream: WriteStream;
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
this.chunks = [];
|
|
13
|
+
|
|
14
|
+
this.writableStream = new WritableStream<Uint8Array>({
|
|
15
|
+
write: (chunk: Uint8Array) => {
|
|
16
|
+
const decoder = new TextDecoder();
|
|
17
|
+
const chunkString = decoder.decode(chunk);
|
|
18
|
+
this.chunks.push(chunkString);
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const passThrough = new PassThrough();
|
|
23
|
+
this.writeStream = passThrough as unknown as WriteStream;
|
|
24
|
+
|
|
25
|
+
passThrough.on("data", (chunk) => {
|
|
26
|
+
if (Buffer.isBuffer(chunk)) {
|
|
27
|
+
this.chunks.push(chunk.toString());
|
|
28
|
+
} else {
|
|
29
|
+
this.chunks.push(String(chunk));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getString(): string {
|
|
35
|
+
return this.chunks.join("");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { expect } from "bun:test";
|
|
2
|
+
import { stripVTControlCharacters } from "node:util";
|
|
3
|
+
import { WritableStream } from "node:stream/web";
|
|
4
|
+
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
|
|
7
|
+
export function expectStringIncludes(actual: string, expected: string) {
|
|
8
|
+
expect(stripVTControlCharacters(actual).includes(expected)).toBeTrue();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function expectStringNotIncludes(
|
|
12
|
+
actual: string,
|
|
13
|
+
expected: string,
|
|
14
|
+
) {
|
|
15
|
+
expect(stripVTControlCharacters(actual).includes(expected)).toBeFalse();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function expectStringEquals(actual: string, expected: string) {
|
|
19
|
+
expect(stripVTControlCharacters(actual)).toEqual(expected);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function expectBytesEquals(actual: string, expected: Uint8Array) {
|
|
23
|
+
expect(encoder.encode(actual)).toEqual(expected);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function sleep(ms: number) {
|
|
27
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function write(
|
|
31
|
+
writableStream: WritableStream,
|
|
32
|
+
message: string,
|
|
33
|
+
) {
|
|
34
|
+
const encoded = encoder.encode(message);
|
|
35
|
+
const writer = writableStream.getWriter();
|
|
36
|
+
|
|
37
|
+
await writer.ready;
|
|
38
|
+
await writer.write(encoded);
|
|
39
|
+
|
|
40
|
+
writer.releaseLock();
|
|
41
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import DefaultContext from "../../src/runtime/DefaultContext.ts";
|
|
3
|
+
import { getCLIConfig } from "../fixtures/CLIConfig.ts";
|
|
4
|
+
|
|
5
|
+
describe("DefaultContext Tests", () => {
|
|
6
|
+
test("Check for duplicate service ID", () => {
|
|
7
|
+
const context = new DefaultContext(getCLIConfig());
|
|
8
|
+
|
|
9
|
+
context.addServiceInstance("foo", {});
|
|
10
|
+
expect(() => context.addServiceInstance("foo", {})).toThrow();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("Check lookup by ID", () => {
|
|
14
|
+
const context = new DefaultContext(getCLIConfig());
|
|
15
|
+
|
|
16
|
+
context.addServiceInstance("foo", "bar");
|
|
17
|
+
|
|
18
|
+
expect(context.getServiceById("foo")).toEqual("bar");
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import type ComplexOption from "../../../src/api/argument/ComplexOption.ts";
|
|
3
|
+
import {
|
|
4
|
+
ArgumentValueTypeName,
|
|
5
|
+
ComplexValueTypeName,
|
|
6
|
+
} from "../../../src/api/argument/ArgumentValueTypes.ts";
|
|
7
|
+
import type Positional from "../../../src/api/argument/Positional.ts";
|
|
8
|
+
import type GlobalCommandArgument from "../../../src/api/argument/GlobalCommandArgument.ts";
|
|
9
|
+
import { isComplexOption } from "../../../src/runtime/argument/ArgumentTypeGuards.ts";
|
|
10
|
+
import type Option from "../../../src/api/argument/Option.ts";
|
|
11
|
+
|
|
12
|
+
function getComplexOption(): ComplexOption {
|
|
13
|
+
return {
|
|
14
|
+
name: "option",
|
|
15
|
+
type: ComplexValueTypeName.COMPLEX,
|
|
16
|
+
properties: [
|
|
17
|
+
getOption(),
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getOption(): Option {
|
|
23
|
+
return {
|
|
24
|
+
name: "option",
|
|
25
|
+
type: ArgumentValueTypeName.STRING,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getPositional(): Positional {
|
|
30
|
+
return {
|
|
31
|
+
name: "positional",
|
|
32
|
+
type: ArgumentValueTypeName.STRING,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getGlobalCommandArgument(): GlobalCommandArgument {
|
|
37
|
+
return {
|
|
38
|
+
type: ArgumentValueTypeName.STRING,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe("ArgumentTypeGuards Tests", () => {
|
|
43
|
+
test("isComplexOption works", () => {
|
|
44
|
+
expect(isComplexOption(getComplexOption())).toBeTrue();
|
|
45
|
+
expect(isComplexOption(getOption())).toBeFalse();
|
|
46
|
+
expect(isComplexOption(getPositional())).toBeFalse();
|
|
47
|
+
expect(isComplexOption(getGlobalCommandArgument())).toBeFalse();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
getGlobalCommand,
|
|
4
|
+
getGlobalModifierCommand,
|
|
5
|
+
getGroupCommand,
|
|
6
|
+
getSubCommandWithOption,
|
|
7
|
+
} from "../../fixtures/Command.ts";
|
|
8
|
+
import {
|
|
9
|
+
isGlobalCommand,
|
|
10
|
+
isGlobalModifierCommand,
|
|
11
|
+
isGroupCommand,
|
|
12
|
+
isSubCommand,
|
|
13
|
+
} from "../../../src/runtime/command/CommandTypeGuards.ts";
|
|
14
|
+
|
|
15
|
+
describe("CommandTypeGuards Tests", () => {
|
|
16
|
+
test("isSubCommand works", () => {
|
|
17
|
+
expect(isSubCommand(getSubCommandWithOption())).toBeTrue();
|
|
18
|
+
expect(isSubCommand(getGroupCommand())).toBeFalse();
|
|
19
|
+
expect(isSubCommand(getGlobalCommand())).toBeFalse();
|
|
20
|
+
expect(isSubCommand(getGlobalModifierCommand())).toBeFalse();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("isGroupCommand works", () => {
|
|
24
|
+
expect(isGroupCommand(getSubCommandWithOption())).toBeFalse();
|
|
25
|
+
expect(isGroupCommand(getGroupCommand())).toBeTrue();
|
|
26
|
+
expect(isGroupCommand(getGlobalCommand())).toBeFalse();
|
|
27
|
+
expect(isGroupCommand(getGlobalModifierCommand())).toBeFalse();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("isGlobalCommand works", () => {
|
|
31
|
+
expect(isGlobalCommand(getSubCommandWithOption())).toBeFalse();
|
|
32
|
+
expect(isGlobalCommand(getGroupCommand())).toBeFalse();
|
|
33
|
+
expect(isGlobalCommand(getGlobalCommand())).toBeTrue();
|
|
34
|
+
expect(isGlobalCommand(getGlobalModifierCommand())).toBeFalse();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("isGlobalModifierCommand works", () => {
|
|
38
|
+
expect(isGlobalModifierCommand(getSubCommandWithOption())).toBeFalse();
|
|
39
|
+
expect(isGlobalModifierCommand(getGroupCommand())).toBeFalse();
|
|
40
|
+
expect(isGlobalModifierCommand(getGlobalCommand())).toBeFalse();
|
|
41
|
+
expect(isGlobalModifierCommand(getGlobalModifierCommand())).toBeTrue();
|
|
42
|
+
});
|
|
43
|
+
});
|