Scaffolding with Fano CLI

What is Fano CLI?

Fano Framework allows many its core functionalities to be configured or replaced with different implementation. This has drawback. You need many boilerplate codes to create a single project.

Fano CLI is command line application to help scaffolding Fano Framework web application project. It helps tedious tasks such as creating Fano web application project, creating controller, model, view, middleware classes, generate random key and GUID, minify JavaScript files and also setting up web server configuration.

Fano CLI is supplemental tool. You can use Fano Framework without Fano CLI installed. However it is recommended to use Fano CLI as you can generate web application project easily in few seconds.

Installation

Make sure Free Pascal and git are installed. Run

$ git clone https://github.com/fanoframework/fano-cli.git
$ cd fano-cli
$ ./tools/config.setup.sh
$ ./build.sh

For easier typing, copy bin/out/fanocli executable binary to globally accessible location, for example

$ sudo cp bin/out/fanocli /usr/local/bin/fanocli

If you do not want to copy to /usr/local/bin, just add fanocli executable path to PATH environment variable.

If you use FreeBSD, after you run config.setup.sh but before run build.sh script, editbuild.cfg and replace line -Tlinux with -Tfreebsd.

Follow installation instruction in Fano CLI README.md document for more information or view Fano CLI Installation video below.

Fano CLI Installation video

View Fano CLI Help

To view available commands, you can run

$ fanocli --help

or simply

$ fanocli

To view help of single command

$ fanocli --help --task=[name of task]

or

$ fanocli --task=[name of task]

For example

$ fanocli --task=project-scgi

Creating Web Application Project

Fano CLI provides several commands for scaffolding Fano Framework web application easily, such as, --project-cgi, --project-fcgi, --project-fcgid, --project-scgi, --project-uwsgi, --project-mhd, --project-indy and --project-http which is to create web application project supporting CGI, FastCGI, SCGI and uwsgi, http protocol. Currently http implementation is using libmicrohttpd library, Indy or Free Pascal built-in TFpHttpServer class.

$ fanocli --project-cgi=[project-name]

[project-name] is directory where project resides and will be created by Fano CLI. Please read Creating Project with Fano CLI for more detail explanation of each command.

Creating controller

After you create project structure, to scaffold controller class, run with --controller command line options. For example, if [project-name] above equals to test-fano then you can create controller as follows,

$ cd test-fano
$ fanocli --controller=Hello

It will create following files

test-fano/src/App/Hello/Controllers/HelloController.pas
test-fano/src/App/Hello/Controllers/Factories/HelloControllerFactory.pas
test-fano/src/Routes/Hello/routes.inc

and also modify following files

test-fano/src/bootstrap.pas
test-fano/src/Dependencies/controllers.dependencies.inc
test-fano/src/Routes/routes.inc
test-fano/build.cfg
test-fano/build.cfg.sample

By default, it will create GET route to /hello. So after running build.sh script, you can access HelloController by visiting URL

wget http://[your host name]/hello

To create controller for certain route pattern or HTTP method, add --route and --method parameter. For example, to create controller which will handle POST request to /my/hello,

$ fanocli --controller=Hello --route=/my/hello --method=POST

If you want controller to handle multiple methods, pass methods as comma-separated values. Following example will create HelloController class that will handle GET and POST request to route /my/hello.

$ fanocli --controller=Hello --route=/my/hello --method=GET,POST

If you want to create controller and skip route creation, use --no-route parameter.

$ fanocli --controller=Hello --no-route

Creating view

After you create project structure, to scaffold view class, run with --view command line options

$ cd test-fano
$ fanocli --view=Hello

It will create following files

test-fano/src/App/Hello/Views/HelloView.pas
test-fano/src/App/Hello/Views/Factories/HelloViewFactory.pas

and also modify following files

test-fano/src/bootstrap.pas
test-fano/src/Dependencies/views.dependencies.inc
test-fano/build.cfg
test-fano/build.cfg.sample

Creating model

After you create project structure, to scaffold model class, run with --model command line option

$ cd test-fano
$ fanocli --model=Hello

It will create following files

test-fano/src/App/Hello/Models/HelloModel.pas
test-fano/src/App/Hello/Models/Factories/HelloModelFactory.pas

and also modify following files

test-fano/src/bootstrap.pas
test-fano/src/Dependencies/models.dependencies.inc
test-fano/build.cfg
test-fano/build.cfg.sample

Creating controller, view and model at same time

To simplify creating controller, view and model at same time, you can use --mvc command line option.

$ fanocli --mvc=Hello

Command above is equal to following command

$ fanocli --controller=Hello
$ fanocli --model=Hello
$ fanocli --view=Hello

Add middleware support

Any project creation commands, i.e, --project* commands, accept additional parameter --with-middleware. If it is set, then during project creation, middleware support is added to generated project.

$ fanocli --project-cgi=Hello --with-middleware

Creating middleware

To scaffold middleware class, run with --middleware command line options

$ cd test-fano
$ fanocli --middleware=AuthOnly

It will create following files

test-fano/src/Middlewares/AuthOnly/AuthOnlyMiddleware.pas
test-fano/src/Middlewares/AuthOnly/Factories/AuthOnlyMiddlewareFactory.pas

Generate random key

To generate random key (for example, encryption secret key), run with --key=[length] command line options

$ fanocli --key=32

If length is not set, it is assumed 64 bytes of random value. Output is Base64 encoded string of random bytes. In unix or Linux, it reads from /dev/urandom. In Windows, it uses CryptoAPI.

Generate GUID

To generate GUID, run with --guid command line options

$ fanocli --guid

Minify JavaScript files

To reduce JavaScript file size, run with --jsmin=[path] command line options.

With [path] empty, it will scan current directory for any JavaScript files and minify them and output as new file with name using original file name appended with min.js.

$ fanocli --jsmin

With [path] not empty, if it is directory, it scans that directory for any JavaScript files and minifies them and output as new file with name using original file name appended with min.js. If [path] is single file, it minifies it and create new file with same name appended with min.js.

$ fanocli --jsmin=/path/to/js

If you specify optional --output=[target-path] parameter, then [target-path] will be used as its filename.

$ fanocli --jsmin=/path/to/js --output=/path/to/js/scripts.min.js

If [target-path] equals stdout, minified output is printed to STDOUT.

$ fanocli --jsmin=/path/to/js --output=stdout

Minify CSS files

To reduce CSS file size, run with --cssmin=[path] command line options.

With [path] empty, it will scan current directory for any CSS files and minify them and output as new file with name using original file name appended with min.css.

$ fanocli --cssmin

With [path] not empty, if it is directory, it scans that directory for any CSS files and minifies them and output as new file with name using original file name appended with min.css. If [path] is single file, it minifies it and create new file with same name appended with min.css.

$ fanocli --cssmin=/path/to/css

If you specify optional --output=[target-path] parameter, then [target-path] will be used as its filename.

$ fanocli --cssmin=/path/to/css --output=/path/to/css/styles.min.css

If [target-path] equals stdout, minified output is printed to STDOUT.

$ fanocli --cssmin=/path/to/css --output=stdout

Add session support

Any project creation commands, i.e, --project* commands, accept additional parameter --with-session=[session storage] where session storage value can be one of following value

  • file, create session which stores session data in file.
  • cookie, create session which stores session data in encrypted cookie.
  • db, create session which stores session data in database.

Session with file as storage

If [session storage] is not set then it is assumed file. So following commands are identical

$ fanocli --project-cgi=Hello --with-session=file
$ fanocli --project-cgi=Hello --with-session

Session data is stored in encrypted cookie.

$ fanocli --project-cgi=Hello --with-session=cookie

Session with database as storage

$ fanocli --project-cgi=Hello --with-session=db

You can set type of RDBMS to use with --db parameter. If it is not set, it assumes MySQL. Following command is same as above.

$ fanocli --project-cgi=Hello --with-session=db --db=mysql

Use postgresql,firebird and sqlite for PostgreSQL, Firebird and SQLite database respectively.

$ fanocli --project-cgi=Hello --with-session=db --db=postgresql

Session data format

For file, cookie and db, you can define format of session data with --type parameter which expect value of json or ini for JSON or INI format respectively.

For example, following command will cause session support to be added to project and each session data will be stored as INI file.

$ fanocli --project-cgi=Hello --with-session=file --type=ini

Session requires middleware

Because in Fano Framework, session support is implemented with middleware infrastructure, --with-session implies usage of --with-middleware so following command are identical

$ fanocli --project-cgi=Hello --with-session
$ fanocli --project-cgi=Hello --with-session --with-middleware

Please read Working with Session for more information about session.

Add CSRF support

Any project creation commands, i.e, --project* commands, accept additional parameter --with-csrf. If it is set, then during project creation, Cross-Site Request Forgery (CSRF) protection is added to generated project.

$ fanocli --project-scgi=Hello --with-csrf

--with-csrf adds --config and --with-session parameters implicitly, so following command generate similar project.

$ fanocli --project-scgi=Hello --with-csrf
$ fanocli --project-scgi=Hello --config --with-session --with-csrf

Add logger dependencies

Any project creation commands, i.e, --project* commands, accept additional parameter --with-logger. If it is set, then during project creation, logger dependencies is added to generated project.

Add logger that store logs in file

$ fanocli --project-scgi=Hello --with-logger=file

Add logger that store logs in database

$ fanocli --project-scgi=Hello --with-logger=db

Add logger that store logs in syslog

$ fanocli --project-scgi=Hello --with-logger=syslog

Deployment

Fano CLI offers commands to simplify setting up Fano web application with various web server through following commands,

  • --deploy-cgi, setup Fano CGI web application with a web server.
  • --deploy-fcgi, setup Fano FastCGI web application with a web server as reverse proxy.
  • --deploy-fcgid, setup Fano FastCGI web application with a Apache web server and mod_fcgid.
  • --deploy-scgi , setup Fano SCGI web application with a web server as reverse proxy.
  • --deploy-lb-scgi , setup Fano SCGI web application with a web server as reverse proxy and load balancer.
  • --deploy-lb-fcgi , setup Fano FastCGI web application with a web server as reverse proxy and load balancer.
  • --deploy-uwsgi , setup Fano uwsgi web application with a web server as reverse proxy.
  • --deploy-lb-uwsgi , setup Fano uwsgi web application with a web server as reverse proxy and load balancer.
  • --deploy-http , setup Fano http web application with a web server as reverse proxy.
  • --deploy-lb-http , setup Fano http web application with a web server as reverse proxy and load balancer.

All commands above requires root privilege, so you need to run it with sudo.

$ sudo fanocli --deploy-cgi=myapp.com

Developer is responsible to make sure that deployment matched project type. For example, project created with --project-fcgi can only be deployed with --deploy-fcgi or --deploy-lb-fcgi.

Read Deployment for more information on how to use commands above.

Setup daemon as service in systemd

In Linux distribution which use systemd, such as latest Fedora or Debian, Fano CLI provides command --daemon-sysd=[service name] to simplify registering daemon web application with systemd.

$ sudo fanocli --daemon-sysd=hello

After that, you can run application using following command,

$ sudo systemctl start hello

or to stop it,

$ sudo systemctl stop hello

--daemon-sysd command accept additional parameter,

  • --user=[username], username whose application is run as. If not set, then current non-root user is used.
  • --bin=[application binary path], absolute path to application executable binary. If not set then it is assumed absolute path of bin/app.cgi.
$ sudo fanocli --daemon-sysd=hello --user=fano --bin=/home/my.fano/bin/myapp.bin

Convert text file content into Pascal string variable declaration

To allow include HTML file directly as an include file, you can convert it into Pascal string variable declaration using --txt2inc command.

For example, if you have file index.html with content as follows

<html><head></head>
<body></body></html>

To convert it as include file, run

$ fanocli --txt2inc --src=index.html --dst=index.html.inc --var=htmlTemplate

It will create index.html.inc file with content as follows,

htmlTemplate : string =
    '<html><head></head>' + LineEnding +
    '<body></body></html>';

which you can include it in Pascal code

procedure print();
var
    {$INCLUDE index.html.inc}
begin
    writeln(htmlTemplate);
end;

Parameters

Parameter --src tells source file path to convert. If it is not set or empty, STDIN will be used. If it is set but file does not exist, error is generated.

Parameter --dst tells destination file path. If it is not set or empty and --src is set then value of --src is concatenated with .inc file extension. If it is not set or empty and --src is not set, STDOUT will be used. If --dst is set but file does exist, error is generated to avoid accidentally overwriting existing file. To force overwriting existing file, add --force parameter.

Parameter --var sets variable name to use for declaration. If it is not set, then myStr is used.

For example

$ printf "<html><head></head>\r\n<body></body></html>" | fanocli --txt2inc

{-------------begin----------------}
myStr : string =
    '<html><head></head>' + LineEnding +
    '<body></body></html>';
{-------------end------------------}

Build

Change active directory to new project directory after you created project and run

$ /build.sh

to build application.

Explore more