effect 4.0.0-beta.12 → 4.0.0-beta.14
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/ManagedRuntime.d.ts +1 -1
- package/dist/ManagedRuntime.js +1 -1
- package/dist/Schedule.js +1 -1
- package/dist/Schedule.js.map +1 -1
- package/dist/SchemaAST.js +1 -1
- package/dist/SchemaAST.js.map +1 -1
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/request.js +2 -2
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/annotations.js +2 -0
- package/dist/internal/schema/annotations.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +36 -36
- package/dist/unstable/ai/McpSchema.js +8 -8
- package/dist/unstable/ai/McpSchema.js.map +1 -1
- package/dist/unstable/cli/CliOutput.js +24 -2
- package/dist/unstable/cli/CliOutput.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +41 -6
- package/dist/unstable/cli/Command.d.ts.map +1 -1
- package/dist/unstable/cli/Command.js +69 -30
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cli/GlobalFlag.d.ts +160 -0
- package/dist/unstable/cli/GlobalFlag.d.ts.map +1 -0
- package/dist/unstable/cli/GlobalFlag.js +157 -0
- package/dist/unstable/cli/GlobalFlag.js.map +1 -0
- package/dist/unstable/cli/HelpDoc.d.ts +10 -0
- package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
- package/dist/unstable/cli/index.d.ts +4 -0
- package/dist/unstable/cli/index.d.ts.map +1 -1
- package/dist/unstable/cli/index.js +4 -0
- package/dist/unstable/cli/index.js.map +1 -1
- package/dist/unstable/cli/internal/command.d.ts +1 -5
- package/dist/unstable/cli/internal/command.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.js +4 -22
- package/dist/unstable/cli/internal/command.js.map +1 -1
- package/dist/unstable/cli/internal/help.d.ts +19 -0
- package/dist/unstable/cli/internal/help.d.ts.map +1 -0
- package/dist/unstable/cli/internal/help.js +53 -0
- package/dist/unstable/cli/internal/help.js.map +1 -0
- package/dist/unstable/cli/internal/parser.js +20 -35
- package/dist/unstable/cli/internal/parser.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +3 -4
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/reactivity/Atom.d.ts +4 -4
- package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
- package/dist/unstable/rpc/Rpc.d.ts +1 -1
- package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
- package/dist/unstable/schema/Model.d.ts +1 -1
- package/dist/unstable/schema/Model.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts +3 -3
- package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.js +3 -3
- package/dist/unstable/schema/VariantSchema.js.map +1 -1
- package/dist/unstable/sql/SqlError.d.ts +14 -14
- package/dist/unstable/sql/SqlError.d.ts.map +1 -1
- package/dist/unstable/sql/SqlError.js +9 -3
- package/dist/unstable/sql/SqlError.js.map +1 -1
- package/package.json +1 -1
- package/src/ManagedRuntime.ts +1 -1
- package/src/Schedule.ts +1 -1
- package/src/SchemaAST.ts +1 -1
- package/src/index.ts +47 -0
- package/src/internal/request.ts +2 -2
- package/src/internal/schema/annotations.ts +2 -0
- package/src/unstable/ai/McpSchema.ts +8 -8
- package/src/unstable/cli/CliOutput.ts +32 -2
- package/src/unstable/cli/Command.ts +104 -37
- package/src/unstable/cli/GlobalFlag.ts +321 -0
- package/src/unstable/cli/HelpDoc.ts +12 -0
- package/src/unstable/cli/index.ts +5 -0
- package/src/unstable/cli/internal/command.ts +5 -30
- package/src/unstable/cli/internal/help.ts +65 -0
- package/src/unstable/cli/internal/parser.ts +23 -52
- package/src/unstable/httpapi/OpenApi.ts +3 -4
- package/src/unstable/reactivity/Atom.ts +6 -6
- package/src/unstable/rpc/Rpc.ts +1 -1
- package/src/unstable/schema/VariantSchema.ts +6 -6
- package/src/unstable/sql/SqlError.ts +11 -9
- package/dist/unstable/cli/internal/builtInFlags.d.ts +0 -7
- package/dist/unstable/cli/internal/builtInFlags.d.ts.map +0 -1
- package/dist/unstable/cli/internal/builtInFlags.js +0 -44
- package/dist/unstable/cli/internal/builtInFlags.js.map +0 -1
- package/src/unstable/cli/internal/builtInFlags.ts +0 -78
|
@@ -6,7 +6,8 @@ import * as Console from "../../Console.ts"
|
|
|
6
6
|
import * as Effect from "../../Effect.ts"
|
|
7
7
|
import type * as FileSystem from "../../FileSystem.ts"
|
|
8
8
|
import { dual } from "../../Function.ts"
|
|
9
|
-
import
|
|
9
|
+
import * as Layer from "../../Layer.ts"
|
|
10
|
+
import * as Option from "../../Option.ts"
|
|
10
11
|
import type * as Path from "../../Path.ts"
|
|
11
12
|
import type { Pipeable } from "../../Pipeable.ts"
|
|
12
13
|
import * as Predicate from "../../Predicate.ts"
|
|
@@ -18,13 +19,13 @@ import type { NoInfer, Simplify } from "../../Types.ts"
|
|
|
18
19
|
import type { ChildProcessSpawner } from "../process/ChildProcessSpawner.ts"
|
|
19
20
|
import * as CliError from "./CliError.ts"
|
|
20
21
|
import * as CliOutput from "./CliOutput.ts"
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import * as Completions from "./internal/completions/Completions.ts"
|
|
22
|
+
import * as GlobalFlag from "./GlobalFlag.ts"
|
|
23
|
+
import { checkForDuplicateFlags, makeCommand, toImpl, TypeId } from "./internal/command.ts"
|
|
24
24
|
import { parseConfig } from "./internal/config.ts"
|
|
25
|
+
import { getHelpForCommandPath } from "./internal/help.ts"
|
|
25
26
|
import * as Lexer from "./internal/lexer.ts"
|
|
26
27
|
import * as Parser from "./internal/parser.ts"
|
|
27
|
-
import
|
|
28
|
+
import * as Param from "./Param.ts"
|
|
28
29
|
|
|
29
30
|
/* ========================================================================== */
|
|
30
31
|
/* Public Types */
|
|
@@ -100,6 +101,11 @@ export interface Command<Name extends string, Input, E = never, R = never> exten
|
|
|
100
101
|
*/
|
|
101
102
|
readonly shortDescription: string | undefined
|
|
102
103
|
|
|
104
|
+
/**
|
|
105
|
+
* An optional alias that can be used as a shorter command name.
|
|
106
|
+
*/
|
|
107
|
+
readonly alias: string | undefined
|
|
108
|
+
|
|
103
109
|
/**
|
|
104
110
|
* Optional usage examples for the command.
|
|
105
111
|
*/
|
|
@@ -934,6 +940,7 @@ export const withSubcommands: {
|
|
|
934
940
|
config: impl.config,
|
|
935
941
|
description: impl.description,
|
|
936
942
|
shortDescription: impl.shortDescription,
|
|
943
|
+
alias: impl.alias,
|
|
937
944
|
annotations: impl.annotations,
|
|
938
945
|
examples: impl.examples,
|
|
939
946
|
service: impl.service,
|
|
@@ -1073,6 +1080,43 @@ export const withShortDescription: {
|
|
|
1073
1080
|
shortDescription: string
|
|
1074
1081
|
) => makeCommand({ ...toImpl(self), shortDescription }))
|
|
1075
1082
|
|
|
1083
|
+
/**
|
|
1084
|
+
* Sets an alias for a command.
|
|
1085
|
+
*
|
|
1086
|
+
* Aliases are accepted as alternate subcommand names during parsing and are
|
|
1087
|
+
* shown in help output as `name, alias`.
|
|
1088
|
+
*
|
|
1089
|
+
* @since 4.0.0
|
|
1090
|
+
* @category combinators
|
|
1091
|
+
*/
|
|
1092
|
+
export const withAlias: {
|
|
1093
|
+
/**
|
|
1094
|
+
* Sets an alias for a command.
|
|
1095
|
+
*
|
|
1096
|
+
* Aliases are accepted as alternate subcommand names during parsing and are
|
|
1097
|
+
* shown in help output as `name, alias`.
|
|
1098
|
+
*
|
|
1099
|
+
* @since 4.0.0
|
|
1100
|
+
* @category combinators
|
|
1101
|
+
*/
|
|
1102
|
+
(alias: string): <const Name extends string, Input, E, R>(
|
|
1103
|
+
self: Command<Name, Input, E, R>
|
|
1104
|
+
) => Command<Name, Input, E, R>
|
|
1105
|
+
/**
|
|
1106
|
+
* Sets an alias for a command.
|
|
1107
|
+
*
|
|
1108
|
+
* Aliases are accepted as alternate subcommand names during parsing and are
|
|
1109
|
+
* shown in help output as `name, alias`.
|
|
1110
|
+
*
|
|
1111
|
+
* @since 4.0.0
|
|
1112
|
+
* @category combinators
|
|
1113
|
+
*/
|
|
1114
|
+
<const Name extends string, Input, E, R>(self: Command<Name, Input, E, R>, alias: string): Command<Name, Input, E, R>
|
|
1115
|
+
} = dual(2, <const Name extends string, Input, E, R>(
|
|
1116
|
+
self: Command<Name, Input, E, R>,
|
|
1117
|
+
alias: string
|
|
1118
|
+
) => makeCommand({ ...toImpl(self), alias }))
|
|
1119
|
+
|
|
1076
1120
|
/**
|
|
1077
1121
|
* Adds a custom annotation to a command.
|
|
1078
1122
|
*
|
|
@@ -1497,7 +1541,7 @@ const showHelp = <Name extends string, Input, E, R>(
|
|
|
1497
1541
|
): Effect.Effect<void, never, Environment> =>
|
|
1498
1542
|
Effect.gen(function*() {
|
|
1499
1543
|
const formatter = yield* CliOutput.Formatter
|
|
1500
|
-
const helpDoc = getHelpForCommandPath(command, commandPath)
|
|
1544
|
+
const helpDoc = yield* getHelpForCommandPath(command, commandPath, GlobalFlag.Registry)
|
|
1501
1545
|
yield* Console.log(formatter.formatHelpDoc(helpDoc))
|
|
1502
1546
|
if (errors && errors.length > 0) {
|
|
1503
1547
|
yield* Console.error(formatter.formatErrors(errors))
|
|
@@ -1553,12 +1597,13 @@ export const run: {
|
|
|
1553
1597
|
* @since 4.0.0
|
|
1554
1598
|
* @category command execution
|
|
1555
1599
|
*/
|
|
1556
|
-
|
|
1557
|
-
command: Command<Name, Input, E, R>,
|
|
1600
|
+
(
|
|
1558
1601
|
config: {
|
|
1559
1602
|
readonly version: string
|
|
1560
1603
|
}
|
|
1561
|
-
):
|
|
1604
|
+
): <Name extends string, Input, E, R>(
|
|
1605
|
+
command: Command<Name, Input, E, R>
|
|
1606
|
+
) => Effect.Effect<void, E | CliError.CliError, R | Environment>
|
|
1562
1607
|
/**
|
|
1563
1608
|
* Runs a command with the provided input arguments.
|
|
1564
1609
|
*
|
|
@@ -1583,13 +1628,12 @@ export const run: {
|
|
|
1583
1628
|
* @since 4.0.0
|
|
1584
1629
|
* @category command execution
|
|
1585
1630
|
*/
|
|
1586
|
-
(
|
|
1631
|
+
<Name extends string, Input, E, R>(
|
|
1632
|
+
command: Command<Name, Input, E, R>,
|
|
1587
1633
|
config: {
|
|
1588
1634
|
readonly version: string
|
|
1589
1635
|
}
|
|
1590
|
-
): <
|
|
1591
|
-
command: Command<Name, Input, E, R>
|
|
1592
|
-
) => Effect.Effect<void, E | CliError.CliError, R | Environment>
|
|
1636
|
+
): Effect.Effect<void, E | CliError.CliError, R | Environment>
|
|
1593
1637
|
} = dual(2, <Name extends string, Input, E, R>(
|
|
1594
1638
|
command: Command<Name, Input, E, R>,
|
|
1595
1639
|
config: {
|
|
@@ -1652,29 +1696,37 @@ export const runWith = <const Name extends string, Input, E, R>(
|
|
|
1652
1696
|
const commandImpl = toImpl(command)
|
|
1653
1697
|
return Effect.fnUntraced(
|
|
1654
1698
|
function*(args: ReadonlyArray<string>) {
|
|
1655
|
-
// Lex and extract built-in flags
|
|
1656
1699
|
const { tokens, trailingOperands } = Lexer.lex(args)
|
|
1657
|
-
|
|
1700
|
+
|
|
1701
|
+
// 1. Read global flags from registry
|
|
1702
|
+
const flags = Array.from(yield* GlobalFlag.Registry)
|
|
1703
|
+
|
|
1704
|
+
// 2. Extract global flag tokens
|
|
1705
|
+
const allFlagParams = flags.flatMap((f) => Param.extractSingleParams(f.flag))
|
|
1706
|
+
const globalRegistry = Parser.createFlagRegistry(allFlagParams.filter(Param.isFlagParam))
|
|
1707
|
+
const { flagMap, remainder } = Parser.consumeKnownFlags(tokens, globalRegistry)
|
|
1708
|
+
const emptyArgs: Param.ParsedArgs = { flags: flagMap, arguments: [] }
|
|
1709
|
+
|
|
1710
|
+
// 3. Parse command arguments from remaining tokens
|
|
1658
1711
|
const parsedArgs = yield* Parser.parseArgs({ tokens: remainder, trailingOperands }, command)
|
|
1659
1712
|
const commandPath = [command.name, ...Parser.getCommandPath(parsedArgs)] as const
|
|
1660
|
-
const
|
|
1661
|
-
|
|
1662
|
-
//
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
yield* Console.log(formatter.formatVersion(command.name, config.version))
|
|
1713
|
+
const handlerCtx: GlobalFlag.HandlerContext = { command, commandPath, version: config.version }
|
|
1714
|
+
|
|
1715
|
+
// 4. Process action flags — first present action wins, then exit
|
|
1716
|
+
for (const flag of flags) {
|
|
1717
|
+
if (flag._tag !== "Action") continue
|
|
1718
|
+
const singles = Param.extractSingleParams(flag.flag)
|
|
1719
|
+
const hasEntry = singles.some((s) => {
|
|
1720
|
+
const entries = flagMap[s.name]
|
|
1721
|
+
return entries !== undefined && entries.length > 0
|
|
1722
|
+
})
|
|
1723
|
+
if (!hasEntry) continue
|
|
1724
|
+
const [, value] = yield* flag.flag.parse(emptyArgs)
|
|
1725
|
+
yield* flag.run(value, handlerCtx)
|
|
1674
1726
|
return
|
|
1675
1727
|
}
|
|
1676
1728
|
|
|
1677
|
-
// Handle parsing errors
|
|
1729
|
+
// 5. Handle parsing errors
|
|
1678
1730
|
if (parsedArgs.errors && parsedArgs.errors.length > 0) {
|
|
1679
1731
|
return yield* showHelp(command, commandPath, parsedArgs.errors)
|
|
1680
1732
|
}
|
|
@@ -1682,15 +1734,30 @@ export const runWith = <const Name extends string, Input, E, R>(
|
|
|
1682
1734
|
if (parseResult._tag === "Failure") {
|
|
1683
1735
|
return yield* showHelp(command, commandPath, [parseResult.failure])
|
|
1684
1736
|
}
|
|
1685
|
-
const parsed = parseResult.success
|
|
1686
1737
|
|
|
1687
|
-
//
|
|
1688
|
-
|
|
1689
|
-
const
|
|
1690
|
-
|
|
1691
|
-
|
|
1738
|
+
// 6. Provide setting values
|
|
1739
|
+
let contextLayer: Layer.Layer<never> = Layer.empty
|
|
1740
|
+
for (const flag of flags) {
|
|
1741
|
+
if (flag._tag !== "Setting") continue
|
|
1742
|
+
const [, value] = yield* flag.flag.parse(emptyArgs)
|
|
1743
|
+
contextLayer = Layer.merge(contextLayer, Layer.succeed(flag, value))
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
// 7. Apply built-in setting behavior
|
|
1747
|
+
if (flags.includes(GlobalFlag.LogLevel)) {
|
|
1748
|
+
const [, logLevel] = yield* GlobalFlag.LogLevel.flag.parse(emptyArgs)
|
|
1749
|
+
contextLayer = Layer.merge(
|
|
1750
|
+
contextLayer,
|
|
1751
|
+
Option.match(logLevel, {
|
|
1752
|
+
onNone: () => Layer.empty,
|
|
1753
|
+
onSome: (level) => Layer.succeed(References.MinimumLogLevel, level)
|
|
1754
|
+
})
|
|
1755
|
+
)
|
|
1756
|
+
}
|
|
1692
1757
|
|
|
1693
|
-
|
|
1758
|
+
// 8. Run command handler with composed context
|
|
1759
|
+
const program = commandImpl.handle(parseResult.success, [command.name])
|
|
1760
|
+
yield* Effect.provide(program, contextLayer)
|
|
1694
1761
|
},
|
|
1695
1762
|
Effect.catchIf(
|
|
1696
1763
|
((error: any) =>
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 4.0.0
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as Console from "../../Console.ts"
|
|
6
|
+
import * as Effect from "../../Effect.ts"
|
|
7
|
+
import { dual } from "../../Function.ts"
|
|
8
|
+
import type { LogLevel as LogLevelType } from "../../LogLevel.ts"
|
|
9
|
+
import * as Option from "../../Option.ts"
|
|
10
|
+
import * as ServiceMap from "../../ServiceMap.ts"
|
|
11
|
+
import * as CliOutput from "./CliOutput.ts"
|
|
12
|
+
import type * as Command from "./Command.ts"
|
|
13
|
+
import * as Flag from "./Flag.ts"
|
|
14
|
+
|
|
15
|
+
/* ========================================================================== */
|
|
16
|
+
/* Types */
|
|
17
|
+
/* ========================================================================== */
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Context passed to action handlers.
|
|
21
|
+
*
|
|
22
|
+
* @since 4.0.0
|
|
23
|
+
* @category models
|
|
24
|
+
*/
|
|
25
|
+
export interface HandlerContext {
|
|
26
|
+
readonly command: Command.Command<any, unknown, unknown, unknown>
|
|
27
|
+
readonly commandPath: ReadonlyArray<string>
|
|
28
|
+
readonly version: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Action flag: side effect + exit (--help, --version, --completions).
|
|
33
|
+
*
|
|
34
|
+
* @since 4.0.0
|
|
35
|
+
* @category models
|
|
36
|
+
*/
|
|
37
|
+
export interface Action<A> {
|
|
38
|
+
readonly _tag: "Action"
|
|
39
|
+
readonly flag: Flag.Flag<A>
|
|
40
|
+
readonly run: (
|
|
41
|
+
value: A,
|
|
42
|
+
context: HandlerContext
|
|
43
|
+
) => Effect.Effect<void>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Setting flag: configure command handler's environment (--log-level, --config).
|
|
48
|
+
*
|
|
49
|
+
* @since 4.0.0
|
|
50
|
+
* @category models
|
|
51
|
+
*/
|
|
52
|
+
export interface Setting<A> extends ServiceMap.Reference<A> {
|
|
53
|
+
readonly _tag: "Setting"
|
|
54
|
+
readonly flag: Flag.Flag<A>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Global flag discriminated union.
|
|
59
|
+
*
|
|
60
|
+
* @since 4.0.0
|
|
61
|
+
* @category models
|
|
62
|
+
*/
|
|
63
|
+
export type GlobalFlag<A> = Action<A> | Setting<A>
|
|
64
|
+
|
|
65
|
+
/* ========================================================================== */
|
|
66
|
+
/* Constructors */
|
|
67
|
+
/* ========================================================================== */
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Creates an Action flag that performs a side effect and exits.
|
|
71
|
+
*
|
|
72
|
+
* @since 4.0.0
|
|
73
|
+
* @category constructors
|
|
74
|
+
*/
|
|
75
|
+
export const action = <A>(options: {
|
|
76
|
+
readonly flag: Flag.Flag<A>
|
|
77
|
+
readonly run: (
|
|
78
|
+
value: A,
|
|
79
|
+
context: HandlerContext
|
|
80
|
+
) => Effect.Effect<void>
|
|
81
|
+
}): Action<A> => ({
|
|
82
|
+
_tag: "Action",
|
|
83
|
+
flag: options.flag,
|
|
84
|
+
run: options.run
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates a Setting flag that configures the command handler's environment.
|
|
89
|
+
*
|
|
90
|
+
* @since 4.0.0
|
|
91
|
+
* @category constructors
|
|
92
|
+
*/
|
|
93
|
+
export const setting = <A>(options: {
|
|
94
|
+
readonly flag: Flag.Flag<A>
|
|
95
|
+
readonly defaultValue: () => A
|
|
96
|
+
}): Setting<A> => {
|
|
97
|
+
settingIdCounter += 1
|
|
98
|
+
const ref = ServiceMap.Reference<A>(
|
|
99
|
+
`effect/cli/GlobalFlag/Setting/${settingIdCounter}`,
|
|
100
|
+
{ defaultValue: options.defaultValue }
|
|
101
|
+
)
|
|
102
|
+
return Object.assign(ref, {
|
|
103
|
+
_tag: "Setting" as const,
|
|
104
|
+
flag: options.flag
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let settingIdCounter = 0
|
|
109
|
+
|
|
110
|
+
/* ========================================================================== */
|
|
111
|
+
/* Built-in Flag References */
|
|
112
|
+
/* ========================================================================== */
|
|
113
|
+
|
|
114
|
+
import * as CommandDescriptor from "./internal/completions/CommandDescriptor.ts"
|
|
115
|
+
import * as CompletionsInternal from "./internal/completions/Completions.ts"
|
|
116
|
+
import * as HelpInternal from "./internal/help.ts"
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The `--help` / `-h` global flag.
|
|
120
|
+
* Shows help documentation for the command.
|
|
121
|
+
*
|
|
122
|
+
* @since 4.0.0
|
|
123
|
+
* @category references
|
|
124
|
+
*/
|
|
125
|
+
export const Help: Action<boolean> = action({
|
|
126
|
+
flag: Flag.boolean("help").pipe(
|
|
127
|
+
Flag.withAlias("h"),
|
|
128
|
+
Flag.withDescription("Show help information")
|
|
129
|
+
),
|
|
130
|
+
run: (_, { command, commandPath }) =>
|
|
131
|
+
Effect.gen(function*() {
|
|
132
|
+
const formatter = yield* CliOutput.Formatter
|
|
133
|
+
const helpDoc = yield* HelpInternal.getHelpForCommandPath(command, commandPath, Registry)
|
|
134
|
+
yield* Console.log(formatter.formatHelpDoc(helpDoc))
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The `--version` global flag.
|
|
140
|
+
* Shows version information for the command.
|
|
141
|
+
*
|
|
142
|
+
* @since 4.0.0
|
|
143
|
+
* @category references
|
|
144
|
+
*/
|
|
145
|
+
export const Version: Action<boolean> = action({
|
|
146
|
+
flag: Flag.boolean("version").pipe(
|
|
147
|
+
Flag.withDescription("Show version information")
|
|
148
|
+
),
|
|
149
|
+
run: (_, { command, version }) =>
|
|
150
|
+
Effect.gen(function*() {
|
|
151
|
+
const formatter = yield* CliOutput.Formatter
|
|
152
|
+
yield* Console.log(formatter.formatVersion(command.name, version))
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* The `--completions` global flag.
|
|
158
|
+
* Prints shell completion script for the given shell.
|
|
159
|
+
*
|
|
160
|
+
* @since 4.0.0
|
|
161
|
+
* @category references
|
|
162
|
+
*/
|
|
163
|
+
export const Completions: Action<Option.Option<"bash" | "zsh" | "fish">> = action({
|
|
164
|
+
flag: Flag.choice("completions", ["bash", "zsh", "fish", "sh"] as const)
|
|
165
|
+
.pipe(
|
|
166
|
+
Flag.optional,
|
|
167
|
+
Flag.map((v) => Option.map(v, (s) => s === "sh" ? "bash" : s)),
|
|
168
|
+
Flag.withDescription("Print shell completion script")
|
|
169
|
+
),
|
|
170
|
+
run: (shell, { command }) =>
|
|
171
|
+
Effect.gen(function*() {
|
|
172
|
+
if (Option.isNone(shell)) return
|
|
173
|
+
const descriptor = CommandDescriptor.fromCommand(command)
|
|
174
|
+
yield* Console.log(
|
|
175
|
+
CompletionsInternal.generate(command.name, shell.value, descriptor)
|
|
176
|
+
)
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The `--log-level` global flag.
|
|
182
|
+
* Sets the minimum log level for the command.
|
|
183
|
+
*
|
|
184
|
+
* @since 4.0.0
|
|
185
|
+
* @category references
|
|
186
|
+
*/
|
|
187
|
+
export const LogLevel: Setting<Option.Option<LogLevelType>> = setting({
|
|
188
|
+
flag: Flag.choiceWithValue(
|
|
189
|
+
"log-level",
|
|
190
|
+
[
|
|
191
|
+
["all", "All"],
|
|
192
|
+
["trace", "Trace"],
|
|
193
|
+
["debug", "Debug"],
|
|
194
|
+
["info", "Info"],
|
|
195
|
+
["warn", "Warn"],
|
|
196
|
+
["warning", "Warn"],
|
|
197
|
+
["error", "Error"],
|
|
198
|
+
["fatal", "Fatal"],
|
|
199
|
+
["none", "None"]
|
|
200
|
+
] as const
|
|
201
|
+
).pipe(
|
|
202
|
+
Flag.optional,
|
|
203
|
+
Flag.withDescription("Sets the minimum log level")
|
|
204
|
+
),
|
|
205
|
+
defaultValue: () => Option.none()
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
/* ========================================================================== */
|
|
209
|
+
/* Registry */
|
|
210
|
+
/* ========================================================================== */
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* The ordered set of global flag references.
|
|
214
|
+
* The parser iterates this set to know which flags to extract.
|
|
215
|
+
*
|
|
216
|
+
* @since 4.0.0
|
|
217
|
+
* @category references
|
|
218
|
+
*/
|
|
219
|
+
export const Registry: ServiceMap.Reference<
|
|
220
|
+
Set<GlobalFlag<any>>
|
|
221
|
+
> = ServiceMap.Reference("effect/cli/GlobalFlag/Registry", {
|
|
222
|
+
defaultValue: () =>
|
|
223
|
+
new Set<GlobalFlag<any>>([
|
|
224
|
+
Help,
|
|
225
|
+
Version,
|
|
226
|
+
Completions,
|
|
227
|
+
LogLevel
|
|
228
|
+
])
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
/* ========================================================================== */
|
|
232
|
+
/* Public API */
|
|
233
|
+
/* ========================================================================== */
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Adds a global flag to the registry.
|
|
237
|
+
*
|
|
238
|
+
* @since 4.0.0
|
|
239
|
+
* @category modifiers
|
|
240
|
+
*/
|
|
241
|
+
export const add: {
|
|
242
|
+
/* ========================================================================== */
|
|
243
|
+
/* Public API */
|
|
244
|
+
/* ========================================================================== */
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Adds a global flag to the registry.
|
|
248
|
+
*
|
|
249
|
+
* @since 4.0.0
|
|
250
|
+
* @category modifiers
|
|
251
|
+
*/
|
|
252
|
+
<A>(flag: GlobalFlag<A>): <B, E, R>(
|
|
253
|
+
self: Effect.Effect<B, E, R>
|
|
254
|
+
) => Effect.Effect<B, E, R>
|
|
255
|
+
/* ========================================================================== */
|
|
256
|
+
/* Public API */
|
|
257
|
+
/* ========================================================================== */
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Adds a global flag to the registry.
|
|
261
|
+
*
|
|
262
|
+
* @since 4.0.0
|
|
263
|
+
* @category modifiers
|
|
264
|
+
*/
|
|
265
|
+
<B, E, R, A>(self: Effect.Effect<B, E, R>, flag: GlobalFlag<A>): Effect.Effect<B, E, R>
|
|
266
|
+
} = dual(
|
|
267
|
+
2,
|
|
268
|
+
Effect.fnUntraced(function*<B, E, R, A>(
|
|
269
|
+
self: Effect.Effect<B, E, R>,
|
|
270
|
+
flag: GlobalFlag<A>
|
|
271
|
+
) {
|
|
272
|
+
const currentRegistry = yield* Registry
|
|
273
|
+
const nextRegistry = new Set([...currentRegistry, flag])
|
|
274
|
+
return yield* Effect.provideService(self, Registry, nextRegistry)
|
|
275
|
+
})
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Removes a global flag by its reference.
|
|
280
|
+
*
|
|
281
|
+
* @since 4.0.0
|
|
282
|
+
* @category modifiers
|
|
283
|
+
*/
|
|
284
|
+
export const remove: {
|
|
285
|
+
/**
|
|
286
|
+
* Removes a global flag by its reference.
|
|
287
|
+
*
|
|
288
|
+
* @since 4.0.0
|
|
289
|
+
* @category modifiers
|
|
290
|
+
*/
|
|
291
|
+
<A>(flag: GlobalFlag<A>): <B, E, R>(
|
|
292
|
+
self: Effect.Effect<B, E, R>
|
|
293
|
+
) => Effect.Effect<B, E, R>
|
|
294
|
+
/**
|
|
295
|
+
* Removes a global flag by its reference.
|
|
296
|
+
*
|
|
297
|
+
* @since 4.0.0
|
|
298
|
+
* @category modifiers
|
|
299
|
+
*/
|
|
300
|
+
<B, E, R, A>(self: Effect.Effect<B, E, R>, flag: GlobalFlag<A>): Effect.Effect<B, E, R>
|
|
301
|
+
} = dual(
|
|
302
|
+
2,
|
|
303
|
+
Effect.fnUntraced(function*<B, E, R, A>(
|
|
304
|
+
self: Effect.Effect<B, E, R>,
|
|
305
|
+
flag: GlobalFlag<A>
|
|
306
|
+
) {
|
|
307
|
+
const currentRegistry = yield* Registry
|
|
308
|
+
const nextRegistry = new Set(currentRegistry)
|
|
309
|
+
nextRegistry.delete(flag)
|
|
310
|
+
return yield* Effect.provideService(self, Registry, nextRegistry)
|
|
311
|
+
})
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Removes all global flags (built-in and user-defined).
|
|
316
|
+
*
|
|
317
|
+
* @since 4.0.0
|
|
318
|
+
* @category modifiers
|
|
319
|
+
*/
|
|
320
|
+
export const clear = <B, E, R>(self: Effect.Effect<B, E, R>): Effect.Effect<B, E, R> =>
|
|
321
|
+
Effect.provideService(self, Registry, new Set())
|
|
@@ -67,6 +67,11 @@ export interface HelpDoc {
|
|
|
67
67
|
*/
|
|
68
68
|
readonly flags: ReadonlyArray<FlagDoc>
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Global flags available to all commands (e.g., --help, --version).
|
|
72
|
+
*/
|
|
73
|
+
readonly globalFlags?: ReadonlyArray<FlagDoc>
|
|
74
|
+
|
|
70
75
|
/**
|
|
71
76
|
* Custom command annotations.
|
|
72
77
|
*/
|
|
@@ -170,12 +175,14 @@ export interface FlagDoc {
|
|
|
170
175
|
*
|
|
171
176
|
* const deploySubcommand: HelpDoc.SubcommandDoc = {
|
|
172
177
|
* name: "deploy",
|
|
178
|
+
* alias: "d",
|
|
173
179
|
* shortDescription: "Deploy app",
|
|
174
180
|
* description: "Deploy the application to the cloud"
|
|
175
181
|
* }
|
|
176
182
|
*
|
|
177
183
|
* const buildSubcommand: HelpDoc.SubcommandDoc = {
|
|
178
184
|
* name: "build",
|
|
185
|
+
* alias: undefined,
|
|
179
186
|
* shortDescription: undefined,
|
|
180
187
|
* description: "Build the application for production"
|
|
181
188
|
* }
|
|
@@ -202,6 +209,11 @@ export interface SubcommandDoc {
|
|
|
202
209
|
*/
|
|
203
210
|
readonly name: string
|
|
204
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Optional short alias for invoking the subcommand.
|
|
214
|
+
*/
|
|
215
|
+
readonly alias: string | undefined
|
|
216
|
+
|
|
205
217
|
/**
|
|
206
218
|
* Optional short description of what the subcommand does.
|
|
207
219
|
*/
|
|
@@ -90,6 +90,7 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
90
90
|
readonly annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
91
91
|
readonly description?: string | undefined
|
|
92
92
|
readonly shortDescription?: string | undefined
|
|
93
|
+
readonly alias?: string | undefined
|
|
93
94
|
readonly examples?: ReadonlyArray<Command.Example> | undefined
|
|
94
95
|
readonly subcommands?: ReadonlyArray<SubcommandGroup> | undefined
|
|
95
96
|
readonly parse?: ((input: ParsedTokens) => Effect.Effect<Input, CliError.CliError, Environment>) | undefined
|
|
@@ -165,6 +166,7 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
165
166
|
group: group.group,
|
|
166
167
|
commands: Arr.map(group.commands, (subcommand) => ({
|
|
167
168
|
name: subcommand.name,
|
|
169
|
+
alias: subcommand.alias,
|
|
168
170
|
shortDescription: subcommand.shortDescription,
|
|
169
171
|
description: subcommand.description ?? ""
|
|
170
172
|
}))
|
|
@@ -200,6 +202,9 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
200
202
|
: {}),
|
|
201
203
|
...(Predicate.isNotUndefined(options.shortDescription)
|
|
202
204
|
? { shortDescription: options.shortDescription }
|
|
205
|
+
: {}),
|
|
206
|
+
...(Predicate.isNotUndefined(options.alias)
|
|
207
|
+
? { alias: options.alias }
|
|
203
208
|
: {})
|
|
204
209
|
})
|
|
205
210
|
}
|
|
@@ -269,33 +274,3 @@ export const checkForDuplicateFlags = <Name extends string, Input>(
|
|
|
269
274
|
}
|
|
270
275
|
}
|
|
271
276
|
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Helper function to get help documentation for a specific command path.
|
|
275
|
-
* Navigates through the command hierarchy to find the right command.
|
|
276
|
-
*/
|
|
277
|
-
export const getHelpForCommandPath = <Name extends string, Input, E, R>(
|
|
278
|
-
command: Command<Name, Input, E, R>,
|
|
279
|
-
commandPath: ReadonlyArray<string>
|
|
280
|
-
): HelpDoc => {
|
|
281
|
-
let currentCommand: Command.Any = command
|
|
282
|
-
|
|
283
|
-
// Navigate through the command path to find the target command
|
|
284
|
-
for (let i = 1; i < commandPath.length; i++) {
|
|
285
|
-
const subcommandName = commandPath[i]
|
|
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
|
-
|
|
295
|
-
if (subcommand) {
|
|
296
|
-
currentCommand = subcommand
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return toImpl(currentCommand).buildHelpDoc(commandPath)
|
|
301
|
-
}
|