Getting started
-
To start a bare-bone server
npm run watchNow point your browser to http://localhost:8000/doc.html
The server is running with default configuration, while no custom code is loaded it still can serve internal API requests described below and serve static assets from the web/ folder.
-
Programmatic way to start the server
$ node > const { server, api } = require('backendjs') > server.start({ api: 1 }) -
By default access is allowed only with valid session or signature, to see all public urls type in the node shell above:
> api.allowPathThis property of the api module corresponds to the the
-api-allow-pathconfig parameter, see it in your browser at docs. -
No database driver is enabled by default so here are examples to load local PostgreSQL, DynamoDB or ElasticSearch
bkjs run -api -db-pool sqlite -db-sqlite-pool bkjs run -api -db-pool pg -db-pg-pool bkjs run -api -db-pool dynamodb -db-dynamodb-pool bkjs run -api -db-pool elasticsearch -db-elasticsearch-pool -
All command line parameters from the above can be saved in the
~.bkjs/etc/config.localmaking pg the default databasedb-pool=sqlite db-sqlite-pool=default db-pg-pool=default db-dynamdb-pool=default db-elasticsearch-pool=default -
To start Node.js shell with backendjs loaded and initialized, all internal modules in shell are global for convenience
bkjs shell -
Here is preview how the database can be accessed using internal DB methods with native Sqlite module:
bkjs shell -db-sqlite-pool -db-pool sqlite -db-create-tables > db.select("bk_user", {}, lib.log); > db.add("bk_user", { login: 'test2', name: 'Test2 name' }, lib.log); > db.select("bk_user", { login: 'test2' }, lib.log); > db.select("bk_user", { login: ['test1','test2'] }, { ops: { login: "in" } }, lib.log);
or the same using async/await, same methods with a prepended to the name
> await db.aselect("bk_user", {});
> await db.aadd("bk_user", { login: 'test2', name: 'Test2 name' });
> await db.aselect("bk_user", { login: 'test2' });
-
To search using Elasticsearch full text capabilities
> await db.aselect("bk_user", { q: 'test' }, { pool: "elasticsearch" });
To run an example
-
The library is packaged with copies of Bootstrap, jQuery, Knockout.js, Alpine.js for quick Web prototyping in web/js and web/css directories, all scripts are available from the browser with /js or /css paths.
-
Go to
examplesdirectory, it has several apps with README.md explaining how to run each. -
Go to an application directory and run:
./app.sh -
When the web server is started with
-watchparameter or asbkjs watchthen any change in the source files will make the server restart automatically letting you focus on the source code and not server management, this mode is only enabled by default in development mode, checkapp.shfor parameters before running it in production.
Dependencies
Only core required dependencies are installed but there are many modules which require a module to work correctly.
All optional dependencies are listed in the package.json under "optionalDependencies" so npm cannot use it, only manual install of required modules is supported or it is possible to install all optional dependencies for development purposes.
Here is the list of modules for each internal feature:
pg- PostgreSQL database accessredis- for Redis queue and cache driverunix-dgram- for Linux to use local syslog via Unix domainweb-push- for Web push notificationssharp- scaling images in uploads using VPS imagingnats- NATS driver for queue and events
The command below will show all core and optional dependencies, npm install will install only the core dependencies
npm install --include=optional
Configuration
Almost everything in the backend is configurable using config files or a config database. The whole principle behind it is that once deployed in production, sometimes even quick restarts are impossible to do so there should be a way to push config changes to the processes without restarting.
Every module defines a set of config parameters that defines the behavior of the code, due to the single threaded nature of the Node.js. It is simple to update any config parameter to a new value so the code can operate differently. To achieve this the code must be written in a special way, like driven by configuration which can be changed at any time.
All configuration goes through the configuration process that checks all inputs and produces valid output which is applied to the module variables. Config file or database table with configuration can be loaded on demand or periodically, for example all local config files are watched for modification and reloaded automatically, the config database is loaded periodically which is defined by another config parameter.
Backend runtime
When the backendjs server starts it spawns several processes that perform different tasks.
There are 2 major tasks of the backend that can be run at the same time or in any combination:
- a Web server (server) with Web workers (web)
- a job scheduler (server)
This is the typical output from the ps command on Linux server:
ec2-user 899 0.0 0.6 1073844 52892 ? Sl 14:33 0:01 bkjs: server
ec2-user 917 0.0 0.7 1072820 59008 ? Sl 14:33 0:01 bkjs: web
ec2-user 919 0.0 0.7 1072820 60792 ? Sl 14:33 0:02 bkjs: web
ec2-user 921 0.0 0.7 1072120 40721 ? Sl 14:33 0:02 bkjs: worker
To enable any task a command line parameter must be provided, it cannot be specified in the config file. The bkjs utility supports several
commands that simplify running the backend in different modes.
bkjs start- this command is supposed to be run at the server startup as a service, it runs in the background and the monitors all tasks, the env variableBKJS_SERVERmust be set in the profile toserverto start the serverbkjs watch- runs the server and Web server in wather mode checking all source files for changes, this is the common command to be used in development, it passes the command line switches:-watch -serverbkjs server- this command is supposed to be run at the server startup, it runs in the background and the monitors all processes, the command line parameters are:-daemon -server -syslog, web server and workers are started by defaultbkjs run- this command runs without other parameters, all additional parameters can be added in the command line, this command is a barebone helper to be used with any other custom settings.bkjs run -api- this command runs a single process as web server, sutable for Dockerbkjs run -worker- this command runs a single process worker, suatable for Dockerbkjs shellorbksh- start backendjs shell, no API or Web server is initialized, only the database pools
Backend directory structure
When the backend server starts and no -home argument passed in the command line the backend uses the current directory. It is also possible to set the default home using BKJS_HOME environment variable.
The backend directory structure is the following:
-
etc- configuration directory, all config files are there-
etc/bkjs.local- shell script loaded by the bkjs utility to customize env variables -
etc/config- config parameters, same as specified in the command line but without leading -, each config parameter per line:Example:
debug=1 db-pool=dynamodb db-dynamodb-pool=http://localhost:9000 db-pg-pool=postgresql://postgres@127.0.0.1/backend To specify other config file: bkjs shell -config-file file -
etc/config.local- same as the config but for the cases when local environment is different than the production or for dev specific parameters -
on startup the following local config files will be loaded if present:
etc/config.runModeandetc/config.instance.tag. These will be loaded after the main config but before config.local. The runMode is set todevby default and can be changed with-run-modeconfig parameter, the instance tag is set with-instance-tagconfig parameter. -
config files support sections that can be used for conditions, see
lib.configParsedescription for details -
etc/crontab- jobs to be run with intervals, JSON file with a list of cron jobs objects:Example:
-
Create file in ~/.backend/etc/crontab with the following contents:
[ { "cron": "0 1 1 * * 1,3", "job": { "app.cleanSessions": { "interval": 3600000 } } } ] -
Define the function that the cron will call with the options specified, callback must be called at the end, create this app.js file
const { app, db } = require("backendjs"); app.cleanSessions = function(options, callback) { db.delAll("session", { mtime: options.interval + Date.now() }, { ops: "le" }, callback); } server.start() -
Start the jobs queue and the web server at once
node app.js -server -jobs-workers 1 -jobs-cron
-
-
etc/crontab.local - additional local crontab that is read after the main one, for local or dev environment
-
-
modules- loadable modules with specific functionality -
var- database files created by the server -
tmp- temporary files -
web- Web pages served by the static Express middleware
Environment variables
On startup some env variable will be used for initial configuration:
- BKJS_HOME - home directory where to cd and find files,
-homeconfig parameter overrides it - BKJS_RUNMODE - initial run mode,
-run-modeoverrides it - BKJS_CONFIG - config file to use instead of 'etc/config',
-configoverrides it - BKJS_PACKAGES - packags to use,
-import-packagesoverrieds it - BKJS_DB_POOL - default db pool,
-db-pooloverrides it - BKJS_DB_CONFIG - config db pool,
-db-configoverrides it - BKJS_ROLES - additonal roles to use for config,
-rolesoverrides it - BKJS_APP_NAME - default app name
- BKJS_APP_PACKAGE - default app package from preloaded packages
- BKJS_TAG - initial instance tag,
-instance-tagoverrides it, it may be also overridden by AWS instance tag - BKJS_LOG_OPTIONS - logger options,
-log-optionsoverrides it - BKJS_PORT - port for web server
- BKJS_WSPORT - port for web sockets