Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
dist
coverage
cache
cache
.temp
4 changes: 2 additions & 2 deletions docs/en/v0/api/command/create.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
outline: [2, 3]
prev:
text: "exec"
link: "/en/v0/api/command/exec"
text: "execOptions"
link: "/en/v0/api/command/execOptions"
next:
text: "createBooleanOption"
link: "/en/v0/api/command/createBooleanOption"
Expand Down
4 changes: 2 additions & 2 deletions docs/en/v0/api/command/exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ prev:
text: "Command"
link: "/en/v0/api/command/"
next:
text: "create"
link: "/en/v0/api/command/create"
text: "execOptions"
link: "/en/v0/api/command/execOptions"
description: "Runs a CLI command from runtime arguments."
---

Expand Down
48 changes: 48 additions & 0 deletions docs/en/v0/api/command/execOptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
outline: [2, 3]
prev:
text: "exec"
link: "/en/v0/api/command/exec"
next:
text: "create"
link: "/en/v0/api/command/create"
description: "Parses CLI options from runtime arguments."
---

# execOptions

`execOptions` parses CLI options and returns the result as a `{ [optionName]: resultOption }` record.
If parsing fails, a detailed error is printed to the console.
The `--help` / `-h` output is generated automatically from the declared options.

## Example

```ts twoslash
// @version: 0
<!--@include: @/examples/v0/api/command/execOptions/main.ts-->
```

## Syntax

```typescript
function execOptions<
GenericOptions extends [Option, ...Option[]]
>(
...options: GenericOptions
): ComputeResult<GenericOptions>
```

## Parameters

- `options` (`[Option, ...Option[]]`) : options to parse from runtime arguments.

## Return value

- `ComputeResult<GenericOptions>` : object whose keys are option names and whose values are the typed result of each parser.

## See also

- [`exec`](/en/v0/api/command/exec) - Runs a full command from runtime arguments.
- [`createBooleanOption`](/en/v0/api/command/createBooleanOption) - Builds a boolean flag option.
- [`createOption`](/en/v0/api/command/createOption) - Builds a single-value option.
- [`createArrayOption`](/en/v0/api/command/createArrayOption) - Builds an array option.
3 changes: 3 additions & 0 deletions docs/en/v0/api/command/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import * as SC from "@duplojs/server-utils/command";
### [`exec`](/en/v0/api/command/exec)
creates the root command, reads process arguments, and runs the command tree.

### [`execOptions`](/en/v0/api/command/execOptions)
only parses options from process arguments.

## Command builder

### [`create`](/en/v0/api/command/create)
Expand Down
31 changes: 31 additions & 0 deletions docs/examples/v0/api/command/execOptions/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { SC } from "@duplojs/server-utils";
import { DP } from "@duplojs/utils";

const portOption = SC.createOption(
"port",
DP.coerce.number(),
{
description: "HTTP port",
required: true,
},
);

const verboseOption = SC.createBooleanOption(
"verbose",
{
aliases: ["v"],
description: "Enable verbose logs",
},
);

const options = SC.execOptions(portOption, verboseOption);
// ^?






if (options.verbose) {
console.log(`server starts on ${options.port}`);
}
4 changes: 2 additions & 2 deletions docs/fr/v0/api/command/create.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
outline: [2, 3]
prev:
text: "exec"
link: "/fr/v0/api/command/exec"
text: "execOptions"
link: "/fr/v0/api/command/execOptions"
next:
text: "createBooleanOption"
link: "/fr/v0/api/command/createBooleanOption"
Expand Down
4 changes: 2 additions & 2 deletions docs/fr/v0/api/command/exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ prev:
text: "Command"
link: "/fr/v0/api/command/"
next:
text: "create"
link: "/fr/v0/api/command/create"
text: "execOptions"
link: "/fr/v0/api/command/execOptions"
description: "Lance une commande CLI à partir des arguments du runtime."
---

Expand Down
48 changes: 48 additions & 0 deletions docs/fr/v0/api/command/execOptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
outline: [2, 3]
prev:
text: "exec"
link: "/fr/v0/api/command/exec"
next:
text: "create"
link: "/fr/v0/api/command/create"
description: "Parse les options CLI depuis les arguments du runtime."
---

# execOptions

`execOptions` parse les options CLI et retourne le résultat sous forme de record `{ [optionName]: resultOption }`.
Si le parsing échoue, une erreur détaillée est affichée dans la console.
Le `--help` / `-h` est généré automatiquement depuis les options déclarées.

## Exemple

```ts twoslash
// @version: 0
<!--@include: @/examples/v0/api/command/execOptions/main.ts-->
```

## Syntaxe

```typescript
function execOptions<
GenericOptions extends [Option, ...Option[]]
>(
...options: GenericOptions
): ComputeResult<GenericOptions>
```

## Paramètres

- `options` (`[Option, ...Option[]]`) : options à parser depuis les arguments du runtime.

## Valeur de retour

- `ComputeResult<GenericOptions>` : objet dont les clés sont les noms d'options et les valeurs sont les résultats typés de chaque parser.

## Voir aussi

- [`exec`](/fr/v0/api/command/exec) - Lance une commande complète depuis les arguments du runtime.
- [`createBooleanOption`](/fr/v0/api/command/createBooleanOption) - Construit une option drapeau booléenne.
- [`createOption`](/fr/v0/api/command/createOption) - Construit une option à valeur unique.
- [`createArrayOption`](/fr/v0/api/command/createArrayOption) - Construit une option tableau.
3 changes: 3 additions & 0 deletions docs/fr/v0/api/command/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import * as SC from "@duplojs/server-utils/command";
### [`exec`](/fr/v0/api/command/exec)
crée la commande racine, lit les arguments du process, puis exécute l'arbre de commandes.

### [`execOptions`](/fr/v0/api/command/execOptions)
parse uniquement les options depuis les arguments du process.

## Construction de commandes

### [`create`](/fr/v0/api/command/create)
Expand Down
117 changes: 95 additions & 22 deletions docs/libs/v0/command/create.cjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
'use strict';

var utils = require('@duplojs/utils');
var AA = require('@duplojs/utils/array');
var OO = require('@duplojs/utils/object');
var DDP = require('@duplojs/utils/dataParser');
var EE = require('@duplojs/utils/either');
var kind = require('../kind.cjs');
var exitProcess = require('../common/exitProcess.cjs');
var error = require('./error.cjs');
var help = require('./help.cjs');
var errors = require('./errors.cjs');
var boolean = require('./options/boolean.cjs');
var exitProcess = require('../common/exitProcess.cjs');

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

var AA__namespace = /*#__PURE__*/_interopNamespaceDefault(AA);
var OO__namespace = /*#__PURE__*/_interopNamespaceDefault(OO);
var DDP__namespace = /*#__PURE__*/_interopNamespaceDefault(DDP);
var EE__namespace = /*#__PURE__*/_interopNamespaceDefault(EE);

function printError(commandError, error$1) {
if (!error$1) {
// eslint-disable-next-line no-console
console.error(error.interpretCommandError(commandError));
exitProcess.exitProcess(1);
}
return error.SymbolCommandError;
}
const commandKind = kind.createDuplojsServerUtilsKind("command");
const helpOption = boolean.createBooleanOption("help", { aliases: ["h"] });
function create(...args) {
Expand All @@ -18,57 +52,96 @@ function create(...args) {
description: params.description ?? null,
options: params.options ?? [],
subject: params.subject ?? null,
execute: async (args) => {
execute: async (args, error$1) => {
const commandError = error$1 ?? error.createError(self.name);
const pathIndex = commandError.currentCommandPath.length;
if (self.subject instanceof Array) {
for (const command of self.subject) {
if (args[0] === command.name) {
await command.execute(utils.A.shift(args));
return;
let result = undefined;
error.setErrorPath(commandError, command.name, pathIndex);
try {
result = await command.execute(AA__namespace.shift(args), commandError);
}
finally {
error.popErrorPath(commandError);
}
if (result === error.SymbolCommandError) {
return printError(commandError, error$1);
}
return result;
}
}
}
const help$1 = helpOption.execute(args);
if (help$1.result) {
help.logHelp(self);
exitProcess.exitProcess(0);
return;
const help$1 = helpOption.execute(args, commandError);
if (help$1 === error.SymbolCommandError) {
return printError(commandError, error$1);
}
else if (help$1.result) {
help.logCommandHelp(self);
return void exitProcess.exitProcess(0);
}
const commandOptions = utils.A.reduce(self.options, utils.A.reduceFrom({
const commandOptions = AA__namespace.reduce(self.options, AA__namespace.reduceFrom({
options: {},
restArgs: args,
}), ({ element: option, lastValue, next }) => {
const optionResult = option.execute(lastValue.restArgs);
}), ({ element: option, lastValue, next, exit }) => {
const optionResult = option.execute(lastValue.restArgs, commandError);
if (optionResult === error.SymbolCommandError) {
return exit(error.SymbolCommandError);
}
return next({
options: utils.O.override(lastValue.options, {
options: OO__namespace.override(lastValue.options, {
[option.name]: optionResult.result,
}),
restArgs: optionResult.argumentRest,
});
});
if (commandOptions === error.SymbolCommandError) {
return printError(commandError, error$1);
}
if (self.subject === null) {
await execute({ options: commandOptions.options });
}
else if (utils.DP.identifier(self.subject, utils.DP.arrayKind)
|| utils.DP.identifier(self.subject, utils.DP.tupleKind)) {
else if (DDP__namespace.identifier(self.subject, DDP__namespace.arrayKind)
|| DDP__namespace.identifier(self.subject, DDP__namespace.tupleKind)) {
const subjectResult = self.subject.parse(commandOptions.restArgs);
if (EE__namespace.isLeft(subjectResult)) {
error.addDataParserError(commandError, utils.unwrap(subjectResult), {
type: "subject",
});
return printError(commandError, error$1);
}
await execute({
options: commandOptions.options,
subject: self.subject.parseOrThrow(commandOptions.restArgs),
subject: utils.unwrap(subjectResult),
});
}
else if (utils.DP.identifier(self.subject, utils.DP.dataParserKind)) {
else if (DDP__namespace.identifier(self.subject, DDP__namespace.dataParserKind)) {
if (commandOptions.restArgs.length > 1) {
throw new errors.CommandManyArgumentsError(commandOptions.restArgs.length);
error.addIssue(commandError, {
type: "command",
expected: "exactly one subject argument",
received: commandOptions.restArgs,
message: `Expected exactly one subject argument, received ${commandOptions.restArgs.length}.`,
});
return printError(commandError, error$1);
}
const subjectResult = self.subject.parse(commandOptions.restArgs);
if (EE__namespace.isLeft(subjectResult)) {
error.addDataParserError(commandError, utils.unwrap(subjectResult), {
type: "subject",
});
return printError(commandError, error$1);
}
await execute({
options: commandOptions.options,
subject: self.subject.parseOrThrow(commandOptions.restArgs),
subject: utils.unwrap(subjectResult),
});
}
else {
await execute({});
}
exitProcess.exitProcess(0);
return;
return void exitProcess.exitProcess(0);
},
});
return self;
Expand Down
Loading
Loading