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.
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 with cookie as storage
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 ofbin/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.