effect 4.0.0-beta.10 → 4.0.0-beta.12
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/dist/Channel.d.ts +7 -7
- package/dist/Config.d.ts +157 -0
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +56 -1
- package/dist/Config.js.map +1 -1
- package/dist/Effect.d.ts +296 -8
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +72 -0
- package/dist/Effect.js.map +1 -1
- package/dist/ErrorReporter.d.ts +376 -0
- package/dist/ErrorReporter.d.ts.map +1 -0
- package/dist/ErrorReporter.js +246 -0
- package/dist/ErrorReporter.js.map +1 -0
- package/dist/Fiber.d.ts +2 -2
- package/dist/Fiber.d.ts.map +1 -1
- package/dist/Fiber.js.map +1 -1
- package/dist/Graph.d.ts.map +1 -1
- package/dist/Graph.js +3 -6
- package/dist/Graph.js.map +1 -1
- package/dist/LogLevel.d.ts +5 -0
- package/dist/LogLevel.d.ts.map +1 -1
- package/dist/LogLevel.js.map +1 -1
- package/dist/Logger.d.ts +25 -91
- package/dist/Logger.d.ts.map +1 -1
- package/dist/Logger.js +2 -3
- package/dist/Logger.js.map +1 -1
- package/dist/Queue.d.ts.map +1 -1
- package/dist/Queue.js +0 -1
- package/dist/Queue.js.map +1 -1
- package/dist/Random.d.ts +17 -0
- package/dist/Random.d.ts.map +1 -1
- package/dist/Random.js +17 -0
- package/dist/Random.js.map +1 -1
- package/dist/References.d.ts +3 -3
- package/dist/References.d.ts.map +1 -1
- package/dist/Schema.d.ts +3 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +2 -1
- package/dist/SchemaAST.js.map +1 -1
- package/dist/Stream.d.ts +5 -5
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/effect.js +98 -33
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/hashMap.js +2 -2
- package/dist/internal/hashMap.js.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js +86 -14
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +112 -36
- package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
- package/dist/unstable/ai/McpSchema.js +47 -10
- package/dist/unstable/ai/McpSchema.js.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +33 -6
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts +16 -0
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +14 -0
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/cli/CliOutput.js +37 -6
- package/dist/unstable/cli/CliOutput.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +199 -7
- package/dist/unstable/cli/Command.d.ts.map +1 -1
- package/dist/unstable/cli/Command.js +116 -6
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cli/HelpDoc.d.ts +60 -2
- package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.d.ts +11 -1
- package/dist/unstable/cli/internal/command.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.js +33 -8
- package/dist/unstable/cli/internal/command.js.map +1 -1
- package/dist/unstable/cli/internal/completions/CommandDescriptor.js +7 -2
- package/dist/unstable/cli/internal/completions/CommandDescriptor.js.map +1 -1
- package/dist/unstable/cli/internal/parser.js +10 -2
- package/dist/unstable/cli/internal/parser.js.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js +2 -2
- package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/unstable/http/Headers.d.ts.map +1 -1
- package/dist/unstable/http/Headers.js +27 -10
- package/dist/unstable/http/Headers.js.map +1 -1
- package/dist/unstable/http/HttpClient.d.ts +28 -4
- package/dist/unstable/http/HttpClient.d.ts.map +1 -1
- package/dist/unstable/http/HttpClient.js.map +1 -1
- package/dist/unstable/http/HttpEffect.d.ts +3 -8
- package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
- package/dist/unstable/http/HttpEffect.js +25 -31
- package/dist/unstable/http/HttpEffect.js.map +1 -1
- package/dist/unstable/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/unstable/http/HttpMiddleware.js +4 -8
- package/dist/unstable/http/HttpMiddleware.js.map +1 -1
- package/dist/unstable/http/HttpServerError.d.ts +14 -27
- package/dist/unstable/http/HttpServerError.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerError.js +37 -44
- package/dist/unstable/http/HttpServerError.js.map +1 -1
- package/dist/unstable/http/HttpServerRespondable.d.ts +2 -2
- package/dist/unstable/http/HttpServerRespondable.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRespondable.js +5 -5
- package/dist/unstable/http/HttpServerRespondable.js.map +1 -1
- package/dist/unstable/http/HttpServerResponse.d.ts +2 -1
- package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerResponse.js +2 -0
- package/dist/unstable/http/HttpServerResponse.js.map +1 -1
- package/dist/unstable/http/internal/preResponseHandler.d.ts +2 -0
- package/dist/unstable/http/internal/preResponseHandler.d.ts.map +1 -0
- package/dist/unstable/http/internal/preResponseHandler.js +10 -0
- package/dist/unstable/http/internal/preResponseHandler.js.map +1 -0
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiError.d.ts +11 -0
- package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiError.js +29 -9
- package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
- package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpLogger.js +7 -4
- package/dist/unstable/observability/OtlpLogger.js.map +1 -1
- package/dist/unstable/reactivity/Atom.js +1 -1
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.d.ts +6 -0
- package/dist/unstable/reactivity/AtomRegistry.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.js +22 -1
- package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
- package/dist/unstable/rpc/RpcSchema.d.ts +13 -0
- package/dist/unstable/rpc/RpcSchema.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSchema.js +14 -0
- package/dist/unstable/rpc/RpcSchema.js.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.js +34 -9
- package/dist/unstable/rpc/RpcSerialization.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts +0 -7
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +9 -10
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/workflow/WorkflowEngine.d.ts +6 -0
- package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/workflow/WorkflowEngine.js +131 -0
- package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +1 -1
- package/src/Channel.ts +9 -9
- package/src/Config.ts +171 -9
- package/src/Effect.ts +315 -8
- package/src/ErrorReporter.ts +459 -0
- package/src/Fiber.ts +9 -2
- package/src/Graph.ts +16 -6
- package/src/LogLevel.ts +6 -0
- package/src/Logger.ts +28 -95
- package/src/Queue.ts +0 -1
- package/src/Random.ts +18 -0
- package/src/References.ts +4 -4
- package/src/Schema.ts +1 -1
- package/src/SchemaAST.ts +2 -1
- package/src/Stream.ts +7 -7
- package/src/index.ts +5 -0
- package/src/internal/effect.ts +205 -49
- package/src/internal/hashMap.ts +2 -2
- package/src/unstable/ai/LanguageModel.ts +117 -16
- package/src/unstable/ai/McpSchema.ts +57 -11
- package/src/unstable/ai/McpServer.ts +44 -6
- package/src/unstable/ai/Tool.ts +15 -0
- package/src/unstable/cli/CliOutput.ts +45 -6
- package/src/unstable/cli/Command.ts +298 -11
- package/src/unstable/cli/HelpDoc.ts +68 -2
- package/src/unstable/cli/internal/command.ts +47 -11
- package/src/unstable/cli/internal/completions/CommandDescriptor.ts +7 -2
- package/src/unstable/cli/internal/parser.ts +11 -3
- package/src/unstable/cluster/ClusterWorkflowEngine.ts +2 -2
- package/src/unstable/http/Headers.ts +28 -13
- package/src/unstable/http/HttpClient.ts +45 -10
- package/src/unstable/http/HttpEffect.ts +30 -44
- package/src/unstable/http/HttpMiddleware.ts +4 -14
- package/src/unstable/http/HttpServerError.ts +42 -45
- package/src/unstable/http/HttpServerRespondable.ts +6 -6
- package/src/unstable/http/HttpServerResponse.ts +3 -1
- package/src/unstable/http/internal/preResponseHandler.ts +15 -0
- package/src/unstable/httpapi/HttpApiBuilder.ts +2 -1
- package/src/unstable/httpapi/HttpApiError.ts +30 -9
- package/src/unstable/observability/OtlpLogger.ts +9 -5
- package/src/unstable/reactivity/Atom.ts +1 -1
- package/src/unstable/reactivity/AtomRegistry.ts +29 -1
- package/src/unstable/rpc/RpcSchema.ts +17 -0
- package/src/unstable/rpc/RpcSerialization.ts +44 -9
- package/src/unstable/rpc/RpcServer.ts +14 -19
- package/src/unstable/workflow/WorkflowEngine.ts +178 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @since 4.0.0
|
|
3
3
|
*/
|
|
4
|
+
import type { NonEmptyArray, NonEmptyReadonlyArray } from "../../Array.ts"
|
|
4
5
|
import * as Console from "../../Console.ts"
|
|
5
6
|
import * as Effect from "../../Effect.ts"
|
|
6
7
|
import type * as FileSystem from "../../FileSystem.ts"
|
|
@@ -11,9 +12,9 @@ import type { Pipeable } from "../../Pipeable.ts"
|
|
|
11
12
|
import * as Predicate from "../../Predicate.ts"
|
|
12
13
|
import * as References from "../../References.ts"
|
|
13
14
|
import * as Result from "../../Result.ts"
|
|
14
|
-
import
|
|
15
|
+
import * as ServiceMap from "../../ServiceMap.ts"
|
|
15
16
|
import * as Terminal from "../../Terminal.ts"
|
|
16
|
-
import type { Simplify } from "../../Types.ts"
|
|
17
|
+
import type { NoInfer, Simplify } from "../../Types.ts"
|
|
17
18
|
import type { ChildProcessSpawner } from "../process/ChildProcessSpawner.ts"
|
|
18
19
|
import * as CliError from "./CliError.ts"
|
|
19
20
|
import * as CliOutput from "./CliOutput.ts"
|
|
@@ -94,16 +95,45 @@ export interface Command<Name extends string, Input, E = never, R = never> exten
|
|
|
94
95
|
*/
|
|
95
96
|
readonly description: string | undefined
|
|
96
97
|
|
|
98
|
+
/**
|
|
99
|
+
* An optional short description used when listing subcommands.
|
|
100
|
+
*/
|
|
101
|
+
readonly shortDescription: string | undefined
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Optional usage examples for the command.
|
|
105
|
+
*/
|
|
106
|
+
readonly examples: ReadonlyArray<Command.Example>
|
|
107
|
+
|
|
97
108
|
/**
|
|
98
109
|
* The subcommands available under this command.
|
|
99
110
|
*/
|
|
100
|
-
readonly subcommands: ReadonlyArray<
|
|
111
|
+
readonly subcommands: ReadonlyArray<{
|
|
112
|
+
readonly group: string | undefined
|
|
113
|
+
readonly commands: NonEmptyReadonlyArray<Command.Any>
|
|
114
|
+
}>
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Custom annotations associated with this command.
|
|
118
|
+
*/
|
|
119
|
+
readonly annotations: ServiceMap.ServiceMap<never>
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
/**
|
|
104
123
|
* @since 4.0.0
|
|
105
124
|
*/
|
|
106
125
|
export declare namespace Command {
|
|
126
|
+
/**
|
|
127
|
+
* Represents a concrete usage example for a command.
|
|
128
|
+
*
|
|
129
|
+
* @since 4.0.0
|
|
130
|
+
* @category models
|
|
131
|
+
*/
|
|
132
|
+
export interface Example {
|
|
133
|
+
readonly command: string
|
|
134
|
+
readonly description?: string | undefined
|
|
135
|
+
}
|
|
136
|
+
|
|
107
137
|
/**
|
|
108
138
|
* Configuration object for defining command flags, arguments, and nested structures.
|
|
109
139
|
*
|
|
@@ -209,6 +239,25 @@ export declare namespace Command {
|
|
|
209
239
|
* @category models
|
|
210
240
|
*/
|
|
211
241
|
export type Any = Command<string, unknown, unknown, unknown>
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* A grouped set of subcommands used by `Command.withSubcommands`.
|
|
245
|
+
*
|
|
246
|
+
* @since 4.0.0
|
|
247
|
+
* @category models
|
|
248
|
+
*/
|
|
249
|
+
export interface SubcommandGroup<Commands extends ReadonlyArray<Any> = ReadonlyArray<Any>> {
|
|
250
|
+
readonly group: string
|
|
251
|
+
readonly commands: Commands
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Entry type accepted by `Command.withSubcommands`.
|
|
256
|
+
*
|
|
257
|
+
* @since 4.0.0
|
|
258
|
+
* @category models
|
|
259
|
+
*/
|
|
260
|
+
export type SubcommandEntry = Any | SubcommandGroup<ReadonlyArray<Any>>
|
|
212
261
|
}
|
|
213
262
|
|
|
214
263
|
/**
|
|
@@ -644,6 +693,57 @@ export const withHandler: {
|
|
|
644
693
|
handler: (value: A) => Effect.Effect<void, E, R>
|
|
645
694
|
): Command<Name, A, E, R> => makeCommand({ ...toImpl(self), handle: handler }))
|
|
646
695
|
|
|
696
|
+
interface SubcommandGroupInternal {
|
|
697
|
+
readonly group: string | undefined
|
|
698
|
+
readonly commands: NonEmptyReadonlyArray<Command.Any>
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const normalizeSubcommandEntries = (
|
|
702
|
+
entries: ReadonlyArray<Command.SubcommandEntry>
|
|
703
|
+
): {
|
|
704
|
+
readonly flat: ReadonlyArray<Command.Any>
|
|
705
|
+
readonly groups: ReadonlyArray<SubcommandGroupInternal>
|
|
706
|
+
} => {
|
|
707
|
+
const flat: Array<Command.Any> = []
|
|
708
|
+
const grouped = new Map<string | undefined, NonEmptyArray<Command.Any>>()
|
|
709
|
+
|
|
710
|
+
const addToGroup = (group: string | undefined, command: Command.Any): void => {
|
|
711
|
+
flat.push(command)
|
|
712
|
+
const existing = grouped.get(group)
|
|
713
|
+
if (existing) {
|
|
714
|
+
existing.push(command)
|
|
715
|
+
} else {
|
|
716
|
+
grouped.set(group, [command])
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
for (const entry of entries) {
|
|
721
|
+
if (isCommand(entry)) {
|
|
722
|
+
addToGroup(undefined, entry)
|
|
723
|
+
continue
|
|
724
|
+
}
|
|
725
|
+
for (const command of entry.commands) {
|
|
726
|
+
addToGroup(entry.group, command)
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
const groups: Array<SubcommandGroupInternal> = []
|
|
731
|
+
const ungroupedCommands = grouped.get(undefined)
|
|
732
|
+
|
|
733
|
+
if (ungroupedCommands && ungroupedCommands.length > 0) {
|
|
734
|
+
groups.push({ group: undefined, commands: ungroupedCommands })
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
for (const [group, commands] of grouped) {
|
|
738
|
+
if (group === undefined) {
|
|
739
|
+
continue
|
|
740
|
+
}
|
|
741
|
+
groups.push({ group, commands })
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
return { flat, groups }
|
|
745
|
+
}
|
|
746
|
+
|
|
647
747
|
/**
|
|
648
748
|
* Adds subcommands to a command, creating a hierarchical command structure.
|
|
649
749
|
*
|
|
@@ -717,7 +817,7 @@ export const withSubcommands: {
|
|
|
717
817
|
* @since 4.0.0
|
|
718
818
|
* @category combinators
|
|
719
819
|
*/
|
|
720
|
-
<const Subcommands extends ReadonlyArray<Command
|
|
820
|
+
<const Subcommands extends ReadonlyArray<Command.SubcommandEntry>>(subcommands: Subcommands): <Name extends string, Input, E, R>(
|
|
721
821
|
self: Command<Name, Input, E, R>
|
|
722
822
|
) => Command<
|
|
723
823
|
Name,
|
|
@@ -766,7 +866,7 @@ export const withSubcommands: {
|
|
|
766
866
|
Input,
|
|
767
867
|
E,
|
|
768
868
|
R,
|
|
769
|
-
const Subcommands extends ReadonlyArray<Command
|
|
869
|
+
const Subcommands extends ReadonlyArray<Command.SubcommandEntry>
|
|
770
870
|
>(self: Command<Name, Input, E, R>, subcommands: Subcommands): Command<
|
|
771
871
|
Name,
|
|
772
872
|
Input,
|
|
@@ -778,7 +878,7 @@ export const withSubcommands: {
|
|
|
778
878
|
Input,
|
|
779
879
|
E,
|
|
780
880
|
R,
|
|
781
|
-
const Subcommands extends ReadonlyArray<Command
|
|
881
|
+
const Subcommands extends ReadonlyArray<Command.SubcommandEntry>
|
|
782
882
|
>(
|
|
783
883
|
self: Command<Name, Input, E, R>,
|
|
784
884
|
subcommands: Subcommands
|
|
@@ -788,10 +888,11 @@ export const withSubcommands: {
|
|
|
788
888
|
E | ExtractSubcommandErrors<Subcommands>,
|
|
789
889
|
R | Exclude<ExtractSubcommandContext<Subcommands>, CommandContext<Name>>
|
|
790
890
|
> => {
|
|
791
|
-
|
|
891
|
+
const normalized = normalizeSubcommandEntries(subcommands)
|
|
892
|
+
checkForDuplicateFlags(self, normalized.flat)
|
|
792
893
|
|
|
793
894
|
const impl = toImpl(self)
|
|
794
|
-
const byName = new Map(
|
|
895
|
+
const byName = new Map(normalized.flat.map((s) => [s.name, toImpl(s)] as const))
|
|
795
896
|
|
|
796
897
|
// Internal type for routing - not exposed in public type
|
|
797
898
|
type SubcommandInfo = { readonly name: string; readonly result: unknown }
|
|
@@ -832,16 +933,22 @@ export const withSubcommands: {
|
|
|
832
933
|
name: impl.name,
|
|
833
934
|
config: impl.config,
|
|
834
935
|
description: impl.description,
|
|
936
|
+
shortDescription: impl.shortDescription,
|
|
937
|
+
annotations: impl.annotations,
|
|
938
|
+
examples: impl.examples,
|
|
835
939
|
service: impl.service,
|
|
836
|
-
subcommands,
|
|
940
|
+
subcommands: normalized.groups,
|
|
837
941
|
parse,
|
|
838
942
|
handle
|
|
839
943
|
})
|
|
840
944
|
})
|
|
841
945
|
|
|
842
946
|
// Type extractors for subcommand arrays - T[number] gives union of all elements
|
|
843
|
-
type
|
|
844
|
-
|
|
947
|
+
type ExtractSubcommand<T> = T extends Command<any, any, any, any> ? T
|
|
948
|
+
: T extends Command.SubcommandGroup<infer Commands> ? Commands[number]
|
|
949
|
+
: never
|
|
950
|
+
type ExtractSubcommandErrors<T extends ReadonlyArray<Command.SubcommandEntry>> = Error<ExtractSubcommand<T[number]>>
|
|
951
|
+
type ExtractSubcommandContext<T extends ReadonlyArray<Command.SubcommandEntry>> = ExtractSubcommand<T[number]> extends
|
|
845
952
|
Command<any, any, any, infer R> ? R : never
|
|
846
953
|
|
|
847
954
|
/**
|
|
@@ -926,6 +1033,186 @@ export const withDescription: {
|
|
|
926
1033
|
description: string
|
|
927
1034
|
) => makeCommand({ ...toImpl(self), description }))
|
|
928
1035
|
|
|
1036
|
+
/**
|
|
1037
|
+
* Sets a short description for a command.
|
|
1038
|
+
*
|
|
1039
|
+
* Short descriptions are used when listing subcommands in help output and
|
|
1040
|
+
* shell completions. If no short description is provided, the full
|
|
1041
|
+
* `description` is used as a fallback.
|
|
1042
|
+
*
|
|
1043
|
+
* @since 4.0.0
|
|
1044
|
+
* @category combinators
|
|
1045
|
+
*/
|
|
1046
|
+
export const withShortDescription: {
|
|
1047
|
+
/**
|
|
1048
|
+
* Sets a short description for a command.
|
|
1049
|
+
*
|
|
1050
|
+
* Short descriptions are used when listing subcommands in help output and
|
|
1051
|
+
* shell completions. If no short description is provided, the full
|
|
1052
|
+
* `description` is used as a fallback.
|
|
1053
|
+
*
|
|
1054
|
+
* @since 4.0.0
|
|
1055
|
+
* @category combinators
|
|
1056
|
+
*/
|
|
1057
|
+
(shortDescription: string): <const Name extends string, Input, E, R>(
|
|
1058
|
+
self: Command<Name, Input, E, R>
|
|
1059
|
+
) => Command<Name, Input, E, R>
|
|
1060
|
+
/**
|
|
1061
|
+
* Sets a short description for a command.
|
|
1062
|
+
*
|
|
1063
|
+
* Short descriptions are used when listing subcommands in help output and
|
|
1064
|
+
* shell completions. If no short description is provided, the full
|
|
1065
|
+
* `description` is used as a fallback.
|
|
1066
|
+
*
|
|
1067
|
+
* @since 4.0.0
|
|
1068
|
+
* @category combinators
|
|
1069
|
+
*/
|
|
1070
|
+
<const Name extends string, Input, E, R>(self: Command<Name, Input, E, R>, shortDescription: string): Command<Name, Input, E, R>
|
|
1071
|
+
} = dual(2, <const Name extends string, Input, E, R>(
|
|
1072
|
+
self: Command<Name, Input, E, R>,
|
|
1073
|
+
shortDescription: string
|
|
1074
|
+
) => makeCommand({ ...toImpl(self), shortDescription }))
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Adds a custom annotation to a command.
|
|
1078
|
+
*
|
|
1079
|
+
* @since 4.0.0
|
|
1080
|
+
* @category combinators
|
|
1081
|
+
*/
|
|
1082
|
+
export const annotate: {
|
|
1083
|
+
/**
|
|
1084
|
+
* Adds a custom annotation to a command.
|
|
1085
|
+
*
|
|
1086
|
+
* @since 4.0.0
|
|
1087
|
+
* @category combinators
|
|
1088
|
+
*/
|
|
1089
|
+
<I, S>(service: ServiceMap.Service<I, S>, value: NoInfer<S>): <Name extends string, Input, E, R>(
|
|
1090
|
+
self: Command<Name, Input, E, R>
|
|
1091
|
+
) => Command<Name, Input, E, R>
|
|
1092
|
+
/**
|
|
1093
|
+
* Adds a custom annotation to a command.
|
|
1094
|
+
*
|
|
1095
|
+
* @since 4.0.0
|
|
1096
|
+
* @category combinators
|
|
1097
|
+
*/
|
|
1098
|
+
<Name extends string, Input, E, R, I, S>(
|
|
1099
|
+
self: Command<Name, Input, E, R>,
|
|
1100
|
+
service: ServiceMap.Service<I, S>,
|
|
1101
|
+
value: NoInfer<S>
|
|
1102
|
+
): Command<Name, Input, E, R>
|
|
1103
|
+
} = dual(3, <Name extends string, Input, E, R, I, S>(
|
|
1104
|
+
self: Command<Name, Input, E, R>,
|
|
1105
|
+
service: ServiceMap.Service<I, S>,
|
|
1106
|
+
value: NoInfer<S>
|
|
1107
|
+
) => {
|
|
1108
|
+
const impl = toImpl(self)
|
|
1109
|
+
return makeCommand({ ...impl, annotations: ServiceMap.add(impl.annotations, service, value) })
|
|
1110
|
+
})
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* Merges a ServiceMap of annotations into a command.
|
|
1114
|
+
*
|
|
1115
|
+
* @since 4.0.0
|
|
1116
|
+
* @category combinators
|
|
1117
|
+
*/
|
|
1118
|
+
export const annotateMerge: {
|
|
1119
|
+
/**
|
|
1120
|
+
* Merges a ServiceMap of annotations into a command.
|
|
1121
|
+
*
|
|
1122
|
+
* @since 4.0.0
|
|
1123
|
+
* @category combinators
|
|
1124
|
+
*/
|
|
1125
|
+
<I>(annotations: ServiceMap.ServiceMap<I>): <Name extends string, Input, E, R>(
|
|
1126
|
+
self: Command<Name, Input, E, R>
|
|
1127
|
+
) => Command<Name, Input, E, R>
|
|
1128
|
+
/**
|
|
1129
|
+
* Merges a ServiceMap of annotations into a command.
|
|
1130
|
+
*
|
|
1131
|
+
* @since 4.0.0
|
|
1132
|
+
* @category combinators
|
|
1133
|
+
*/
|
|
1134
|
+
<Name extends string, Input, E, R, I>(self: Command<Name, Input, E, R>, annotations: ServiceMap.ServiceMap<I>): Command<Name, Input, E, R>
|
|
1135
|
+
} = dual(2, <Name extends string, Input, E, R, I>(
|
|
1136
|
+
self: Command<Name, Input, E, R>,
|
|
1137
|
+
annotations: ServiceMap.ServiceMap<I>
|
|
1138
|
+
) => {
|
|
1139
|
+
const impl = toImpl(self)
|
|
1140
|
+
return makeCommand({ ...impl, annotations: ServiceMap.merge(impl.annotations, annotations) })
|
|
1141
|
+
})
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Sets usage examples for a command.
|
|
1145
|
+
*
|
|
1146
|
+
* Examples are exposed in structured `HelpDoc` data and rendered by the
|
|
1147
|
+
* default formatter in an `EXAMPLES` section.
|
|
1148
|
+
*
|
|
1149
|
+
* @example
|
|
1150
|
+
* ```ts
|
|
1151
|
+
* import { Command } from "effect/unstable/cli"
|
|
1152
|
+
*
|
|
1153
|
+
* const login = Command.make("login").pipe(
|
|
1154
|
+
* Command.withExamples([
|
|
1155
|
+
* { command: "myapp login", description: "Log in with browser OAuth" },
|
|
1156
|
+
* { command: "myapp login --token sbp_abc123", description: "Log in with a token" }
|
|
1157
|
+
* ])
|
|
1158
|
+
* )
|
|
1159
|
+
* ```
|
|
1160
|
+
*
|
|
1161
|
+
* @since 4.0.0
|
|
1162
|
+
* @category combinators
|
|
1163
|
+
*/
|
|
1164
|
+
export const withExamples: {
|
|
1165
|
+
/**
|
|
1166
|
+
* Sets usage examples for a command.
|
|
1167
|
+
*
|
|
1168
|
+
* Examples are exposed in structured `HelpDoc` data and rendered by the
|
|
1169
|
+
* default formatter in an `EXAMPLES` section.
|
|
1170
|
+
*
|
|
1171
|
+
* @example
|
|
1172
|
+
* ```ts
|
|
1173
|
+
* import { Command } from "effect/unstable/cli"
|
|
1174
|
+
*
|
|
1175
|
+
* const login = Command.make("login").pipe(
|
|
1176
|
+
* Command.withExamples([
|
|
1177
|
+
* { command: "myapp login", description: "Log in with browser OAuth" },
|
|
1178
|
+
* { command: "myapp login --token sbp_abc123", description: "Log in with a token" }
|
|
1179
|
+
* ])
|
|
1180
|
+
* )
|
|
1181
|
+
* ```
|
|
1182
|
+
*
|
|
1183
|
+
* @since 4.0.0
|
|
1184
|
+
* @category combinators
|
|
1185
|
+
*/
|
|
1186
|
+
(examples: ReadonlyArray<Command.Example>): <const Name extends string, Input, E, R>(
|
|
1187
|
+
self: Command<Name, Input, E, R>
|
|
1188
|
+
) => Command<Name, Input, E, R>
|
|
1189
|
+
/**
|
|
1190
|
+
* Sets usage examples for a command.
|
|
1191
|
+
*
|
|
1192
|
+
* Examples are exposed in structured `HelpDoc` data and rendered by the
|
|
1193
|
+
* default formatter in an `EXAMPLES` section.
|
|
1194
|
+
*
|
|
1195
|
+
* @example
|
|
1196
|
+
* ```ts
|
|
1197
|
+
* import { Command } from "effect/unstable/cli"
|
|
1198
|
+
*
|
|
1199
|
+
* const login = Command.make("login").pipe(
|
|
1200
|
+
* Command.withExamples([
|
|
1201
|
+
* { command: "myapp login", description: "Log in with browser OAuth" },
|
|
1202
|
+
* { command: "myapp login --token sbp_abc123", description: "Log in with a token" }
|
|
1203
|
+
* ])
|
|
1204
|
+
* )
|
|
1205
|
+
* ```
|
|
1206
|
+
*
|
|
1207
|
+
* @since 4.0.0
|
|
1208
|
+
* @category combinators
|
|
1209
|
+
*/
|
|
1210
|
+
<const Name extends string, Input, E, R>(self: Command<Name, Input, E, R>, examples: ReadonlyArray<Command.Example>): Command<Name, Input, E, R>
|
|
1211
|
+
} = dual(2, <const Name extends string, Input, E, R>(
|
|
1212
|
+
self: Command<Name, Input, E, R>,
|
|
1213
|
+
examples: ReadonlyArray<Command.Example>
|
|
1214
|
+
) => makeCommand({ ...toImpl(self), examples }))
|
|
1215
|
+
|
|
929
1216
|
/* ========================================================================== */
|
|
930
1217
|
/* Providing Services */
|
|
931
1218
|
/* ========================================================================== */
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* @since 4.0.0
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { NonEmptyReadonlyArray } from "../../Array.ts"
|
|
6
|
+
import type * as ServiceMap from "../../ServiceMap.ts"
|
|
7
|
+
|
|
5
8
|
/**
|
|
6
9
|
* Structured representation of help documentation for a command.
|
|
7
10
|
* This data structure is independent of formatting, allowing for
|
|
@@ -9,11 +12,13 @@
|
|
|
9
12
|
*
|
|
10
13
|
* @example
|
|
11
14
|
* ```ts
|
|
15
|
+
* import { ServiceMap } from "effect"
|
|
12
16
|
* import type * as HelpDoc from "effect/unstable/cli/HelpDoc"
|
|
13
17
|
*
|
|
14
18
|
* const deployCommandHelp: HelpDoc.HelpDoc = {
|
|
15
19
|
* description: "Deploy your application to the cloud",
|
|
16
20
|
* usage: "myapp deploy [options] <target>",
|
|
21
|
+
* annotations: ServiceMap.empty(),
|
|
17
22
|
* flags: [
|
|
18
23
|
* {
|
|
19
24
|
* name: "verbose",
|
|
@@ -62,6 +67,11 @@ export interface HelpDoc {
|
|
|
62
67
|
*/
|
|
63
68
|
readonly flags: ReadonlyArray<FlagDoc>
|
|
64
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Custom command annotations.
|
|
72
|
+
*/
|
|
73
|
+
readonly annotations: ServiceMap.ServiceMap<never>
|
|
74
|
+
|
|
65
75
|
/**
|
|
66
76
|
* List of positional arguments for this command
|
|
67
77
|
*/
|
|
@@ -70,7 +80,30 @@ export interface HelpDoc {
|
|
|
70
80
|
/**
|
|
71
81
|
* Optional list of subcommands if this is a parent command
|
|
72
82
|
*/
|
|
73
|
-
readonly subcommands?: ReadonlyArray<
|
|
83
|
+
readonly subcommands?: ReadonlyArray<SubcommandGroupDoc>
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Optional concrete usage examples for the command
|
|
87
|
+
*/
|
|
88
|
+
readonly examples?: ReadonlyArray<ExampleDoc>
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Documentation for a command usage example
|
|
93
|
+
*
|
|
94
|
+
* @since 4.0.0
|
|
95
|
+
* @category models
|
|
96
|
+
*/
|
|
97
|
+
export interface ExampleDoc {
|
|
98
|
+
/**
|
|
99
|
+
* Command line invocation example
|
|
100
|
+
*/
|
|
101
|
+
readonly command: string
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Optional explanation for the example
|
|
105
|
+
*/
|
|
106
|
+
readonly description?: string | undefined
|
|
74
107
|
}
|
|
75
108
|
|
|
76
109
|
/**
|
|
@@ -132,15 +165,18 @@ export interface FlagDoc {
|
|
|
132
165
|
*
|
|
133
166
|
* @example
|
|
134
167
|
* ```ts
|
|
168
|
+
* import { ServiceMap } from "effect"
|
|
135
169
|
* import type { HelpDoc } from "effect/unstable/cli"
|
|
136
170
|
*
|
|
137
171
|
* const deploySubcommand: HelpDoc.SubcommandDoc = {
|
|
138
172
|
* name: "deploy",
|
|
173
|
+
* shortDescription: "Deploy app",
|
|
139
174
|
* description: "Deploy the application to the cloud"
|
|
140
175
|
* }
|
|
141
176
|
*
|
|
142
177
|
* const buildSubcommand: HelpDoc.SubcommandDoc = {
|
|
143
178
|
* name: "build",
|
|
179
|
+
* shortDescription: undefined,
|
|
144
180
|
* description: "Build the application for production"
|
|
145
181
|
* }
|
|
146
182
|
*
|
|
@@ -148,8 +184,12 @@ export interface FlagDoc {
|
|
|
148
184
|
* const mainCommandHelp: HelpDoc.HelpDoc = {
|
|
149
185
|
* description: "Cloud deployment tool",
|
|
150
186
|
* usage: "myapp <command> [options]",
|
|
187
|
+
* annotations: ServiceMap.empty(),
|
|
151
188
|
* flags: [],
|
|
152
|
-
* subcommands: [
|
|
189
|
+
* subcommands: [{
|
|
190
|
+
* group: undefined,
|
|
191
|
+
* commands: [deploySubcommand, buildSubcommand]
|
|
192
|
+
* }]
|
|
153
193
|
* }
|
|
154
194
|
* ```
|
|
155
195
|
*
|
|
@@ -162,17 +202,42 @@ export interface SubcommandDoc {
|
|
|
162
202
|
*/
|
|
163
203
|
readonly name: string
|
|
164
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Optional short description of what the subcommand does.
|
|
207
|
+
*/
|
|
208
|
+
readonly shortDescription: string | undefined
|
|
209
|
+
|
|
165
210
|
/**
|
|
166
211
|
* Brief description of what the subcommand does
|
|
167
212
|
*/
|
|
168
213
|
readonly description: string
|
|
169
214
|
}
|
|
170
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Documentation for a grouped subcommand listing
|
|
218
|
+
*
|
|
219
|
+
* @since 4.0.0
|
|
220
|
+
* @category models
|
|
221
|
+
*/
|
|
222
|
+
export interface SubcommandGroupDoc {
|
|
223
|
+
/**
|
|
224
|
+
* Group name used in help output.
|
|
225
|
+
* Undefined means the default ungrouped section.
|
|
226
|
+
*/
|
|
227
|
+
readonly group: string | undefined
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Subcommands in this group.
|
|
231
|
+
*/
|
|
232
|
+
readonly commands: NonEmptyReadonlyArray<SubcommandDoc>
|
|
233
|
+
}
|
|
234
|
+
|
|
171
235
|
/**
|
|
172
236
|
* Documentation for a positional argument
|
|
173
237
|
*
|
|
174
238
|
* @example
|
|
175
239
|
* ```ts
|
|
240
|
+
* import { ServiceMap } from "effect"
|
|
176
241
|
* import type { HelpDoc } from "effect/unstable/cli"
|
|
177
242
|
*
|
|
178
243
|
* const sourceArg: HelpDoc.ArgDoc = {
|
|
@@ -195,6 +260,7 @@ export interface SubcommandDoc {
|
|
|
195
260
|
* const copyCommandHelp: HelpDoc.HelpDoc = {
|
|
196
261
|
* description: "Copy files from source to destination",
|
|
197
262
|
* usage: "copy <source> [files...]",
|
|
263
|
+
* annotations: ServiceMap.empty(),
|
|
198
264
|
* flags: [],
|
|
199
265
|
* args: [sourceArg, filesArg]
|
|
200
266
|
* }
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* Internal implementation details for CLI commands.
|
|
6
6
|
* Public API is in ../Command.ts
|
|
7
7
|
*/
|
|
8
|
+
import * as Arr from "../../../Array.ts"
|
|
8
9
|
import * as Effect from "../../../Effect.ts"
|
|
9
10
|
import { YieldableProto } from "../../../internal/core.ts"
|
|
10
11
|
import { pipeArguments } from "../../../Pipeable.ts"
|
|
11
12
|
import * as Predicate from "../../../Predicate.ts"
|
|
12
13
|
import * as ServiceMap from "../../../ServiceMap.ts"
|
|
13
14
|
import * as CliError from "../CliError.ts"
|
|
14
|
-
import type { ArgDoc, FlagDoc, HelpDoc,
|
|
15
|
+
import type { ArgDoc, ExampleDoc, FlagDoc, HelpDoc, SubcommandGroupDoc } from "../HelpDoc.ts"
|
|
15
16
|
import * as Param from "../Param.ts"
|
|
16
17
|
import * as Primitive from "../Primitive.ts"
|
|
17
18
|
import { type ConfigInternal, reconstructTree } from "./config.ts"
|
|
@@ -22,6 +23,11 @@ import { type ConfigInternal, reconstructTree } from "./config.ts"
|
|
|
22
23
|
|
|
23
24
|
import type { Command, CommandContext, Environment, ParsedTokens } from "../Command.ts"
|
|
24
25
|
|
|
26
|
+
interface SubcommandGroup {
|
|
27
|
+
readonly group: string | undefined
|
|
28
|
+
readonly commands: Arr.NonEmptyReadonlyArray<Command<any, unknown, unknown, unknown>>
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
/**
|
|
26
32
|
* Internal implementation interface with all the machinery.
|
|
27
33
|
* Use toImpl() to access from internal code.
|
|
@@ -29,6 +35,7 @@ import type { Command, CommandContext, Environment, ParsedTokens } from "../Comm
|
|
|
29
35
|
export interface CommandInternal<Name extends string, Input, E, R> extends Command<Name, Input, E, R> {
|
|
30
36
|
readonly config: ConfigInternal
|
|
31
37
|
readonly service: ServiceMap.Service<CommandContext<Name>, Input>
|
|
38
|
+
readonly annotations: ServiceMap.ServiceMap<never>
|
|
32
39
|
readonly parse: (input: ParsedTokens) => Effect.Effect<Input, CliError.CliError, Environment>
|
|
33
40
|
readonly handle: (
|
|
34
41
|
input: Input,
|
|
@@ -80,8 +87,11 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
80
87
|
readonly name: Name
|
|
81
88
|
readonly config: ConfigInternal
|
|
82
89
|
readonly service?: ServiceMap.Service<CommandContext<Name>, Input> | undefined
|
|
90
|
+
readonly annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
83
91
|
readonly description?: string | undefined
|
|
84
|
-
readonly
|
|
92
|
+
readonly shortDescription?: string | undefined
|
|
93
|
+
readonly examples?: ReadonlyArray<Command.Example> | undefined
|
|
94
|
+
readonly subcommands?: ReadonlyArray<SubcommandGroup> | undefined
|
|
85
95
|
readonly parse?: ((input: ParsedTokens) => Effect.Effect<Input, CliError.CliError, Environment>) | undefined
|
|
86
96
|
readonly handle?:
|
|
87
97
|
| ((input: Input, commandPath: ReadonlyArray<string>) => Effect.Effect<void, E, R | Environment>)
|
|
@@ -89,6 +99,8 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
89
99
|
}): Command<Name, Input, E, R> => {
|
|
90
100
|
const service = options.service ?? ServiceMap.Service<CommandContext<Name>, Input>(`${TypeId}/${options.name}`)
|
|
91
101
|
const config = options.config
|
|
102
|
+
const annotations = options.annotations ?? ServiceMap.empty()
|
|
103
|
+
const subcommands = options.subcommands ?? []
|
|
92
104
|
|
|
93
105
|
const handle = (
|
|
94
106
|
input: Input,
|
|
@@ -123,8 +135,7 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
let usage = commandPath.length > 0 ? commandPath.join(" ") : options.name
|
|
126
|
-
|
|
127
|
-
if (subcommands.length > 0) {
|
|
138
|
+
if (subcommands.some((group) => group.commands.length > 0)) {
|
|
128
139
|
usage += " <subcommand>"
|
|
129
140
|
}
|
|
130
141
|
usage += " [flags]"
|
|
@@ -147,24 +158,38 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
147
158
|
}
|
|
148
159
|
}
|
|
149
160
|
|
|
150
|
-
const subcommandDocs: Array<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
const subcommandDocs: Array<SubcommandGroupDoc> = []
|
|
162
|
+
|
|
163
|
+
for (const group of subcommands) {
|
|
164
|
+
subcommandDocs.push({
|
|
165
|
+
group: group.group,
|
|
166
|
+
commands: Arr.map(group.commands, (subcommand) => ({
|
|
167
|
+
name: subcommand.name,
|
|
168
|
+
shortDescription: subcommand.shortDescription,
|
|
169
|
+
description: subcommand.description ?? ""
|
|
170
|
+
}))
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const examples: ReadonlyArray<ExampleDoc> = options.examples ?? []
|
|
154
175
|
|
|
155
176
|
return {
|
|
156
177
|
description: options.description ?? "",
|
|
157
178
|
usage,
|
|
158
179
|
flags,
|
|
180
|
+
annotations,
|
|
159
181
|
...(args.length > 0 && { args }),
|
|
160
|
-
...(subcommandDocs.length > 0 && { subcommands: subcommandDocs })
|
|
182
|
+
...(subcommandDocs.length > 0 && { subcommands: subcommandDocs }),
|
|
183
|
+
...(examples.length > 0 && { examples })
|
|
161
184
|
}
|
|
162
185
|
}
|
|
163
186
|
|
|
164
187
|
return Object.assign(Object.create(Proto), {
|
|
165
188
|
[TypeId]: TypeId,
|
|
166
189
|
name: options.name,
|
|
167
|
-
|
|
190
|
+
examples: options.examples ?? [],
|
|
191
|
+
annotations,
|
|
192
|
+
subcommands,
|
|
168
193
|
config,
|
|
169
194
|
service,
|
|
170
195
|
parse,
|
|
@@ -172,6 +197,9 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
172
197
|
buildHelpDoc,
|
|
173
198
|
...(Predicate.isNotUndefined(options.description)
|
|
174
199
|
? { description: options.description }
|
|
200
|
+
: {}),
|
|
201
|
+
...(Predicate.isNotUndefined(options.shortDescription)
|
|
202
|
+
? { shortDescription: options.shortDescription }
|
|
175
203
|
: {})
|
|
176
204
|
})
|
|
177
205
|
}
|
|
@@ -255,7 +283,15 @@ export const getHelpForCommandPath = <Name extends string, Input, E, R>(
|
|
|
255
283
|
// Navigate through the command path to find the target command
|
|
256
284
|
for (let i = 1; i < commandPath.length; i++) {
|
|
257
285
|
const subcommandName = commandPath[i]
|
|
258
|
-
|
|
286
|
+
let subcommand: Command.Any | undefined = undefined
|
|
287
|
+
|
|
288
|
+
for (const group of currentCommand.subcommands) {
|
|
289
|
+
subcommand = group.commands.find((sub) => sub.name === subcommandName)
|
|
290
|
+
if (subcommand) {
|
|
291
|
+
break
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
259
295
|
if (subcommand) {
|
|
260
296
|
currentCommand = subcommand
|
|
261
297
|
}
|