New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@effect/cli

Package Overview
Dependencies
Maintainers
3
Versions
348
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@effect/cli - npm Package Compare versions

Comparing version 0.24.0 to 0.25.0

Args/package.json

10

dist/dts/Args.d.ts

@@ -12,2 +12,3 @@ /**

import type { NonEmptyReadonlyArray } from "effect/ReadonlyArray";
import type { Secret } from "effect/Secret";
import type { CliConfig } from "./CliConfig.js";

@@ -276,2 +277,11 @@ import type { HelpDoc } from "./HelpDoc.js";

*
* Can optionally provide a custom argument name (defaults to `"secret"`).
*
* @since 1.0.0
* @category constructors
*/
export declare const secret: (config?: Args.BaseArgsConfig) => Args<Secret>;
/**
* Creates a text argument.
*
* Can optionally provide a custom argument name (defaults to `"text"`).

@@ -278,0 +288,0 @@ *

19

dist/dts/CliConfig.d.ts

@@ -15,6 +15,10 @@ /**

* Whether or not the argument parser should be case sensitive.
*
* Defaults to `false`.
*/
readonly isCaseSensitive: boolean;
/**
* Threshold for when to show auto correct suggestions.
* Levenstein distance threshold for when to show auto correct suggestions.
*
* Defaults to `2`.
*/

@@ -25,2 +29,4 @@ readonly autoCorrectLimit: number;

* a built-in option, even if the provided command is not valid.
*
* Defaults to `false`.
*/

@@ -31,7 +37,18 @@ readonly finalCheckBuiltIn: boolean;

* particular command.
*
* Defaults to `true`.
*/
readonly showAllNames: boolean;
/**
* Whether or not to display built-in options in the help documentation
* generated for a `Command`.
*
* Defaults to `true`.
*/
readonly showBuiltIns: boolean;
/**
* Whether or not to display the type of an option in the usage of a
* particular command.
*
* Defaults to `true`.
*/

@@ -38,0 +55,0 @@ readonly showTypes: boolean;

2

dist/dts/Command.d.ts

@@ -121,3 +121,3 @@ /**

*/
export declare const getHelp: <Name extends string, R, E, A>(self: Command<Name, R, E, A>) => HelpDoc;
export declare const getHelp: <Name extends string, R, E, A>(self: Command<Name, R, E, A>, config: CliConfig) => HelpDoc;
/**

@@ -124,0 +124,0 @@ * @since 1.0.0

@@ -97,3 +97,3 @@ /**

*/
export declare const getHelp: <A>(self: Command<A>) => HelpDoc;
export declare const getHelp: <A>(self: Command<A>, config: CliConfig) => HelpDoc;
/**

@@ -100,0 +100,0 @@ * @since 1.0.0

@@ -13,2 +13,3 @@ /**

import type { NonEmptyReadonlyArray } from "effect/ReadonlyArray";
import type { Secret } from "effect/Secret";
import type { CliConfig } from "./CliConfig.js";

@@ -218,2 +219,7 @@ import type { HelpDoc } from "./HelpDoc.js";

*/
export declare const secret: (name: string) => Options<Secret>;
/**
* @since 1.0.0
* @category constructors
*/
export declare const text: (name: string) => Options<string>;

@@ -220,0 +226,0 @@ /**

@@ -8,2 +8,3 @@ /**

import type { Pipeable } from "effect/Pipeable";
import type { Secret } from "effect/Secret";
import type { PromptAction } from "./Prompt/Action.js";

@@ -266,6 +267,2 @@ /**

/**
* The type of the text option.
*/
readonly type?: "hidden" | "password" | "text";
/**
* The default value of the text option.

@@ -380,2 +377,7 @@ */

*/
export declare const hidden: (options: Prompt.TextOptions) => Prompt<Secret>;
/**
* @since 1.0.0
* @category constructors
*/
export declare const integer: (options: Prompt.IntegerOptions) => Prompt<number>;

@@ -396,2 +398,7 @@ /**

/**
* @since 1.0.0
* @category constructors
*/
export declare const password: (options: Prompt.TextOptions) => Prompt<Secret>;
/**
* Executes the specified `Prompt`.

@@ -398,0 +405,0 @@ *

@@ -164,2 +164,11 @@ import * as InternalArgs from "./internal/args.js";

*
* Can optionally provide a custom argument name (defaults to `"secret"`).
*
* @since 1.0.0
* @category constructors
*/
export const secret = InternalArgs.secret;
/**
* Creates a text argument.
*
* Can optionally provide a custom argument name (defaults to `"text"`).

@@ -166,0 +175,0 @@ *

@@ -101,2 +101,4 @@ import * as Console from "effect/Console";

/** @internal */
export const secret = (config = {}) => makeSingle(Option.fromNullable(config.name), InternalPrimitive.secret);
/** @internal */
export const text = (config = {}) => makeSingle(Option.fromNullable(config.name), InternalPrimitive.text);

@@ -436,3 +438,3 @@ // =============================================================================

{
return validateInternal(self.args, args, config).pipe(Effect.catchTag("MissingValue", e => Effect.map(Effect.mapError(Effect.config(self.config), () => e), value => [args, value])));
return validateInternal(self.args, args, config).pipe(Effect.catchTag("MissingValue", e => Effect.map(Effect.mapError(self.config, () => e), value => [args, value])));
}

@@ -439,0 +441,0 @@ }

@@ -162,8 +162,2 @@ import * as Color from "@effect/printer-ansi/Color";

}
case "OrElse":
{
prefix = ReadonlyArray.empty();
command = undefined;
break;
}
case "Subcommands":

@@ -170,0 +164,0 @@ {

@@ -15,4 +15,5 @@ import * as Context from "effect/Context";

autoCorrectLimit: 2,
finalCheckBuiltIn: true,
finalCheckBuiltIn: false,
showAllNames: true,
showBuiltIns: true,
showTypes: true

@@ -19,0 +20,0 @@ };

@@ -115,3 +115,3 @@ import * as Context from "effect/Context";

/** @internal */
export const getHelp = self => InternalDescriptor.getHelp(self.descriptor);
export const getHelp = (self, config) => InternalDescriptor.getHelp(self.descriptor, config);
/** @internal */

@@ -118,0 +118,0 @@ export const getNames = self => InternalDescriptor.getNames(self.descriptor);

@@ -50,4 +50,2 @@ import * as Color from "@effect/printer-ansi/Color";

/** @internal */
export const isOrElse = self => self._tag === "OrElse";
/** @internal */
export const isSubcommands = self => self._tag === "Subcommands";

@@ -80,5 +78,5 @@ // =============================================================================

/** @internal */
export const getHelp = self => getHelpInternal(self);
export const getHelp = (self, config) => getHelpInternal(self, config);
/** @internal */
export const getNames = self => getNamesInternal(self);
export const getNames = self => HashSet.fromIterable(getNamesInternal(self));
/** @internal */

@@ -91,3 +89,3 @@ export const getBashCompletions = (self, programName) => getBashCompletionsInternal(self, programName);

/** @internal */
export const getSubcommands = self => getSubcommandsInternal(self);
export const getSubcommands = self => HashMap.fromIterable(getSubcommandsInternal(self));
/** @internal */

@@ -106,12 +104,2 @@ export const getUsage = self => getUsageInternal(self);

/** @internal */
export const orElse = /*#__PURE__*/dual(2, (self, that) => {
const op = Object.create(proto);
op._tag = "OrElse";
op.left = self;
op.right = that;
return op;
});
/** @internal */
export const orElseEither = /*#__PURE__*/dual(2, (self, that) => orElse(map(self, Either.left), map(that, Either.right)));
/** @internal */
export const parse = /*#__PURE__*/dual(3, (self, args, config) => parseInternal(self, args, config));

@@ -125,10 +113,4 @@ /** @internal */

op.parent = self;
if (ReadonlyArray.isNonEmptyReadonlyArray(subcommands)) {
const mapped = ReadonlyArray.map(subcommands, ([id, command]) => map(command, a => [id, a]));
const head = ReadonlyArray.headNonEmpty(mapped);
const tail = ReadonlyArray.tailNonEmpty(mapped);
op.child = ReadonlyArray.isNonEmptyReadonlyArray(tail) ? ReadonlyArray.reduce(tail, head, orElse) : head;
return op;
}
throw new Error("[BUG]: Command.subcommands - received empty list of subcommands");
op.children = ReadonlyArray.map(subcommands, ([id, command]) => map(command, a => [id, a]));
return op;
});

@@ -140,3 +122,3 @@ /** @internal */

// =============================================================================
const getHelpInternal = self => {
const getHelpInternal = (self, config) => {
switch (self._tag) {

@@ -148,3 +130,4 @@ case "Standard":

const argsSection = InternalHelpDoc.isEmpty(argsHelp) ? InternalHelpDoc.empty : InternalHelpDoc.sequence(InternalHelpDoc.h1("ARGUMENTS"), argsHelp);
const optionsHelp = InternalOptions.getHelp(self.options);
const options = config.showBuiltIns ? Options.all([self.options, InternalBuiltInOptions.builtIns]) : self.options;
const optionsHelp = InternalOptions.getHelp(options);
const optionsSection = InternalHelpDoc.isEmpty(optionsHelp) ? InternalHelpDoc.empty : InternalHelpDoc.sequence(InternalHelpDoc.h1("OPTIONS"), optionsHelp);

@@ -159,8 +142,4 @@ return InternalHelpDoc.sequence(header, InternalHelpDoc.sequence(argsSection, optionsSection));

{
return getHelpInternal(self.command);
return getHelpInternal(self.command, config);
}
case "OrElse":
{
return InternalHelpDoc.sequence(getHelpInternal(self.left), getHelpInternal(self.right));
}
case "Subcommands":

@@ -183,6 +162,2 @@ {

}
case "OrElse":
{
return ReadonlyArray.appendAll(getUsage(command.left, preceding), getUsage(command.right, preceding));
}
case "Subcommands":

@@ -192,6 +167,6 @@ {

return Option.match(ReadonlyArray.head(parentUsage), {
onNone: () => getUsage(command.child, preceding),
onNone: () => ReadonlyArray.flatMap(command.children, child => getUsage(child, preceding)),
onSome: ([usage]) => {
const childUsage = getUsage(command.child, ReadonlyArray.append(preceding, usage));
return ReadonlyArray.appendAll(parentUsage, childUsage);
const childrenUsage = ReadonlyArray.flatMap(command.children, child => getUsage(child, ReadonlyArray.append(preceding, usage)));
return ReadonlyArray.appendAll(parentUsage, childrenUsage);
}

@@ -210,3 +185,3 @@ });

};
return InternalHelpDoc.sequence(getHelpInternal(self.parent), InternalHelpDoc.sequence(InternalHelpDoc.h1("COMMANDS"), printSubcommands(getUsage(self.child, ReadonlyArray.empty()))));
return InternalHelpDoc.sequence(getHelpInternal(self.parent, config), InternalHelpDoc.sequence(InternalHelpDoc.h1("COMMANDS"), printSubcommands(ReadonlyArray.flatMap(self.children, child => getUsage(child, ReadonlyArray.empty())))));
}

@@ -220,3 +195,3 @@ }

{
return HashSet.make(self.name);
return ReadonlyArray.of(self.name);
}

@@ -227,6 +202,2 @@ case "Map":

}
case "OrElse":
{
return HashSet.union(getNamesInternal(self.right), getNamesInternal(self.left));
}
case "Subcommands":

@@ -239,21 +210,22 @@ {

const getSubcommandsInternal = self => {
switch (self._tag) {
case "Standard":
case "GetUserInput":
{
return HashMap.make([self.name, self]);
}
case "Map":
{
return getSubcommandsInternal(self.command);
}
case "OrElse":
{
return HashMap.union(getSubcommandsInternal(self.left), getSubcommandsInternal(self.right));
}
case "Subcommands":
{
return getSubcommandsInternal(self.parent);
}
}
const loop = (self, isSubcommand) => {
switch (self._tag) {
case "Standard":
case "GetUserInput":
{
return ReadonlyArray.of([self.name, self]);
}
case "Map":
{
return loop(self.command, isSubcommand);
}
case "Subcommands":
{
// Ensure that we only traverse the subcommands one level deep from the
// parent command
return isSubcommand ? loop(self.parent, false) : ReadonlyArray.flatMap(self.children, child => loop(child, true));
}
}
};
return loop(self, false);
};

@@ -274,9 +246,5 @@ const getUsageInternal = self => {

}
case "OrElse":
{
return InternalUsage.mixed;
}
case "Subcommands":
{
return InternalUsage.concat(getUsageInternal(self.parent), getUsageInternal(self.child));
return InternalUsage.concat(getUsageInternal(self.parent), InternalUsage.mixed);
}

@@ -289,6 +257,8 @@ }

{
const parseCommandLine = args => {
if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
const head = ReadonlyArray.headNonEmpty(args);
const tail = ReadonlyArray.tailNonEmpty(args);
const parseCommandLine = args => ReadonlyArray.matchLeft(args, {
onEmpty: () => {
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`);
return Effect.fail(InternalValidationError.commandMismatch(error));
},
onNonEmpty: (head, tail) => {
const normalizedArgv0 = InternalCliConfig.normalizeCase(config, head);

@@ -301,15 +271,17 @@ const normalizedCommandName = InternalCliConfig.normalizeCase(config, self.name);

}
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`);
return Effect.fail(InternalValidationError.commandMismatch(error));
};
const parseBuiltInArgs = args => {
if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
const argv0 = ReadonlyArray.headNonEmpty(args);
});
const parseBuiltInArgs = args => ReadonlyArray.matchLeft(args, {
onEmpty: () => {
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`);
return Effect.fail(InternalValidationError.commandMismatch(error));
},
onNonEmpty: argv0 => {
const normalizedArgv0 = InternalCliConfig.normalizeCase(config, argv0);
const normalizedCommandName = InternalCliConfig.normalizeCase(config, self.name);
if (normalizedArgv0 === normalizedCommandName) {
const help = getHelpInternal(self);
const help = getHelpInternal(self, config);
const usage = getUsageInternal(self);
const options = InternalBuiltInOptions.builtInOptions(self, usage, help);
return InternalOptions.processCommandLine(options, ReadonlyArray.drop(args, 1), config).pipe(Effect.flatMap(tuple => tuple[2]), Effect.catchTag("NoSuchElementException", () => {
const argsWithoutCommand = ReadonlyArray.drop(args, 1);
return InternalOptions.processCommandLine(options, argsWithoutCommand, config).pipe(Effect.flatMap(tuple => tuple[2]), Effect.catchTag("NoSuchElementException", () => {
const error = InternalHelpDoc.p("No built-in option was matched");

@@ -319,6 +291,6 @@ return Effect.fail(InternalValidationError.noBuiltInMatch(error));

}
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`);
return Effect.fail(InternalValidationError.commandMismatch(error));
}
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`);
return Effect.fail(InternalValidationError.commandMismatch(error));
};
});
const parseUserDefinedArgs = args => parseCommandLine(args).pipe(Effect.flatMap(commandOptionsAndArgs => {

@@ -375,28 +347,30 @@ const [optionsAndArgs, forcedCommandArgs] = splitForcedArgs(commandOptionsAndArgs);

}
case "OrElse":
{
return parseInternal(self.left, args, config).pipe(Effect.catchSome(e => {
return InternalValidationError.isCommandMismatch(e) ? Option.some(parseInternal(self.right, args, config)) : Option.none();
}));
}
case "Subcommands":
{
const names = Array.from(getNamesInternal(self));
const subcommands = getSubcommandsInternal(self.child);
const [parentArgs, childArgs] = ReadonlyArray.span(args, name => !HashMap.has(subcommands, name));
const names = getNamesInternal(self);
const subcommands = getSubcommandsInternal(self);
const [parentArgs, childArgs] = ReadonlyArray.span(args, arg => !ReadonlyArray.some(subcommands, ([name]) => name === arg));
const parseChildren = Effect.suspend(() => {
const iterator = self.children[Symbol.iterator]();
const loop = next => {
return parseInternal(next, childArgs, config).pipe(Effect.catchIf(InternalValidationError.isCommandMismatch, e => {
const next = iterator.next();
return next.done ? Effect.fail(e) : loop(next.value);
}));
};
return loop(iterator.next().value);
});
const helpDirectiveForParent = Effect.sync(() => {
return InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(getUsageInternal(self), getHelpInternal(self)));
return InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(getUsageInternal(self), getHelpInternal(self, config)));
});
const helpDirectiveForChild = Effect.suspend(() => {
return parseInternal(self.child, childArgs, config).pipe(Effect.flatMap(directive => {
if (InternalCommandDirective.isBuiltIn(directive) && InternalBuiltInOptions.isShowHelp(directive.option)) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "");
const newDirective = InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(InternalUsage.concat(InternalUsage.named(ReadonlyArray.of(parentName), Option.none()), directive.option.usage), directive.option.helpDoc));
return Effect.succeed(newDirective);
}
return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty));
}));
});
const helpDirectiveForChild = parseChildren.pipe(Effect.flatMap(directive => {
if (InternalCommandDirective.isBuiltIn(directive) && InternalBuiltInOptions.isShowHelp(directive.option)) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "");
const newDirective = InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(InternalUsage.concat(InternalUsage.named(ReadonlyArray.of(parentName), Option.none()), directive.option.usage), directive.option.helpDoc));
return Effect.succeed(newDirective);
}
return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty));
}));
const wizardDirectiveForParent = Effect.sync(() => InternalCommandDirective.builtIn(InternalBuiltInOptions.showWizard(self)));
const wizardDirectiveForChild = Effect.suspend(() => parseInternal(self.child, childArgs, config).pipe(Effect.flatMap(directive => {
const wizardDirectiveForChild = parseChildren.pipe(Effect.flatMap(directive => {
if (InternalCommandDirective.isBuiltIn(directive) && InternalBuiltInOptions.isShowWizard(directive.option)) {

@@ -406,4 +380,4 @@ return Effect.succeed(directive);

return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty));
})));
return parseInternal(self.parent, parentArgs, config).pipe(Effect.flatMap(directive => {
}));
return Effect.suspend(() => parseInternal(self.parent, parentArgs, config).pipe(Effect.flatMap(directive => {
switch (directive._tag) {

@@ -426,9 +400,9 @@ case "BuiltIn":

if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
return parseInternal(self.child, args, config).pipe(Effect.mapBoth({
return parseChildren.pipe(Effect.mapBoth({
onFailure: err => {
if (InternalValidationError.isCommandMismatch(err)) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "");
const subcommandNames = pipe(ReadonlyArray.fromIterable(HashMap.keys(subcommands)), ReadonlyArray.map(name => `'${name}'`));
const oneOf = subcommandNames.length === 1 ? "" : " one of";
const error = InternalHelpDoc.p(`Invalid subcommand for ${parentName} - use${oneOf} ${ReadonlyArray.join(subcommandNames, ", ")}`);
const childNames = ReadonlyArray.map(subcommands, ([name]) => `'${name}'`);
const oneOf = childNames.length === 1 ? "" : " one of";
const error = InternalHelpDoc.p(`Invalid subcommand for ${parentName} - use${oneOf} ${ReadonlyArray.join(childNames, ", ")}`);
return InternalValidationError.commandMismatch(error);

@@ -450,3 +424,3 @@ }

}
}), Effect.catchSome(() => ReadonlyArray.isEmptyReadonlyArray(args) ? Option.some(helpDirectiveForParent) : Option.none()));
}), Effect.catchSome(() => ReadonlyArray.isEmptyReadonlyArray(args) ? Option.some(helpDirectiveForParent) : Option.none())));
}

@@ -486,8 +460,2 @@ }

}
case "OrElse":
{
// TODO: if both the left and right commands also have help defined, that
// help will be overwritten by this method which may be undesirable
return orElse(withDescriptionInternal(self.left, description), withDescriptionInternal(self.right, description));
}
case "Subcommands":

@@ -498,3 +466,3 @@ {

op.parent = withDescriptionInternal(self.parent, description);
op.child = self.child;
op.children = self.children.slice();
return op;

@@ -509,3 +477,4 @@ }

switch (self._tag) {
case "SingleCommandWizard":
case "GetUserInput":
case "Standard":
{

@@ -517,11 +486,11 @@ return Effect.gen(function* (_) {

}));
if (isStandard(self.command)) {
if (isStandard(self)) {
// Log the current command line arguments
yield* _(logCurrentCommand);
const commandName = InternalSpan.highlight(self.command.name, Color.magenta);
const commandName = InternalSpan.highlight(self.name, Color.magenta);
// If the command has options, run the wizard for them
if (!InternalOptions.isEmpty(self.command.options)) {
if (!InternalOptions.isEmpty(self.options)) {
const message = InternalHelpDoc.p(InternalSpan.concat(optionsWizardHeader, commandName));
yield* _(Console.log(InternalHelpDoc.toAnsiText(message)));
const options = yield* _(InternalOptions.wizard(self.command.options, config));
const options = yield* _(InternalOptions.wizard(self.options, config));
yield* _(Ref.updateAndGet(commandLineRef, ReadonlyArray.appendAll(options)));

@@ -531,6 +500,6 @@ yield* _(logCurrentCommand);

// If the command has args, run the wizard for them
if (!InternalArgs.isEmpty(self.command.args)) {
if (!InternalArgs.isEmpty(self.args)) {
const message = InternalHelpDoc.p(InternalSpan.concat(argsWizardHeader, commandName));
yield* _(Console.log(InternalHelpDoc.toAnsiText(message)));
const options = yield* _(InternalArgs.wizard(self.command.args, config));
const options = yield* _(InternalArgs.wizard(self.args, config));
yield* _(Ref.updateAndGet(commandLineRef, ReadonlyArray.appendAll(options)));

@@ -543,79 +512,24 @@ yield* _(logCurrentCommand);

}
case "AlternativeCommandWizard":
case "Map":
{
const makeChoice = (title, value) => ({
return loop(self.command, commandLineRef);
}
case "Subcommands":
{
const description = InternalHelpDoc.p("Select which command you would like to execute");
const message = InternalHelpDoc.toAnsiText(description).trimEnd();
const makeChoice = (title, index) => ({
title,
value: [title, value]
value: [title, index]
});
const choices = self.alternatives.map(alternative => {
switch (alternative._tag) {
case "SingleCommandWizard":
{
return makeChoice(alternative.command.name, alternative);
}
case "SubcommandWizard":
{
return makeChoice(alternative.names, alternative);
}
}
});
const description = InternalHelpDoc.p("Select which command you would like to execute");
const message = InternalHelpDoc.toAnsiText(description).trimEnd();
return InternalSelectPrompt.select({
const choices = pipe(Array.from(getSubcommandsInternal(self)), ReadonlyArray.map(([name], index) => makeChoice(name, index)));
return loop(self.parent, commandLineRef).pipe(Effect.zipRight(InternalSelectPrompt.select({
message,
choices
}).pipe(Effect.tap(([name]) => Ref.update(commandLineRef, ReadonlyArray.append(name))), Effect.zipLeft(Console.log()), Effect.flatMap(([, nextSequence]) => loop(nextSequence, commandLineRef)));
}).pipe(Effect.tap(([name]) => Ref.update(commandLineRef, ReadonlyArray.append(name))), Effect.zipLeft(Console.log()), Effect.flatMap(([, nextIndex]) => loop(self.children[nextIndex], commandLineRef)))));
}
case "SubcommandWizard":
{
return loop(self.parent, commandLineRef).pipe(Effect.zipRight(loop(self.child, commandLineRef)));
}
}
};
return Ref.make(prefix).pipe(Effect.flatMap(commandLineRef => loop(getWizardCommandSequence(self), commandLineRef).pipe(Effect.zipRight(Ref.get(commandLineRef)))));
return Ref.make(prefix).pipe(Effect.flatMap(commandLineRef => loop(self, commandLineRef).pipe(Effect.zipRight(Ref.get(commandLineRef)))));
};
/**
* Creates an intermediate data structure that allows commands to be properly
* sequenced by the prompts of Wizard Mode.
*/
const getWizardCommandSequence = self => {
switch (self._tag) {
case "Standard":
case "GetUserInput":
{
return {
_tag: "SingleCommandWizard",
command: self
};
}
case "Map":
{
return getWizardCommandSequence(self.command);
}
case "OrElse":
{
const left = getWizardCommandSequence(self.left);
const leftAlternatives = left._tag === "AlternativeCommandWizard" ? left.alternatives : ReadonlyArray.of(left);
const right = getWizardCommandSequence(self.right);
const rightAlternatives = right._tag === "AlternativeCommandWizard" ? right.alternatives : ReadonlyArray.of(right);
const alternatives = ReadonlyArray.appendAll(leftAlternatives, rightAlternatives);
return {
_tag: "AlternativeCommandWizard",
alternatives
};
}
case "Subcommands":
{
const names = pipe(ReadonlyArray.fromIterable(getNamesInternal(self.parent)), ReadonlyArray.join(" | "));
const parent = getWizardCommandSequence(self.parent);
const child = getWizardCommandSequence(self.child);
return {
_tag: "SubcommandWizard",
names,
parent,
child
};
}
}
};
// =============================================================================

@@ -638,3 +552,2 @@ // Completion Internals

}
case "OrElse":
case "Subcommands":

@@ -677,17 +590,11 @@ {

}
case "OrElse":
{
const left = loop(self.left, parentCommands, subcommands, level);
const right = loop(self.right, parentCommands, subcommands, level);
return Effect.zipRight(left, right);
}
case "Subcommands":
{
const parentNames = Array.from(getNamesInternal(self.parent));
const nextSubcommands = Array.from(getSubcommandsInternal(self.child));
const nextSubcommands = Array.from(getSubcommandsInternal(self));
const nextParentCommands = ReadonlyArray.appendAll(parentCommands, parentNames);
// Traverse the parent command using old parent names and next subcommands
return loop(self.parent, parentCommands, nextSubcommands, level).pipe(Effect.zipRight(
return loop(self.parent, parentCommands, nextSubcommands, level).pipe(Effect.zipRight(Effect.forEach(self.children, child =>
// Traverse the child command using next parent names and old subcommands
loop(self.child, nextParentCommands, subcommands, level + 1)));
loop(child, nextParentCommands, subcommands, level + 1))));
}

@@ -782,14 +689,8 @@ }

}
case "OrElse":
{
const left = getZshSubcommandCases(self.left, parentCommands, subcommands);
const right = getZshSubcommandCases(self.right, parentCommands, subcommands);
return ReadonlyArray.appendAll(left, right);
}
case "Subcommands":
{
const nextSubcommands = Array.from(getSubcommandsInternal(self.child));
const nextSubcommands = Array.from(getSubcommandsInternal(self));
const parentNames = Array.from(getNamesInternal(self.parent));
const parentLines = getZshSubcommandCases(self.parent, parentCommands, ReadonlyArray.appendAll(subcommands, nextSubcommands));
const childCases = getZshSubcommandCases(self.child, ReadonlyArray.appendAll(parentCommands, parentNames), subcommands);
const childCases = pipe(self.children, ReadonlyArray.flatMap(child => getZshSubcommandCases(child, ReadonlyArray.appendAll(parentCommands, parentNames), subcommands)));
const hyphenName = pipe(ReadonlyArray.appendAll(parentCommands, parentNames), ReadonlyArray.join("-"));

@@ -807,5 +708,5 @@ const childLines = pipe(parentNames, ReadonlyArray.flatMap(parentName => ["case $state in", ` (${parentName})`, ` words=($line[1] "\${words[@]}")`, " (( CURRENT += 1 ))", ` curcontext="\${curcontext%:*:*}:${hyphenName}-command-$line[1]:"`, ` case $line[1] in`, ...indentAll(childCases, 8), " esac", " ;;", "esac"]), ReadonlyArray.appendAll(ReadonlyArray.isEmptyReadonlyArray(parentCommands) ? ReadonlyArray.empty() : ReadonlyArray.of(";;")));

op.error = InternalHelpDoc.empty;
op.showHelp = InternalBuiltInOptions.showHelp(getUsageInternal(command), getHelpInternal(command));
op.showHelp = InternalBuiltInOptions.showHelp(getUsageInternal(command), getHelpInternal(command, InternalCliConfig.defaultConfig));
return op;
};
//# sourceMappingURL=commandDescriptor.js.map

@@ -150,2 +150,4 @@ import * as Console from "effect/Console";

/** @internal */
export const secret = name => makeSingle(name, ReadonlyArray.empty(), InternalPrimitive.secret);
/** @internal */
export const text = name => makeSingle(name, ReadonlyArray.empty(), InternalPrimitive.text);

@@ -741,3 +743,3 @@ // =============================================================================

{
return parseInternal(self.options, args, config).pipe(Effect.catchTag("MissingValue", e => Effect.mapError(Effect.config(self.config), () => e)));
return parseInternal(self.options, args, config).pipe(Effect.catchTag("MissingValue", e => Effect.mapError(self.config, () => e)));
}

@@ -744,0 +746,0 @@ }

import * as FileSystem from "@effect/platform/FileSystem";
// import * as AnsiRender from "@effect/printer-ansi/AnsiRender"
// import * as AnsiStyle from "@effect/printer-ansi/AnsiStyle"
// import * as Color from "@effect/printer-ansi/Color"
// import * as Doc from "@effect/printer/Doc"
import * as Schema from "@effect/schema/Schema";

@@ -12,2 +8,3 @@ import * as Effect from "effect/Effect";

import * as ReadonlyArray from "effect/ReadonlyArray";
import * as EffectSecret from "effect/Secret";
import * as InternalCliConfig from "./cliConfig.js";

@@ -53,2 +50,4 @@ import * as InternalHelpDoc from "./helpDoc.js";

/** @internal */
export const isSecretType = self => self._tag === "Path";
/** @internal */
export const isTextType = self => self._tag === "Text";

@@ -107,2 +106,8 @@ // =============================================================================

/** @internal */
export const secret = /*#__PURE__*/(() => {
const op = /*#__PURE__*/Object.create(proto);
op._tag = "Secret";
return op;
})();
/** @internal */
export const text = /*#__PURE__*/(() => {

@@ -147,2 +152,3 @@ const op = /*#__PURE__*/Object.create(proto);

case "Path":
case "Secret":
case "Text":

@@ -208,2 +214,6 @@ {

}
case "Secret":
{
return InternalSpan.text("A user-defined piece of text that is confidential.");
}
case "Text":

@@ -244,2 +254,6 @@ {

}
case "Secret":
{
return "secret";
}
case "Text":

@@ -291,2 +305,6 @@ {

}
case "Secret":
{
return attempt(value, getTypeNameInternal(self), Schema.parse(Schema.string)).pipe(Effect.map(value => EffectSecret.fromString(value)));
}
case "Text":

@@ -384,2 +402,10 @@ {

}
case "Secret":
{
const primitiveHelp = InternalHelpDoc.p("Enter some text (value will be hidden)");
const message = InternalHelpDoc.sequence(help, primitiveHelp);
return InternalTextPrompt.hidden({
message: InternalHelpDoc.toAnsiText(message).trimEnd()
});
}
case "Text":

@@ -408,2 +434,3 @@ {

case "Integer":
case "Secret":
case "Text":

@@ -447,2 +474,3 @@ {

case "Integer":
case "Secret":
case "Text":

@@ -517,2 +545,3 @@ {

}
case "Secret":
case "Text":

@@ -519,0 +548,0 @@ {

@@ -9,2 +9,3 @@ import * as Terminal from "@effect/platform/Terminal";

import * as ReadonlyArray from "effect/ReadonlyArray";
import * as Secret from "effect/Secret";
import * as InternalPrompt from "../prompt.js";

@@ -167,7 +168,6 @@ import * as InternalPromptAction from "./action.js";

};
/** @internal */
export const text = options => {
const basePrompt = (options, type) => {
const opts = {
default: "",
type: "text",
type,
validate: Effect.succeed,

@@ -224,2 +224,8 @@ ...options

};
/** @internal */
export const hidden = options => basePrompt(options, "hidden").pipe(InternalPrompt.map(Secret.fromString));
/** @internal */
export const password = options => basePrompt(options, "password").pipe(InternalPrompt.map(Secret.fromString));
/** @internal */
export const text = options => basePrompt(options, "text");
//# sourceMappingURL=text.js.map

@@ -133,2 +133,7 @@ import * as InternalOptions from "./internal/options.js";

*/
export const secret = InternalOptions.secret;
/**
* @since 1.0.0
* @category constructors
*/
export const text = InternalOptions.text;

@@ -135,0 +140,0 @@ // =============================================================================

@@ -61,2 +61,7 @@ import * as InternalPrompt from "./internal/prompt.js";

*/
export const hidden = InternalTextPrompt.hidden;
/**
* @since 1.0.0
* @category constructors
*/
export const integer = InternalNumberPrompt.integer;

@@ -74,2 +79,7 @@ /**

/**
* @since 1.0.0
* @category constructors
*/
export const password = InternalTextPrompt.password;
/**
* Executes the specified `Prompt`.

@@ -76,0 +86,0 @@ *

{
"name": "@effect/cli",
"version": "0.24.0",
"version": "0.25.0",
"description": "Functional programming in TypeScript",

@@ -13,9 +13,9 @@ "license": "MIT",

"peerDependencies": {
"@effect/platform": "^0.33.0",
"@effect/printer": "^0.26.0",
"@effect/printer-ansi": "^0.27.0",
"@effect/schema": "^0.52.0",
"effect": "2.0.0-next.59"
"@effect/platform": "^0.34.0",
"@effect/printer": "^0.27.0",
"@effect/printer-ansi": "^0.28.0",
"@effect/schema": "^0.53.0",
"effect": "2.0.0-next.60"
},
"main": "./index.js",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",

@@ -28,3 +28,3 @@ "types": "./dist/dts/index.d.ts",

"import": "./dist/esm/index.js",
"default": "./index.js"
"default": "./dist/cjs/index.js"
},

@@ -34,3 +34,3 @@ "./Args": {

"import": "./dist/esm/Args.js",
"default": "./Args.js"
"default": "./dist/cjs/Args.js"
},

@@ -40,3 +40,3 @@ "./AutoCorrect": {

"import": "./dist/esm/AutoCorrect.js",
"default": "./AutoCorrect.js"
"default": "./dist/cjs/AutoCorrect.js"
},

@@ -46,3 +46,3 @@ "./BuiltInOptions": {

"import": "./dist/esm/BuiltInOptions.js",
"default": "./BuiltInOptions.js"
"default": "./dist/cjs/BuiltInOptions.js"
},

@@ -52,3 +52,3 @@ "./CliApp": {

"import": "./dist/esm/CliApp.js",
"default": "./CliApp.js"
"default": "./dist/cjs/CliApp.js"
},

@@ -58,3 +58,3 @@ "./CliConfig": {

"import": "./dist/esm/CliConfig.js",
"default": "./CliConfig.js"
"default": "./dist/cjs/CliConfig.js"
},

@@ -64,3 +64,3 @@ "./Command": {

"import": "./dist/esm/Command.js",
"default": "./Command.js"
"default": "./dist/cjs/Command.js"
},

@@ -70,3 +70,3 @@ "./CommandDescriptor": {

"import": "./dist/esm/CommandDescriptor.js",
"default": "./CommandDescriptor.js"
"default": "./dist/cjs/CommandDescriptor.js"
},

@@ -76,3 +76,3 @@ "./CommandDirective": {

"import": "./dist/esm/CommandDirective.js",
"default": "./CommandDirective.js"
"default": "./dist/cjs/CommandDirective.js"
},

@@ -82,3 +82,3 @@ "./HelpDoc": {

"import": "./dist/esm/HelpDoc.js",
"default": "./HelpDoc.js"
"default": "./dist/cjs/HelpDoc.js"
},

@@ -88,3 +88,3 @@ "./HelpDoc/Span": {

"import": "./dist/esm/HelpDoc/Span.js",
"default": "./HelpDoc/Span.js"
"default": "./dist/cjs/HelpDoc/Span.js"
},

@@ -94,3 +94,3 @@ "./Options": {

"import": "./dist/esm/Options.js",
"default": "./Options.js"
"default": "./dist/cjs/Options.js"
},

@@ -100,3 +100,3 @@ "./Primitive": {

"import": "./dist/esm/Primitive.js",
"default": "./Primitive.js"
"default": "./dist/cjs/Primitive.js"
},

@@ -106,3 +106,3 @@ "./Prompt": {

"import": "./dist/esm/Prompt.js",
"default": "./Prompt.js"
"default": "./dist/cjs/Prompt.js"
},

@@ -112,3 +112,3 @@ "./Prompt/Action": {

"import": "./dist/esm/Prompt/Action.js",
"default": "./Prompt/Action.js"
"default": "./dist/cjs/Prompt/Action.js"
},

@@ -118,3 +118,3 @@ "./Usage": {

"import": "./dist/esm/Usage.js",
"default": "./Usage.js"
"default": "./dist/cjs/Usage.js"
},

@@ -124,3 +124,3 @@ "./ValidationError": {

"import": "./dist/esm/ValidationError.js",
"default": "./ValidationError.js"
"default": "./dist/cjs/ValidationError.js"
}

@@ -127,0 +127,0 @@ },

@@ -12,2 +12,3 @@ /**

import type { NonEmptyReadonlyArray } from "effect/ReadonlyArray"
import type { Secret } from "effect/Secret"
import type { CliConfig } from "./CliConfig.js"

@@ -326,2 +327,12 @@ import type { HelpDoc } from "./HelpDoc.js"

*
* Can optionally provide a custom argument name (defaults to `"secret"`).
*
* @since 1.0.0
* @category constructors
*/
export const secret: (config?: Args.BaseArgsConfig) => Args<Secret> = InternalArgs.secret
/**
* Creates a text argument.
*
* Can optionally provide a custom argument name (defaults to `"text"`).

@@ -328,0 +339,0 @@ *

@@ -17,6 +17,10 @@ /**

* Whether or not the argument parser should be case sensitive.
*
* Defaults to `false`.
*/
readonly isCaseSensitive: boolean
/**
* Threshold for when to show auto correct suggestions.
* Levenstein distance threshold for when to show auto correct suggestions.
*
* Defaults to `2`.
*/

@@ -27,2 +31,4 @@ readonly autoCorrectLimit: number

* a built-in option, even if the provided command is not valid.
*
* Defaults to `false`.
*/

@@ -33,7 +39,18 @@ readonly finalCheckBuiltIn: boolean

* particular command.
*
* Defaults to `true`.
*/
readonly showAllNames: boolean
/**
* Whether or not to display built-in options in the help documentation
* generated for a `Command`.
*
* Defaults to `true`.
*/
readonly showBuiltIns: boolean
/**
* Whether or not to display the type of an option in the usage of a
* particular command.
*
* Defaults to `true`.
*/

@@ -40,0 +57,0 @@ readonly showTypes: boolean

@@ -147,4 +147,6 @@ /**

*/
export const getHelp: <Name extends string, R, E, A>(self: Command<Name, R, E, A>) => HelpDoc =
Internal.getHelp
export const getHelp: <Name extends string, R, E, A>(
self: Command<Name, R, E, A>,
config: CliConfig
) => HelpDoc = Internal.getHelp

@@ -151,0 +153,0 @@ /**

@@ -110,3 +110,3 @@ /**

*/
export const getHelp: <A>(self: Command<A>) => HelpDoc = Internal.getHelp
export const getHelp: <A>(self: Command<A>, config: CliConfig) => HelpDoc = Internal.getHelp

@@ -113,0 +113,0 @@ /**

@@ -12,2 +12,3 @@ import type * as FileSystem from "@effect/platform/FileSystem"

import * as Ref from "effect/Ref"
import type * as Secret from "effect/Secret"
import type * as Args from "../Args.js"

@@ -228,2 +229,8 @@ import type * as CliConfig from "../CliConfig.js"

/** @internal */
export const secret = (
config: Args.Args.BaseArgsConfig = {}
): Args.Args<Secret.Secret> =>
makeSingle(Option.fromNullable(config.name), InternalPrimitive.secret)
/** @internal */
export const text = (config: Args.Args.BaseArgsConfig = {}): Args.Args<string> =>

@@ -774,3 +781,3 @@ makeSingle(Option.fromNullable(config.name), InternalPrimitive.text)

Effect.map(
Effect.mapError(Effect.config(self.config), () => e),
Effect.mapError(self.config, () => e),
(value) => [args, value] as [ReadonlyArray<string>, any]

@@ -777,0 +784,0 @@ ))

@@ -294,12 +294,7 @@ import type * as Terminal from "@effect/platform/Terminal"

case "Map": {
command = command.command as InternalCommand.Instruction
command = command.command
break
}
case "OrElse": {
prefix = ReadonlyArray.empty()
command = undefined
break
}
case "Subcommands": {
command = command.parent as InternalCommand.Instruction
command = command.parent
break

@@ -306,0 +301,0 @@ }

@@ -19,4 +19,5 @@ import * as Context from "effect/Context"

autoCorrectLimit: 2,
finalCheckBuiltIn: true,
finalCheckBuiltIn: false,
showAllNames: true,
showBuiltIns: true,
showTypes: true

@@ -23,0 +24,0 @@ }

@@ -1,3 +0,3 @@

import type { FileSystem } from "@effect/platform/FileSystem"
import type { QuitException, Terminal } from "@effect/platform/Terminal"
import type * as FileSystem from "@effect/platform/FileSystem"
import type * as Terminal from "@effect/platform/Terminal"
import * as Context from "effect/Context"

@@ -8,4 +8,4 @@ import * as Effect from "effect/Effect"

import { globalValue } from "effect/GlobalValue"
import type { HashMap } from "effect/HashMap"
import type { HashSet } from "effect/HashSet"
import type * as HashMap from "effect/HashMap"
import type * as HashSet from "effect/HashSet"
import type * as Option from "effect/Option"

@@ -17,10 +17,10 @@ import { pipeArguments } from "effect/Pipeable"

import type * as CliApp from "../CliApp.js"
import type { CliConfig } from "../CliConfig.js"
import type * as CliConfig from "../CliConfig.js"
import type * as Command from "../Command.js"
import type * as Descriptor from "../CommandDescriptor.js"
import type { HelpDoc } from "../HelpDoc.js"
import type { Span } from "../HelpDoc/Span.js"
import type * as HelpDoc from "../HelpDoc.js"
import type * as Span from "../HelpDoc/Span.js"
import type * as Options from "../Options.js"
import type * as Prompt from "../Prompt.js"
import type { Usage } from "../Usage.js"
import type * as Usage from "../Usage.js"
import * as ValidationError from "../ValidationError.js"

@@ -228,4 +228,5 @@ import * as InternalArgs from "./args.js"

export const getHelp = <Name extends string, R, E, A>(
self: Command.Command<Name, R, E, A>
): HelpDoc => InternalDescriptor.getHelp(self.descriptor)
self: Command.Command<Name, R, E, A>,
config: CliConfig.CliConfig
): HelpDoc.HelpDoc => InternalDescriptor.getHelp(self.descriptor, config)

@@ -235,3 +236,3 @@ /** @internal */

self: Command.Command<Name, R, E, A>
): HashSet<string> => InternalDescriptor.getNames(self.descriptor)
): HashSet.HashSet<string> => InternalDescriptor.getNames(self.descriptor)

@@ -262,3 +263,3 @@ /** @internal */

self: Command.Command<Name, R, E, A>
): HashMap<string, Descriptor.Command<unknown>> =>
): HashMap.HashMap<string, Descriptor.Command<unknown>> =>
InternalDescriptor.getSubcommands(self.descriptor)

@@ -269,3 +270,3 @@

self: Command.Command<Name, R, E, A>
): Usage => InternalDescriptor.getUsage(self.descriptor)
): Usage.Usage => InternalDescriptor.getUsage(self.descriptor)

@@ -299,3 +300,3 @@ const mapDescriptor = dual<

(
help: string | HelpDoc
help: string | HelpDoc.HelpDoc
) => <Name extends string, R, E, A>(

@@ -306,3 +307,3 @@ self: Command.Command<Name, R, E, A>

self: Command.Command<Name, R, E, A>,
help: string | HelpDoc
help: string | HelpDoc.HelpDoc
) => Command.Command<Name, R, E, A>

@@ -400,8 +401,8 @@ >(2, (self, help) => mapDescriptor(self, InternalDescriptor.withDescription(help)))

prefix: ReadonlyArray<string>,
config: CliConfig
config: CliConfig.CliConfig
) => <Name extends string, R, E, A>(
self: Command.Command<Name, R, E, A>
) => Effect.Effect<
FileSystem | Terminal,
QuitException | ValidationError.ValidationError,
FileSystem.FileSystem | Terminal.Terminal,
Terminal.QuitException | ValidationError.ValidationError,
ReadonlyArray<string>

@@ -412,6 +413,6 @@ >,

prefix: ReadonlyArray<string>,
config: CliConfig
config: CliConfig.CliConfig
) => Effect.Effect<
FileSystem | Terminal,
QuitException | ValidationError.ValidationError,
FileSystem.FileSystem | Terminal.Terminal,
Terminal.QuitException | ValidationError.ValidationError,
ReadonlyArray<string>

@@ -426,4 +427,4 @@ >

readonly version: string
readonly summary?: Span | undefined
readonly footer?: HelpDoc | undefined
readonly summary?: Span.Span | undefined
readonly footer?: HelpDoc.HelpDoc | undefined
}) => <Name extends string, R, E, A>(

@@ -437,4 +438,4 @@ self: Command.Command<Name, R, E, A>

readonly version: string
readonly summary?: Span | undefined
readonly footer?: HelpDoc | undefined
readonly summary?: Span.Span | undefined
readonly footer?: HelpDoc.HelpDoc | undefined
}) => (

@@ -441,0 +442,0 @@ args: ReadonlyArray<string>

@@ -64,3 +64,2 @@ import type * as FileSystem from "@effect/platform/FileSystem"

| Map
| OrElse
| Subcommands

@@ -90,3 +89,3 @@

Op<"Map", {
readonly command: Descriptor.Command<unknown>
readonly command: Instruction
readonly f: (value: unknown) => Either.Either<ValidationError.ValidationError, unknown>

@@ -97,14 +96,6 @@ }>

/** @internal */
export interface OrElse extends
Op<"OrElse", {
readonly left: Descriptor.Command<unknown>
readonly right: Descriptor.Command<unknown>
}>
{}
/** @internal */
export interface Subcommands extends
Op<"Subcommands", {
readonly parent: Descriptor.Command<unknown>
readonly child: Descriptor.Command<unknown>
readonly parent: Instruction
readonly children: ReadonlyArray.NonEmptyReadonlyArray<Instruction>
}>

@@ -132,5 +123,2 @@ {}

/** @internal */
export const isOrElse = (self: Instruction): self is OrElse => self._tag === "OrElse"
/** @internal */
export const isSubcommands = (self: Instruction): self is Subcommands => self._tag === "Subcommands"

@@ -177,8 +165,10 @@

/** @internal */
export const getHelp = <A>(self: Descriptor.Command<A>): HelpDoc.HelpDoc =>
getHelpInternal(self as Instruction)
export const getHelp = <A>(
self: Descriptor.Command<A>,
config: CliConfig.CliConfig
): HelpDoc.HelpDoc => getHelpInternal(self as Instruction, config)
/** @internal */
export const getNames = <A>(self: Descriptor.Command<A>): HashSet.HashSet<string> =>
getNamesInternal(self as Instruction)
HashSet.fromIterable(getNamesInternal(self as Instruction))

@@ -210,3 +200,3 @@ /** @internal */

): HashMap.HashMap<string, Descriptor.Command<unknown>> =>
getSubcommandsInternal(self as Instruction)
HashMap.fromIterable(getSubcommandsInternal(self as Instruction))

@@ -241,30 +231,2 @@ /** @internal */

/** @internal */
export const orElse = dual<
<B>(
that: Descriptor.Command<B>
) => <A>(self: Descriptor.Command<A>) => Descriptor.Command<A | B>,
<A, B>(
self: Descriptor.Command<A>,
that: Descriptor.Command<B>
) => Descriptor.Command<A | B>
>(2, (self, that) => {
const op = Object.create(proto)
op._tag = "OrElse"
op.left = self
op.right = that
return op
})
/** @internal */
export const orElseEither = dual<
<B>(
that: Descriptor.Command<B>
) => <A>(self: Descriptor.Command<A>) => Descriptor.Command<Either.Either<A, B>>,
<A, B>(
self: Descriptor.Command<A>,
that: Descriptor.Command<B>
) => Descriptor.Command<Either.Either<A, B>>
>(2, (self, that) => orElse(map(self, Either.left), map(that, Either.right)))
/** @internal */
export const parse = dual<

@@ -335,15 +297,4 @@ (

op.parent = self
if (ReadonlyArray.isNonEmptyReadonlyArray(subcommands)) {
const mapped = ReadonlyArray.map(
subcommands,
([id, command]) => map(command, (a) => [id, a] as const)
)
const head = ReadonlyArray.headNonEmpty<Descriptor.Command<any>>(mapped)
const tail = ReadonlyArray.tailNonEmpty<Descriptor.Command<any>>(mapped)
op.child = ReadonlyArray.isNonEmptyReadonlyArray(tail)
? ReadonlyArray.reduce(tail, head, orElse)
: head
return op
}
throw new Error("[BUG]: Command.subcommands - received empty list of subcommands")
op.children = ReadonlyArray.map(subcommands, ([id, command]) => map(command, (a) => [id, a]))
return op
})

@@ -376,3 +327,3 @@

const getHelpInternal = (self: Instruction): HelpDoc.HelpDoc => {
const getHelpInternal = (self: Instruction, config: CliConfig.CliConfig): HelpDoc.HelpDoc => {
switch (self._tag) {

@@ -387,3 +338,6 @@ case "Standard": {

: InternalHelpDoc.sequence(InternalHelpDoc.h1("ARGUMENTS"), argsHelp)
const optionsHelp = InternalOptions.getHelp(self.options)
const options = config.showBuiltIns
? Options.all([self.options, InternalBuiltInOptions.builtIns])
: self.options
const optionsHelp = InternalOptions.getHelp(options)
const optionsSection = InternalHelpDoc.isEmpty(optionsHelp)

@@ -400,10 +354,4 @@ ? InternalHelpDoc.empty

case "Map": {
return getHelpInternal(self.command as Instruction)
return getHelpInternal(self.command, config)
}
case "OrElse": {
return InternalHelpDoc.sequence(
getHelpInternal(self.left as Instruction),
getHelpInternal(self.right as Instruction)
)
}
case "Subcommands": {

@@ -433,20 +381,18 @@ const getUsage = (

case "Map": {
return getUsage(command.command as Instruction, preceding)
return getUsage(command.command, preceding)
}
case "OrElse": {
return ReadonlyArray.appendAll(
getUsage(command.left as Instruction, preceding),
getUsage(command.right as Instruction, preceding)
)
}
case "Subcommands": {
const parentUsage = getUsage(command.parent as Instruction, preceding)
const parentUsage = getUsage(command.parent, preceding)
return Option.match(ReadonlyArray.head(parentUsage), {
onNone: () => getUsage(command.child as Instruction, preceding),
onNone: () =>
ReadonlyArray.flatMap(
command.children,
(child) => getUsage(child, preceding)
),
onSome: ([usage]) => {
const childUsage = getUsage(
command.child as Instruction,
ReadonlyArray.append(preceding, usage)
const childrenUsage = ReadonlyArray.flatMap(
command.children,
(child) => getUsage(child, ReadonlyArray.append(preceding, usage))
)
return ReadonlyArray.appendAll(parentUsage, childUsage)
return ReadonlyArray.appendAll(parentUsage, childrenUsage)
}

@@ -479,6 +425,9 @@ })

return InternalHelpDoc.sequence(
getHelpInternal(self.parent as Instruction),
getHelpInternal(self.parent, config),
InternalHelpDoc.sequence(
InternalHelpDoc.h1("COMMANDS"),
printSubcommands(getUsage(self.child as Instruction, ReadonlyArray.empty()))
printSubcommands(ReadonlyArray.flatMap(
self.children,
(child) => getUsage(child, ReadonlyArray.empty())
))
)

@@ -490,19 +439,13 @@ )

const getNamesInternal = (self: Instruction): HashSet.HashSet<string> => {
const getNamesInternal = (self: Instruction): ReadonlyArray<string> => {
switch (self._tag) {
case "Standard":
case "GetUserInput": {
return HashSet.make(self.name)
return ReadonlyArray.of(self.name)
}
case "Map": {
return getNamesInternal(self.command as Instruction)
return getNamesInternal(self.command)
}
case "OrElse": {
return HashSet.union(
getNamesInternal(self.right as Instruction),
getNamesInternal(self.left as Instruction)
)
}
case "Subcommands": {
return getNamesInternal(self.parent as Instruction)
return getNamesInternal(self.parent)
}

@@ -514,21 +457,25 @@ }

self: Instruction
): HashMap.HashMap<string, GetUserInput | Standard> => {
switch (self._tag) {
case "Standard":
case "GetUserInput": {
return HashMap.make([self.name, self])
): ReadonlyArray<[string, GetUserInput | Standard]> => {
const loop = (
self: Instruction,
isSubcommand: boolean
): ReadonlyArray<[string, GetUserInput | Standard]> => {
switch (self._tag) {
case "Standard":
case "GetUserInput": {
return ReadonlyArray.of([self.name, self])
}
case "Map": {
return loop(self.command, isSubcommand)
}
case "Subcommands": {
// Ensure that we only traverse the subcommands one level deep from the
// parent command
return isSubcommand
? loop(self.parent, false)
: ReadonlyArray.flatMap(self.children, (child) => loop(child, true))
}
}
case "Map": {
return getSubcommandsInternal(self.command as Instruction)
}
case "OrElse": {
return HashMap.union(
getSubcommandsInternal(self.left as Instruction),
getSubcommandsInternal(self.right as Instruction)
)
}
case "Subcommands": {
return getSubcommandsInternal(self.parent as Instruction)
}
}
return loop(self, false)
}

@@ -551,11 +498,8 @@

case "Map": {
return getUsageInternal(self.command as Instruction)
return getUsageInternal(self.command)
}
case "OrElse": {
return InternalUsage.mixed
}
case "Subcommands": {
return InternalUsage.concat(
getUsageInternal(self.parent as Instruction),
getUsageInternal(self.child as Instruction)
getUsageInternal(self.parent),
InternalUsage.mixed
)

@@ -579,20 +523,21 @@ }

args: ReadonlyArray<string>
): Effect.Effect<never, ValidationError.ValidationError, ReadonlyArray<string>> => {
if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
const head = ReadonlyArray.headNonEmpty(args)
const tail = ReadonlyArray.tailNonEmpty(args)
const normalizedArgv0 = InternalCliConfig.normalizeCase(config, head)
const normalizedCommandName = InternalCliConfig.normalizeCase(config, self.name)
return Effect.succeed(tail).pipe(
Effect.when(() => normalizedArgv0 === normalizedCommandName),
Effect.flatten,
Effect.catchTag("NoSuchElementException", () => {
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
})
)
}
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
}
): Effect.Effect<never, ValidationError.ValidationError, ReadonlyArray<string>> =>
ReadonlyArray.matchLeft(args, {
onEmpty: () => {
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
},
onNonEmpty: (head, tail) => {
const normalizedArgv0 = InternalCliConfig.normalizeCase(config, head)
const normalizedCommandName = InternalCliConfig.normalizeCase(config, self.name)
return Effect.succeed(tail).pipe(
Effect.when(() => normalizedArgv0 === normalizedCommandName),
Effect.flatten,
Effect.catchTag("NoSuchElementException", () => {
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
})
)
}
})
const parseBuiltInArgs = (

@@ -604,25 +549,30 @@ args: ReadonlyArray<string>

Directive.CommandDirective<never>
> => {
if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
const argv0 = ReadonlyArray.headNonEmpty(args)
const normalizedArgv0 = InternalCliConfig.normalizeCase(config, argv0)
const normalizedCommandName = InternalCliConfig.normalizeCase(config, self.name)
if (normalizedArgv0 === normalizedCommandName) {
const help = getHelpInternal(self)
const usage = getUsageInternal(self)
const options = InternalBuiltInOptions.builtInOptions(self, usage, help)
return InternalOptions.processCommandLine(options, ReadonlyArray.drop(args, 1), config)
.pipe(
Effect.flatMap((tuple) => tuple[2]),
Effect.catchTag("NoSuchElementException", () => {
const error = InternalHelpDoc.p("No built-in option was matched")
return Effect.fail(InternalValidationError.noBuiltInMatch(error))
}),
Effect.map(InternalCommandDirective.builtIn)
)
> =>
ReadonlyArray.matchLeft(args, {
onEmpty: () => {
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
},
onNonEmpty: (argv0) => {
const normalizedArgv0 = InternalCliConfig.normalizeCase(config, argv0)
const normalizedCommandName = InternalCliConfig.normalizeCase(config, self.name)
if (normalizedArgv0 === normalizedCommandName) {
const help = getHelpInternal(self, config)
const usage = getUsageInternal(self)
const options = InternalBuiltInOptions.builtInOptions(self, usage, help)
const argsWithoutCommand = ReadonlyArray.drop(args, 1)
return InternalOptions.processCommandLine(options, argsWithoutCommand, config)
.pipe(
Effect.flatMap((tuple) => tuple[2]),
Effect.catchTag("NoSuchElementException", () => {
const error = InternalHelpDoc.p("No built-in option was matched")
return Effect.fail(InternalValidationError.noBuiltInMatch(error))
}),
Effect.map(InternalCommandDirective.builtIn)
)
}
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
}
}
const error = InternalHelpDoc.p(`Missing command name: '${self.name}'`)
return Effect.fail(InternalValidationError.commandMismatch(error))
}
})
const parseUserDefinedArgs = (

@@ -713,3 +663,3 @@ args: ReadonlyArray<string>

case "Map": {
return parseInternal(self.command as Instruction, args, config).pipe(
return parseInternal(self.command, args, config).pipe(
Effect.flatMap((directive) => {

@@ -729,115 +679,119 @@ if (InternalCommandDirective.isUserDefined(directive)) {

}
case "OrElse": {
return parseInternal(self.left as Instruction, args, config).pipe(
Effect.catchSome((e) => {
return InternalValidationError.isCommandMismatch(e)
? Option.some(parseInternal(self.right as Instruction, args, config))
: Option.none()
})
)
}
case "Subcommands": {
const names = Array.from(getNamesInternal(self))
const subcommands = getSubcommandsInternal(self.child as Instruction)
const names = getNamesInternal(self)
const subcommands = getSubcommandsInternal(self)
const [parentArgs, childArgs] = ReadonlyArray.span(
args,
(name) => !HashMap.has(subcommands, name)
(arg) => !ReadonlyArray.some(subcommands, ([name]) => name === arg)
)
const parseChildren = Effect.suspend(() => {
const iterator = self.children[Symbol.iterator]()
const loop = (
next: Instruction
): Effect.Effect<
FileSystem.FileSystem | Terminal.Terminal,
ValidationError.ValidationError,
Directive.CommandDirective<any>
> => {
return parseInternal(next, childArgs, config).pipe(
Effect.catchIf(InternalValidationError.isCommandMismatch, (e) => {
const next = iterator.next()
return next.done ? Effect.fail(e) : loop(next.value)
})
)
}
return loop(iterator.next().value)
})
const helpDirectiveForParent = Effect.sync(() => {
return InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(
getUsageInternal(self),
getHelpInternal(self)
getHelpInternal(self, config)
))
})
const helpDirectiveForChild = Effect.suspend(() => {
return parseInternal(self.child as Instruction, childArgs, config).pipe(
Effect.flatMap((directive) => {
if (
InternalCommandDirective.isBuiltIn(directive) &&
InternalBuiltInOptions.isShowHelp(directive.option)
) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "")
const newDirective = InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(
InternalUsage.concat(
InternalUsage.named(ReadonlyArray.of(parentName), Option.none()),
directive.option.usage
),
directive.option.helpDoc
))
return Effect.succeed(newDirective)
}
return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty))
})
)
})
const helpDirectiveForChild = parseChildren.pipe(
Effect.flatMap((directive) => {
if (
InternalCommandDirective.isBuiltIn(directive) &&
InternalBuiltInOptions.isShowHelp(directive.option)
) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "")
const newDirective = InternalCommandDirective.builtIn(InternalBuiltInOptions.showHelp(
InternalUsage.concat(
InternalUsage.named(ReadonlyArray.of(parentName), Option.none()),
directive.option.usage
),
directive.option.helpDoc
))
return Effect.succeed(newDirective)
}
return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty))
})
)
const wizardDirectiveForParent = Effect.sync(() =>
InternalCommandDirective.builtIn(InternalBuiltInOptions.showWizard(self))
)
const wizardDirectiveForChild = Effect.suspend(() =>
parseInternal(self.child as Instruction, childArgs, config).pipe(
const wizardDirectiveForChild = parseChildren.pipe(
Effect.flatMap((directive) => {
if (
InternalCommandDirective.isBuiltIn(directive) &&
InternalBuiltInOptions.isShowWizard(directive.option)
) {
return Effect.succeed(directive)
}
return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty))
})
)
return Effect.suspend(() =>
parseInternal(self.parent, parentArgs, config).pipe(
Effect.flatMap((directive) => {
if (
InternalCommandDirective.isBuiltIn(directive) &&
InternalBuiltInOptions.isShowWizard(directive.option)
) {
return Effect.succeed(directive)
}
return Effect.fail(InternalValidationError.invalidArgument(InternalHelpDoc.empty))
})
)
)
return parseInternal(self.parent as Instruction, parentArgs, config).pipe(
Effect.flatMap((directive) => {
switch (directive._tag) {
case "BuiltIn": {
if (InternalBuiltInOptions.isShowHelp(directive.option)) {
// We do not want to display the child help docs if there are
// no arguments indicating the CLI command was for the child
return ReadonlyArray.isNonEmptyReadonlyArray(childArgs)
? Effect.orElse(helpDirectiveForChild, () => helpDirectiveForParent)
: helpDirectiveForParent
switch (directive._tag) {
case "BuiltIn": {
if (InternalBuiltInOptions.isShowHelp(directive.option)) {
// We do not want to display the child help docs if there are
// no arguments indicating the CLI command was for the child
return ReadonlyArray.isNonEmptyReadonlyArray(childArgs)
? Effect.orElse(helpDirectiveForChild, () => helpDirectiveForParent)
: helpDirectiveForParent
}
if (InternalBuiltInOptions.isShowWizard(directive.option)) {
return Effect.orElse(wizardDirectiveForChild, () => wizardDirectiveForParent)
}
return Effect.succeed(directive)
}
if (InternalBuiltInOptions.isShowWizard(directive.option)) {
return Effect.orElse(wizardDirectiveForChild, () => wizardDirectiveForParent)
}
return Effect.succeed(directive)
}
case "UserDefined": {
const args = ReadonlyArray.appendAll(directive.leftover, childArgs)
if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
return parseInternal(self.child as Instruction, args, config).pipe(Effect.mapBoth({
onFailure: (err) => {
if (InternalValidationError.isCommandMismatch(err)) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "")
const subcommandNames = pipe(
ReadonlyArray.fromIterable(HashMap.keys(subcommands)),
ReadonlyArray.map((name) => `'${name}'`)
)
const oneOf = subcommandNames.length === 1 ? "" : " one of"
const error = InternalHelpDoc.p(
`Invalid subcommand for ${parentName} - use${oneOf} ${
ReadonlyArray.join(subcommandNames, ", ")
}`
)
return InternalValidationError.commandMismatch(error)
}
return err
},
onSuccess: InternalCommandDirective.map((subcommand) => ({
...directive.value as any,
subcommand: Option.some(subcommand)
case "UserDefined": {
const args = ReadonlyArray.appendAll(directive.leftover, childArgs)
if (ReadonlyArray.isNonEmptyReadonlyArray(args)) {
return parseChildren.pipe(Effect.mapBoth({
onFailure: (err) => {
if (InternalValidationError.isCommandMismatch(err)) {
const parentName = Option.getOrElse(ReadonlyArray.head(names), () => "")
const childNames = ReadonlyArray.map(subcommands, ([name]) => `'${name}'`)
const oneOf = childNames.length === 1 ? "" : " one of"
const error = InternalHelpDoc.p(
`Invalid subcommand for ${parentName} - use${oneOf} ${
ReadonlyArray.join(childNames, ", ")
}`
)
return InternalValidationError.commandMismatch(error)
}
return err
},
onSuccess: InternalCommandDirective.map((subcommand) => ({
...directive.value as any,
subcommand: Option.some(subcommand)
}))
}))
}
return Effect.succeed(InternalCommandDirective.userDefined(directive.leftover, {
...directive.value as any,
subcommand: Option.none()
}))
}
return Effect.succeed(InternalCommandDirective.userDefined(directive.leftover, {
...directive.value as any,
subcommand: Option.none()
}))
}
}
}),
Effect.catchSome(() =>
ReadonlyArray.isEmptyReadonlyArray(args)
? Option.some(helpDirectiveForParent) :
Option.none()
}),
Effect.catchSome(() =>
ReadonlyArray.isEmptyReadonlyArray(args)
? Option.some(helpDirectiveForParent) :
Option.none()
)
)

@@ -881,17 +835,9 @@ )

case "Map": {
return mapOrFail(withDescriptionInternal(self.command as Instruction, description), self.f)
return mapOrFail(withDescriptionInternal(self.command, description), self.f)
}
case "OrElse": {
// TODO: if both the left and right commands also have help defined, that
// help will be overwritten by this method which may be undesirable
return orElse(
withDescriptionInternal(self.left as Instruction, description),
withDescriptionInternal(self.right as Instruction, description)
)
}
case "Subcommands": {
const op = Object.create(proto)
op._tag = "Subcommands"
op.parent = withDescriptionInternal(self.parent as Instruction, description)
op.child = self.child
op.parent = withDescriptionInternal(self.parent, description)
op.children = self.children.slice()
return op

@@ -915,3 +861,3 @@ }

const loop = (
self: WizardCommandSequence,
self: Instruction,
commandLineRef: Ref.Ref<ReadonlyArray<string>>

@@ -924,3 +870,4 @@ ): Effect.Effect<

switch (self._tag) {
case "SingleCommandWizard": {
case "GetUserInput":
case "Standard": {
return Effect.gen(function*(_) {

@@ -938,8 +885,8 @@ const logCurrentCommand = Ref.get(commandLineRef).pipe(Effect.flatMap((commandLine) => {

}))
if (isStandard(self.command)) {
if (isStandard(self)) {
// Log the current command line arguments
yield* _(logCurrentCommand)
const commandName = InternalSpan.highlight(self.command.name, Color.magenta)
const commandName = InternalSpan.highlight(self.name, Color.magenta)
// If the command has options, run the wizard for them
if (!InternalOptions.isEmpty(self.command.options as InternalOptions.Instruction)) {
if (!InternalOptions.isEmpty(self.options as InternalOptions.Instruction)) {
const message = InternalHelpDoc.p(

@@ -949,3 +896,3 @@ InternalSpan.concat(optionsWizardHeader, commandName)

yield* _(Console.log(InternalHelpDoc.toAnsiText(message)))
const options = yield* _(InternalOptions.wizard(self.command.options, config))
const options = yield* _(InternalOptions.wizard(self.options, config))
yield* _(Ref.updateAndGet(commandLineRef, ReadonlyArray.appendAll(options)))

@@ -955,3 +902,3 @@ yield* _(logCurrentCommand)

// If the command has args, run the wizard for them
if (!InternalArgs.isEmpty(self.command.args as InternalArgs.Instruction)) {
if (!InternalArgs.isEmpty(self.args as InternalArgs.Instruction)) {
const message = InternalHelpDoc.p(

@@ -961,3 +908,3 @@ InternalSpan.concat(argsWizardHeader, commandName)

yield* _(Console.log(InternalHelpDoc.toAnsiText(message)))
const options = yield* _(InternalArgs.wizard(self.command.args, config))
const options = yield* _(InternalArgs.wizard(self.args, config))
yield* _(Ref.updateAndGet(commandLineRef, ReadonlyArray.appendAll(options)))

@@ -970,28 +917,24 @@ yield* _(logCurrentCommand)

}
case "AlternativeCommandWizard": {
const makeChoice = (title: string, value: WizardCommandSequence) => ({
case "Map": {
return loop(self.command, commandLineRef)
}
case "Subcommands": {
const description = InternalHelpDoc.p("Select which command you would like to execute")
const message = InternalHelpDoc.toAnsiText(description).trimEnd()
const makeChoice = (title: string, index: number) => ({
title,
value: [title, value] as const
value: [title, index] as const
})
const choices = self.alternatives.map((alternative) => {
switch (alternative._tag) {
case "SingleCommandWizard": {
return makeChoice(alternative.command.name, alternative)
}
case "SubcommandWizard": {
return makeChoice(alternative.names, alternative)
}
}
})
const description = InternalHelpDoc.p("Select which command you would like to execute")
const message = InternalHelpDoc.toAnsiText(description).trimEnd()
return InternalSelectPrompt.select({ message, choices }).pipe(
Effect.tap(([name]) => Ref.update(commandLineRef, ReadonlyArray.append(name))),
Effect.zipLeft(Console.log()),
Effect.flatMap(([, nextSequence]) => loop(nextSequence, commandLineRef))
const choices = pipe(
Array.from(getSubcommandsInternal(self)),
ReadonlyArray.map(([name], index) => makeChoice(name, index))
)
}
case "SubcommandWizard": {
return loop(self.parent, commandLineRef).pipe(
Effect.zipRight(loop(self.child, commandLineRef))
Effect.zipRight(
InternalSelectPrompt.select({ message, choices }).pipe(
Effect.tap(([name]) => Ref.update(commandLineRef, ReadonlyArray.append(name))),
Effect.zipLeft(Console.log()),
Effect.flatMap(([, nextIndex]) => loop(self.children[nextIndex], commandLineRef))
)
)
)

@@ -1003,3 +946,3 @@ }

Effect.flatMap((commandLineRef) =>
loop(getWizardCommandSequence(self), commandLineRef).pipe(
loop(self, commandLineRef).pipe(
Effect.zipRight(Ref.get(commandLineRef))

@@ -1011,58 +954,2 @@ )

type WizardCommandSequence = SingleCommandWizard | AlternativeCommandWizard | SubcommandWizard
interface SingleCommandWizard {
readonly _tag: "SingleCommandWizard"
readonly command: GetUserInput | Standard
}
interface AlternativeCommandWizard {
readonly _tag: "AlternativeCommandWizard"
readonly alternatives: ReadonlyArray<SingleCommandWizard | SubcommandWizard>
}
interface SubcommandWizard {
_tag: "SubcommandWizard"
readonly names: string
readonly parent: WizardCommandSequence
readonly child: WizardCommandSequence
}
/**
* Creates an intermediate data structure that allows commands to be properly
* sequenced by the prompts of Wizard Mode.
*/
const getWizardCommandSequence = (self: Instruction): WizardCommandSequence => {
switch (self._tag) {
case "Standard":
case "GetUserInput": {
return { _tag: "SingleCommandWizard", command: self }
}
case "Map": {
return getWizardCommandSequence(self.command as Instruction)
}
case "OrElse": {
const left = getWizardCommandSequence(self.left as Instruction)
const leftAlternatives = left._tag === "AlternativeCommandWizard"
? left.alternatives
: ReadonlyArray.of(left)
const right = getWizardCommandSequence(self.right as Instruction)
const rightAlternatives = right._tag === "AlternativeCommandWizard"
? right.alternatives
: ReadonlyArray.of(right)
const alternatives = ReadonlyArray.appendAll(leftAlternatives, rightAlternatives)
return { _tag: "AlternativeCommandWizard", alternatives }
}
case "Subcommands": {
const names = pipe(
ReadonlyArray.fromIterable(getNamesInternal(self.parent as Instruction)),
ReadonlyArray.join(" | ")
)
const parent = getWizardCommandSequence(self.parent as Instruction)
const child = getWizardCommandSequence(self.child as Instruction)
return { _tag: "SubcommandWizard", names, parent, child }
}
}
}
// =============================================================================

@@ -1081,5 +968,4 @@ // Completion Internals

case "Map": {
return getShortDescription(self.command as Instruction)
return getShortDescription(self.command)
}
case "OrElse":
case "Subcommands": {

@@ -1134,19 +1020,13 @@ return ""

case "Map": {
return loop(self.command as Instruction, parentCommands, subcommands, level)
return loop(self.command, parentCommands, subcommands, level)
}
case "OrElse": {
const left = loop(self.left as Instruction, parentCommands, subcommands, level)
const right = loop(self.right as Instruction, parentCommands, subcommands, level)
return Effect.zipRight(left, right)
}
case "Subcommands": {
const parentNames = Array.from(getNamesInternal(self.parent as Instruction))
const nextSubcommands = Array.from(getSubcommandsInternal(self.child as Instruction))
const parentNames = Array.from(getNamesInternal(self.parent))
const nextSubcommands = Array.from(getSubcommandsInternal(self))
const nextParentCommands = ReadonlyArray.appendAll(parentCommands, parentNames)
// Traverse the parent command using old parent names and next subcommands
return loop(self.parent as Instruction, parentCommands, nextSubcommands, level).pipe(
Effect.zipRight(
return loop(self.parent, parentCommands, nextSubcommands, level).pipe(
Effect.zipRight(Effect.forEach(self.children, (child) =>
// Traverse the child command using next parent names and old subcommands
loop(self.child as Instruction, nextParentCommands, subcommands, level + 1)
)
loop(child, nextParentCommands, subcommands, level + 1)))
)

@@ -1457,21 +1337,21 @@ }

case "Map": {
return getZshSubcommandCases(self.command as Instruction, parentCommands, subcommands)
return getZshSubcommandCases(self.command, parentCommands, subcommands)
}
case "OrElse": {
const left = getZshSubcommandCases(self.left as Instruction, parentCommands, subcommands)
const right = getZshSubcommandCases(self.right as Instruction, parentCommands, subcommands)
return ReadonlyArray.appendAll(left, right)
}
case "Subcommands": {
const nextSubcommands = Array.from(getSubcommandsInternal(self.child as Instruction))
const parentNames = Array.from(getNamesInternal(self.parent as Instruction))
const nextSubcommands = Array.from(getSubcommandsInternal(self))
const parentNames = Array.from(getNamesInternal(self.parent))
const parentLines = getZshSubcommandCases(
self.parent as Instruction,
self.parent,
parentCommands,
ReadonlyArray.appendAll(subcommands, nextSubcommands)
)
const childCases = getZshSubcommandCases(
self.child as Instruction,
ReadonlyArray.appendAll(parentCommands, parentNames),
subcommands
const childCases = pipe(
self.children,
ReadonlyArray.flatMap((child) =>
getZshSubcommandCases(
child,
ReadonlyArray.appendAll(parentCommands, parentNames),
subcommands
)
)
)

@@ -1518,5 +1398,5 @@ const hyphenName = pipe(

getUsageInternal(command as Instruction),
getHelpInternal(command as Instruction)
getHelpInternal(command as Instruction, InternalCliConfig.defaultConfig)
)
return op
}
import * as FileSystem from "@effect/platform/FileSystem"
// import * as AnsiRender from "@effect/printer-ansi/AnsiRender"
// import * as AnsiStyle from "@effect/printer-ansi/AnsiStyle"
// import * as Color from "@effect/printer-ansi/Color"
// import * as Doc from "@effect/printer/Doc"
import * as Schema from "@effect/schema/Schema"

@@ -12,2 +8,3 @@ import * as Effect from "effect/Effect"

import * as ReadonlyArray from "effect/ReadonlyArray"
import * as EffectSecret from "effect/Secret"
import type * as CliConfig from "../CliConfig.js"

@@ -57,2 +54,3 @@ import type * as HelpDoc from "../HelpDoc.js"

| Path
| Secret
| Text

@@ -92,2 +90,5 @@

/** @internal */
export interface Secret extends Op<"Secret", {}> {}
/** @internal */
export interface Text extends Op<"Text", {}> {}

@@ -126,2 +127,5 @@

/** @internal */
export const isSecretType = (self: Instruction): self is Path => self._tag === "Path"
/** @internal */
export const isTextType = (self: Instruction): self is Text => self._tag === "Text"

@@ -197,2 +201,9 @@

/** @internal */
export const secret: Primitive.Primitive<EffectSecret.Secret> = (() => {
const op = Object.create(proto)
op._tag = "Secret"
return op
})()
/** @internal */
export const text: Primitive.Primitive<string> = (() => {

@@ -269,2 +280,3 @@ const op = Object.create(proto)

case "Path":
case "Secret":
case "Text": {

@@ -332,2 +344,5 @@ return Option.none()

}
case "Secret": {
return InternalSpan.text("A user-defined piece of text that is confidential.")
}
case "Text": {

@@ -362,2 +377,5 @@ return InternalSpan.text("A user-defined piece of text.")

}
case "Secret": {
return "secret"
}
case "Text": {

@@ -443,2 +461,7 @@ return "text"

}
case "Secret": {
return attempt(value, getTypeNameInternal(self), Schema.parse(Schema.string)).pipe(
Effect.map((value) => EffectSecret.fromString(value))
)
}
case "Text": {

@@ -565,2 +588,9 @@ return attempt(value, getTypeNameInternal(self), Schema.parse(Schema.string))

}
case "Secret": {
const primitiveHelp = InternalHelpDoc.p("Enter some text (value will be hidden)")
const message = InternalHelpDoc.sequence(help, primitiveHelp)
return InternalTextPrompt.hidden({
message: InternalHelpDoc.toAnsiText(message).trimEnd()
})
}
case "Text": {

@@ -589,2 +619,3 @@ const primitiveHelp = InternalHelpDoc.p("Enter some text")

case "Integer":
case "Secret":
case "Text": {

@@ -631,2 +662,3 @@ return "$(compgen -f \"${cur}\")"

case "Integer":
case "Secret":
case "Text": {

@@ -710,2 +742,3 @@ return ReadonlyArray.make("-r", "-f")

}
case "Secret":
case "Text": {

@@ -712,0 +745,0 @@ return ""

@@ -9,2 +9,3 @@ import * as Terminal from "@effect/platform/Terminal"

import * as ReadonlyArray from "effect/ReadonlyArray"
import * as Secret from "effect/Secret"
import type * as Prompt from "../../Prompt.js"

@@ -15,2 +16,9 @@ import * as InternalPrompt from "../prompt.js"

interface Options extends Required<Prompt.Prompt.TextOptions> {
/**
* The type of the text option.
*/
readonly type: "hidden" | "password" | "text"
}
interface State {

@@ -27,3 +35,3 @@ readonly cursor: number

prevState: Option.Option<State>,
options: Required<Prompt.Prompt.TextOptions>,
options: Options,
columns: number

@@ -60,3 +68,3 @@ ): Doc.AnsiDoc => {

nextState: State,
options: Required<Prompt.Prompt.TextOptions>,
options: Options,
submitted: boolean

@@ -110,3 +118,3 @@ ): Doc.AnsiDoc => {

trailingSymbol: Doc.AnsiDoc,
options: Required<Prompt.Prompt.TextOptions>,
options: Options,
submitted: boolean = false

@@ -134,3 +142,3 @@ ): Doc.AnsiDoc => {

nextState: State,
options: Required<Prompt.Prompt.TextOptions>
options: Options
): Effect.Effect<Terminal.Terminal, never, string> =>

@@ -158,3 +166,3 @@ Effect.gen(function*(_) {

nextState: State,
options: Required<Prompt.Prompt.TextOptions>
options: Options
) =>

@@ -242,7 +250,9 @@ Effect.gen(function*(_) {

/** @internal */
export const text = (options: Prompt.Prompt.TextOptions): Prompt.Prompt<string> => {
const opts: Required<Prompt.Prompt.TextOptions> = {
const basePrompt = (
options: Prompt.Prompt.TextOptions,
type: Options["type"]
): Prompt.Prompt<string> => {
const opts: Options = {
default: "",
type: "text",
type,
validate: Effect.succeed,

@@ -296,1 +306,13 @@ ...options

}
/** @internal */
export const hidden = (options: Prompt.Prompt.TextOptions): Prompt.Prompt<Secret.Secret> =>
basePrompt(options, "hidden").pipe(InternalPrompt.map(Secret.fromString))
/** @internal */
export const password = (options: Prompt.Prompt.TextOptions): Prompt.Prompt<Secret.Secret> =>
basePrompt(options, "password").pipe(InternalPrompt.map(Secret.fromString))
/** @internal */
export const text = (options: Prompt.Prompt.TextOptions): Prompt.Prompt<string> =>
basePrompt(options, "text")

@@ -13,2 +13,3 @@ /**

import type { NonEmptyReadonlyArray } from "effect/ReadonlyArray"
import type { Secret } from "effect/Secret"
import type { CliConfig } from "./CliConfig.js"

@@ -274,2 +275,8 @@ import type { HelpDoc } from "./HelpDoc.js"

*/
export const secret: (name: string) => Options<Secret> = InternalOptions.secret
/**
* @since 1.0.0
* @category constructors
*/
export const text: (name: string) => Options<string> = InternalOptions.text

@@ -276,0 +283,0 @@

@@ -8,2 +8,3 @@ /**

import type { Pipeable } from "effect/Pipeable"
import type { Secret } from "effect/Secret"
import * as InternalPrompt from "./internal/prompt.js"

@@ -289,6 +290,2 @@ import * as InternalConfirmPrompt from "./internal/prompt/confirm.js"

/**
* The type of the text option.
*/
readonly type?: "hidden" | "password" | "text"
/**
* The default value of the text option.

@@ -435,2 +432,8 @@ */

*/
export const hidden: (options: Prompt.TextOptions) => Prompt<Secret> = InternalTextPrompt.hidden
/**
* @since 1.0.0
* @category constructors
*/
export const integer: (options: Prompt.IntegerOptions) => Prompt<number> =

@@ -456,2 +459,8 @@ InternalNumberPrompt.integer

/**
* @since 1.0.0
* @category constructors
*/
export const password: (options: Prompt.TextOptions) => Prompt<Secret> = InternalTextPrompt.password
/**
* Executes the specified `Prompt`.

@@ -458,0 +467,0 @@ *

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc