fn-to-cli
Table of contents
Installation
npm install fn-to-cli
Description
This module converts typescript functions to CLI.
Code coverage
Code coverage is around 90%.
Quick start
For a quick start:
-
execute from terminal:
npx fn-to-cli --help;
-
add
@CLI
JSDoc tag comment to the functions you want to convert to CLI -
compile your typescript project to javascript project
-
execute from terminal:
npx fn-to-cli;
If something goes wrong you will receive helpful error messages that will guide you on resolving the error.
Example
-
Create a new folder and set it as your current working directory:
mkdir example; cd ./example;
-
Create
./package.json
with the following content:{ "name": "some-random-package-name", "version": "1.0.0", "private": true, "main": "./dist/index.js", "bin": "bin/bin.js", "scripts": { "build-ts": "rm -rf ./dist; npx tsc", "build-bin": "rm -rf ./bin; npx fn-to-cli", "build": "npm run build-ts && npm run build-bin", "test": "jest" }, "devDependencies": { "jest": "^26.6.3", "typescript": "^4.2.3" }, "dependencies": { "fn-to-cli": "file:.." } }
Notice the bin property in
./package.json
. This is used byfn-to-cli
as a path to output the generated CLI. -
Delete from
./package.json
the line:"fn-to-cli": "../"
-
Install
fn-to-cli
:npm install fn-to-cli;
this will also install the rest of the dependencies.
-
Create
./tsconfig.json
with the following content:{ "compilerOptions": { "rootDir": "./src", "outDir": "./dist", "module": "CommonJS", "target": "ESNext", "declaration": true }, "exclude": [ "node_modules" ] }
-
Create
./src/index.ts
with the following content:export { foo } from "./foo";
-
Create
./src/foo.ts
with the following content:/** * Some tag less description for command foo. * @CLI */ export function foo(_: { /** * @description * Some tag full description for option `a` of command `foo`. */ a: string; /** * Some tag less description for option `b` of command `foo`. * @default true * @flag V */ b?: boolean; }): void { const { a } = _; let { b } = _; if (b === undefined) b = true; console.log(`foo executed with a = "${a}", b = ${b}`); }
-
Create
./src/bar/bar.ts
with the following content:/** * @description * Some tag full description for command `bar`. * @CLI baz */ export default function bar(_: { /** * Some tag less description for option `c` of command `bar`. */ c: boolean; /** * Some tag less description for option `d` of command `bar`. * @private * @default true */ d?: boolean; }): void { const { c } = _; let { d } = _; if (d === undefined) d = true; console.log(`bar executed with c = ${c}, d = ${d}`); }
-
Execute:
npm run build;
This command does two things:
- builds typescript to javascript
- generates the CLI
-
Now you can use the generated CLI. Here are some examples:
node ./bin/bin.js foo --a "'hello'"; node ./bin/bin.js foo --a "'hello'" -V "false"; node ./bin/bin.js baz --c "false";
Documentation
Execute the following command:
npx fn-to-cli --help
to get the CLI documentation:
CLI syntax:
fn-to-cli fnToCLI? [[--<option> | -<flag>] <value>]#
Description:
Converts typescript functions to CLI.
Non required options:
-t --pathToTsconfig : string = "./tsconfig.json" Path to `tsconfig.json`.
-p --pathToPackageJson : string = "./package.json" Path to `package.json`.
-s --strict : boolean = false For one command CLI, it is optional to write the command name when using the CLI. Give `true` to disable that.
The CLI generator works by searching deeply in the directory defined by the property compilerOptions.outDir
of tsconfig.json
, for all the .d.ts
files that have functions with @CLI
JSDoc tag. These functions become commands to the generated CLI.
The generated CLI is saved to the path defined by the bin
property of package.json
, and imports js functions from the directories compilerOptions.outDir
, and node_modules
, so it will not work if these folders are missing or moved.
Each function with the @CLI
JSDoc tag has to:
-
have a single parameter that is
TypeLiteral
, for example:{ param1 : string, param2 : boolean }
-
be a function declaration statement, for example:
-
incorrect:
const foo = () => { //some code };
-
correct:
function foo() { //some code }
-
-
be named or default exported
-
have name
-
have description in its JSDoc comment via a
@description
tag or tag-less -
same for each property in its parameter type signature
-
have
@default
JSDoc tag with initialization value for each optional parameter -
be inside the
rootDir
directory as defined by the providedtsconfig.json
-
be in a
.ts
file
The functions can have:
-
@flag
JSDoc tag for any of its properties. It has to have a single letter as a value which can be used instead of the parameter names in the CLI. -
@cliPrivate
JSDoc tag for any of its optional properties. These properties will not be visible in the documentation of the CLI and will not receive a value even if the user of the CLI provides one for them.
Motivation
A typescript function with JSDoc comments, contains all the necessary information to be converted automatically to a cli. Why would anyone waste their time doing the conversion manually? Automating that is the only maintainable solution.
Contributing
I am open to suggestions/pull request to improve this program.
You will find the following commands useful:
-
Clones the github repository of this project:
git clone https://github.com/lillallol/fn-to-cli
-
Installs the node modules (nothing will work without them):
npm install
-
Tests the source code:
npm run test-src
-
Tests the example in the example folder:
npm run test-example
-
Lints the source folder using typescript and eslint:
npm run lint
-
Builds the typescript code from the
./src
folder to javascript code in./dist
:npm run build-ts
-
Creates the CLI executable of this program in
./bin/bin.js
:npm run build-bin
Make sure that the
./dist
exists when you execute this command, otherwise it will not work. -
Injects in place the generated toc and imported files to
README.md
:npm run build-md
-
Checks the project for spelling mistakes:
npm run spell-check
Take a look at the related configuration
./cspell.json
. -
Checks
./src
for dead typescript files:npm run dead-files
Take a look at the related configuration
./unimportedrc.json
.
Changelog
2.0.3
Removed package name and version from the CLI generated documentation.
2.0.2
Removed the unnecessary quotation marks from the default values in the CLI generated documentation.
2.0.1
bug fixes:
Moved typescript-is
from development dependencies to dependencies.
2.0.0
breaking changes:
- Command line arguments are now evaluated with
eval
instead ofJSON.parse
.
-
-v
and--version
are reserved for printing the version. -
@private
JSDoc tag is now replaced with@cliPrivate
. - The
@CLI
JSDoc tag can now get a value as a custom name for the command.
non breaking changes
-
json5
node module is used for parsingpackage.json
andtsconfig.json
. That means (among others) no more headaches with trailing commas. - You can now add any type you want for command options.
- The default JSDoc tag value is no longer validated that it is the same type as the argument type.
other
-
README.md
has been improved and extra sections like changelog and contributing have been added. You can read the example section code in theREADME.md
now.
1.0.0
- Published the package to npm.
License
MIT