siokas / denomander Goto Github PK
View Code? Open in Web Editor NEWDeno command-line interfaces made easy
Home Page: https://doc.deno.land/https/deno.land/x/denomander/docs.ts
License: MIT License
Deno command-line interfaces made easy
Home Page: https://doc.deno.land/https/deno.land/x/denomander/docs.ts
License: MIT License
There should be an object to hold all the option values passed from the arguments. Currently the options are accessible only from the main Denomander object instance.
Consider something similar to this:
const programOptions = program.opts();
console.log(programOptions.name);
All validation logic seems a bit messy and its not scalable.
.validateArgs() .validateOnCommands() .validateRequiredOptions() .validateOptionsAndCommands()
When a command is provide with more than one argument, VALIDATION_ARG_NOT_FOUND is thrown
repro steps :
import Denomander from "https://raw.githubusercontent.com/siokas/denomander/master/mod.ts";
const program = new Denomander({
app_name: "My MY App",
app_description: "My MY Description",
app_version: "1.0.1",
});
program
.command("token [email] [password]")
.action((email: string, password : any) => {
console.log(email, password);
})
.description("get bearer token");
try {
program.parse(Deno.args);
} catch (error) {
console.log(error);
}
deno run .\index.ts token email password
outputs Error: Argument not found in available commands!
When a required options is set for a command, it must be provide for all commands instead of just the one adding it
deno run https://raw.githubusercontent.com/siokas/denomander/master/example.ts clone folder
outputs : Error: Required option is not specified!
deno run https://raw.githubusercontent.com/siokas/denomander/master/example.ts clone folder -p 8080
outputs: The repo is cloned into: folder
throwned
should be thrown
I think.
Specify a function to do custom processing of option values.
Take a look on the commander.js feature https://github.com/tj/commander.js#custom-option-processing
The following warnings are shown when downloading denomander:
Download https://deno.land/[email protected]/testing/asserts.ts
Warning std versions prefixed with 'v' will be deprecated soon. Please change your import to https://deno.land/[email protected]/fmt/colors.ts (at https://deno.land/[email protected]/fmt/colors.ts)
Download https://deno.land/[email protected]/fmt/colors.ts
Warning std versions prefixed with 'v' will be deprecated soon. Please change your import to https://deno.land/[email protected]/testing/asserts.ts (at https://deno.land/[email protected]/testing/asserts.ts)
Download https://deno.land/[email protected]/testing/asserts.ts
Warning std versions prefixed with 'v' will be deprecated soon. Please change your import to https://deno.land/[email protected]/flags/mod.ts (at https://deno.land/[email protected]/flags/mod.ts)
Hi,
Allow me to give you a little feedback, do with it what you want, feel free to ignore.
The quality of the code you produce is very good but I think the main problem with commander.js is that it was designed for vanilla JavaScript. Its API design does not allow type inference...
Maybe you should keep the denomander
name and the logo which is really cool and join forces with u/KSXGitHub to work on https://github.com/KSXGitHub/deno-args which look really promising.
I think for commander.js a simple fork using denoify to make it cross-compatible is enough.
However, what you did is cool.
Cheers
Another enhancement: I tried using subcommands with denomander (based on https://github.com/tj/commander.js/blob/master/examples/nestedCommands.js), and denomander works nicely. However, when using --help
, each subcommand is treated as if they are main commands instead of hierachically under the main command. Adding 2 spaces would make the relationship clearer to an end user.
Prefix _ (underscore) in the url.
The following program complains, Required option is not specified!
, even when it is. As far as I can tell, it has to do with the presence of a hyphen in the option.
import Denomander from "https://deno.land/x/denomander/mod.ts";
new Denomander({ app_name: '', app_description: '', app_version: '' })
.requiredOption('--hyphenated-option', '')
.parse(Deno.args);
Also, in case I might be preemptive, I suggest only using the invalid
issue label for irrelevant issues, as suggested here.
I'm not a native english speaker... but choises looks like a potential typo to me. Was it deliberately called that way or did you intend it to be called choices instead?
deno cache 'https://x.nest.land/denomander/mod.ts'
results in "not found error".When using .option("-a --action", "Name of Action") how can i get hold of the option value? It gets overwritten by the action function itself ... In general i dont think its a good idea to expose the options on the program object itself. Why not make everything available at the first param of the action callback ?
The reason for the error can be seen here: https://stackoverflow.com/a/63887967
The error message is as follows.
error: TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Denomander } from "./Denomander.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/src/interfaces.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Arguments } from "./Arguments.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/src/Validator.ts:2:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Kernel } from "./Kernel.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/src/Validator.ts:3:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Command } from "./Command.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/src/Validator.ts:4:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { ValidatorContract } from "./interfaces.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/src/Validator.ts:5:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Option } from "./Option.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/src/Validator.ts:13:1
I took a quick look at the API and also into printCommandHelp
and figured there's no way to specify a description for an argument. This is a bit of a bummer because it limits the usefulness of the generated help text
Description:
Transform service instances using specified handlers
Command Usage:
transform [path] {Options}
Arguments:
path
Required Options:
-o --out Path to the out repo
Options:
-h --help Help Screen
It would be great if we could specify the same kind of description as for options.
Consider Typedoc or something similar to auto-generate a documentation for the api.
Also consider a wiki
Is it possible to add an option that pics up all the remaining args? like
program.command("test [args...]").action(({args}) => {
console.log(args);
});
$ deno run test.ts test foo bar foo2 bar2
foo bar foo2 bar2
Not able to use import map feature. Please advise.
$ deno run --import-map=import-maps.json my-first-deno-program.js -h
error: Uncaught SyntaxError: The requested module 'denomander/mod.ts' does not provide an export named 'Denomander'
export { Denomander } from "denomander/mod.ts";
^
at <anonymous> (file:///lang/deno/dependencies.js:1:10)
$ cat import-maps.json
{
"imports": {
"denomander/": "https://deno.land/x/[email protected]/"
}
}
$ cat dependencies.js
export { Denomander } from "denomander/mod.ts";
$ cat my-first-deno-program.js
import { Denomander } from "./dependencies.js";
const program = new Denomander({
app_name: "My App Name",
app_description: "My App Description",
app_version: "1.0.1",
});
program
.command("serve", "Start the server")
.alias("server", "start-server")
.action(() => {
console.log("the server is started");
});
$ deno info https://deno.land/x/[email protected]/mod.ts | head
local: /home/.cache/deno/deps/https/deno.land/5be3b5383be15d79eb1fd49da8662bc89f5d3df67ccbac67808450d7f673a7e3
emit: /home/.cache/deno/gen/https/deno.land/5be3b5383be15d79eb1fd49da8662bc89f5d3df67ccbac67808450d7f673a7e3.js
type: TypeScript
dependencies: 25 unique (total 133.73KB)
$ cat /home/.cache/deno/deps/https/deno.land/5be3b5383be15d79eb1fd49da8662bc89f5d3df67ccbac67808450d7f673a7e3
import Denomander from "./src/Denomander.ts";
export { default as Option } from "./src/CustomOption.ts";
export { error_log, success_log, warning_log } from "./src/utils/print.ts";
export default Denomander;
Due to deno.land update their module exporting system, this "https://deno.land/[email protected]/fmt/colors.ts" is no longer supported
Can you change it to without that "v"?
Separate the logic for creating command over option
Hi! Is there a way to allow for optional arguments?
Right now, if I use command
program.command("command [value]")
it will result in an error if I don't provide a value.
However, I would like to have this value optional, is this possible in the current version?
Hi, I have two mandatory actions, but Denomander seems to get confused about what the right choices are, it mixes things up. Did I find a bug?
import { default as Denomander, Option as DenomanderOption } from "https://deno.land/x/[email protected]/mod.ts";
const projectActions: string[] = [
"clone",
"reset",
"flavor",
"clean",
"prepare",
"build",
"tag",
"release",
"exec",
"wipe",
];
const projectNames: string[] = [
"core",
"explorer",
"wallet",
"desktop",
"android",
"ios",
];
program
.command("proj", "Executes a given action on a project.")
.option(
"-s --slug",
"Execute the action on a different slug than provided in the env configuration. (optional)"
)
.option(
"-b --base-slug",
"Execute the action from a different slug origin than provided in the env configuration. (optional)"
)
.addOption(
new DenomanderOption({
flags: "-a --action",
description: "Action to execute.",
isRequired: true,
}).choices(projectActions)
)
.addOption(
new DenomanderOption({
flags: "-n --name",
description: "Name of the project.",
isRequired: true,
}).choices([...projectNames, "all"])
)
.action(async () => {
});
program.parse(Deno.args);
> deno run ./demo.ts proj -a flavor -n core
❌ Error (a): Invalid option choice! Argument 'flavor' is invalid. Allowed choices are: core,explorer,wallet,desktop,android,ios,all
@siokas Am I missing something?
program
.command("open", "Opens a foo.")
.addOption(
new Option({
flags: "-f --foo",
description: "Open something",
isRequired: true,
choices: ["a", "b", "c"],
})
)
.action(async () => {
console.log(program.foo);
});
Testing:
> ./my-test.ts open
undefined
> ./my-test.ts open -f d
d
In both cases it should complain that either -f
is missing or d
is not a valid choice. This doesn't work.
examples/example.ts throws an error.
OPTION_CHOICE
is required in errors
object.
const program = new Denomander(
{
app_name: "My MY App",
app_description: "My MY Description",
app_version: "1.0.1",
errors: {
INVALID_RULE: "Invalid Rule",
OPTION_NOT_FOUND: "Option not found!",
COMMAND_NOT_FOUND: "Command not found!",
REQUIRED_OPTION_NOT_FOUND: "Required option is not specified!",
REQUIRED_VALUE_NOT_FOUND: "Required command value is not specified!",
TOO_MANY_PARAMS: "You have passed too many parameters",
+ OPTION_CHOICE: "Invalid option choice!",
},
},
);
deno 1.36.1 (release, x86_64-pc-windows-msvc)
v8 11.6.189.12
typescript 5.1.6
Running a script with a simple import as per documentation
import Denomander from "https://deno.land/x/denomander/mod.ts";
you get this error
C:\temp>deno run -A --unstable test-deanomander-import.ts
error: missing field `now` at line 9 column 1
at file:///C:/temp/test-deanomander-import.ts:2:24
C:\temp>
Hi! I found a bug which happens when passing a number to a command.
How to reproduce:
import Denomander from "https://deno.land/x/denomander/mod.ts";
const program = new Denomander();
program.command("foo [bar]", "Foo")
program.globalOption("--baz", "Baz")
program.parse(Deno.args);
deno run mod.ts foo 1
The error:
error: Uncaught TypeError: text.substr is not a function
return text.substr(0, 2).replace(/-/g, "") +
^
at Function.stripDashes (https://deno.land/x/[email protected]/src/Helper.ts:5:17)
at https://deno.land/x/[email protected]/src/Util.ts:112:43
at Array.find (<anonymous>)
at Function.findCommandFromArgs (https://deno.land/x/[email protected]/src/Util.ts:111:18)
at https://deno.land/x/[email protected]/src/Executor.ts:28:30
at Array.forEach (<anonymous>)
at Executor.defaultCommands (https://deno.land/x/[email protected]/src/Executor.ts:27:26)
at Denomander.execute (https://deno.land/x/[email protected]/src/Kernel.ts:130:10)
at Denomander.run (https://deno.land/x/[email protected]/src/Kernel.ts:218:8)
at Denomander.parse (https://deno.land/x/[email protected]/src/Denomander.ts:15:10)
Also, when passing an option e.g. deno run mod.ts foo bar --baz buz
, both bar and baz will have the value buz
instead of foo=bar
and baz=buz
It would be really nice when an error occurs to show the following instead of what is there now:
Error: You specified an option (--https) that is not defined for the command (serve).
or something more like bash
serve: illegal option -- https
usage: serve [-ap]
This would be much cleaner for the end user. The current error made me think that there was an error in my code, when the error was actually in the command line I typed.
Excellent module by the way!
Even though it works fine as it is, there should be no non-null assertions in the project. Currently I use the ❗️ postfix operator but I should consider a better logic here. Maybe a non undefined var or a check-before-use solution.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.