kwebapp is an open source UNIX RAD tool generating front-end code (JavaScript, TypeScript) and back-end code (SQL, C) for your web application, leaving you to develop your middle-tier business and presentation logic. It's designed for small to medium deployments.

The system consists of a set of source generators, each accepting a single kwebapp(5) configuration file that describes your data and how it is accessed, modified, created, deleted.

Outputs generated by a kwebapp(5) configuration.

Each source generator is available as a standalone program with a thorough manpage. All available source generators are as follows.

Database generation: SQL schema (and schema upgrade commands) for your SQLite database.
kwebapp-sql(1), kwebapp-sqldiff(1)
Back-end C source code—API and implementation—for manipulating and exporting from the database. This must be driven by your program code.
kwebapp-c-source(1), kwebapp-c-header(1)
Front-end JavaScript or TypeScript source code populating HTML5 trees with exported data. This must be driven by your front-end code.
kwebapp-javascript(1)
Internationalisation: translation files for front-end JavaScript labels.
kwebapp-xliff(1)
Security and accountability: role audits for studying the data accessable by user roles.
kwebapp-audit(1), kwebapp-audit-json(1), kwebapp-audit-gv(1)

Seen from the flow of information to and from the browser, kwebapp (or your build process) manages all of the data in grey. The only parts requiring authorship are in blue: the business logic (your code), the presentational material (your presentation—likely glue Java/TypeScript, HTML5, and CSS), and your kwebapp(5) configuration itself. For simplicity, this assumes an un-translated data store.

These programs have no run-time dependencies; however, the generated C files use ksql(3) as a wrapper for the underlying SQLite database, and often require kcgi(3) when generating validators and output formatters. You will need the newest version of the dependency libraries. Sources output by kwebapp use features from the newest releases: all of these tools are being built in tandem. Generated JavaScript and TypeScript files are vanilla and have no framework dependencies.

See the GitHub repository for issue tracking and versioning. To use kwebapp, just unpack, run ./configure, make, then make install. kwebapp is a BSD.lv project.

For previous releases, see the version archive.

parse and validate configuration

% kwebapp db.txt

Consider an example kwebapp(5) configuration db.txt. It defines three data objects—a user, company, and session—with relations between the three. Each session refers to a user by the userid field. Then each user refers to a company by its cid.

The configuration is fairly readable: structures and fields, with field types and limits (string length or numeric value) and other options (nullity, whether a row identifier, etc.). Beyond the data itself, each objects defines search, update, and deletion functions. (A normal application would have more, but for brevity…)

The kwebapp(1) utility parses and validates the configuration. To do something with this configuration, we need to have code. Most applications start by creating an API from the data configuration as described in the next section. Note: this validation is superfluous, as all other compilation processes will do the same.

generate back-end code

% kwebapp-c-header -jv db.txt > db.h
% kwebapp-c-source -jv -h db.h db.txt > db.c

This generates source and header files to be linked to sources (usually) driving a kcgi(3) CGI script. Each function and structure in the header file is documented thoroughly. The source files are also documented (more sparsely) to guide developers in reading through the implementation.

The C source file is generated for the target architecture, so it's not guaranteed to be portable between operating systems.

You can break apart C headers and sources into the database routines, JSON export, validation, and so on. For smaller applications, it's generally easiest to have them in one. I break apart the routines when I have several applications, e.g., a CGI script and a cron(8) job for period e-mails. This allows the non-CGI applications not to link to CGI bits.

compile back-end code

% cc -static -o test main.c db.c -lksql -lsqlite3 -lpthread -lkcgijson -lkcgi -lz

The -static is for simplicity when running CGI scripts in a file-system jail. This is the default operation on OpenBSD web servers (see httpd(8), which I use as a reference web server).

The required libraries are -lksql for the database routines, -lkcgijson for the JSON output, and -lkcgi for the input validation (and a library dependency for -lkcgijson). The other libraries are dependencies on the former (-lsqlite3 and -lpthread) and latter (-lz). Obviously, I assume these are in the standard library path, though the third-party libraries will probably be in -L/usr/local/lib, with headers in -I/usr/local/include.

On some machines, you may additionally need -lcrypt (for password hashing) and -lm (for -lkcgijson).

generate and initialise database

% kwebapp-sql db.txt > db.sql
% sqlite3 db.db < db.sql

That some object fields, like the user structure inside of the section, are not part of the SQL. Rather, they are generated within db.c using the foreign keys. But for the most part, all structure items map into database columns.

The SQL schema file is thoroughly documented. I suggest using sqliteconvert if you'd like to browse the SQL documentation for any non-trivial application.

update database

% kwebapp-sqldiff db.old.txt db.txt > db.update.sql
% sqlite3 db.db < db.update.sql

A feature I use a lot in kwebapp is to track differences in the database schema by using kwebapp-sqldiff(1). This allows me to double-check that upgrades to my database won't be incompatible. It also generates the correct invocations without having me fat-finger mistakes in the upgraded database.

Update scripts should always be perused for correctness. They currently don't handle default values, so columns not accepting null will not pass through the database application.

generate javascript front-end

% kwebapp-javascript db.txt > db.js
% kwebapp-javascript -t db.txt > db.ts

The last part of the toolchain is to handle the JSON-export output in the browser itself. The kwebapp-javascript(1) tool will also generate JavaScript or TypeScript files to assist in filling in data for your front-end web application code.

Both are the same, and provide an easy interface for replacing elements (noted by class names) in your HTML DOM tree with data. All of this is documented using jsdoc notation. For example, consider the following:

    1 <div id="foobar">
    2   User <span class="user-email-text"></span>: company 
    3   <span class="user-company-obj">
    4     <span class="company-name-text"></span>.
    5   </span>
    6 </div>

A JavaScript file may invoke new kwebapp.user(res).fill(document.getElementById('foobar')), where res is the JSON object parsed from an AJAX call to the CGI script. This will recursively replace text (classes ending with -text), fill in input values, and allow for extensive customisation.

translate javascript labels

% kwebapp-xliff db.txt > db.fr.xml
% kwebapp-xliff -j db.txt db.fr.xml > db.trans.txt

The kwebapp-javascript(1) tool is capable of filling in labels of exported enumeration and bitfield values. For example, if an exported field is of the enum foo type, and the enumeration's items have jslabel tags, integral enumeration values can be programmatically converted to the labels by invoking the kwebapp.foo.format() method as a custom callback.

These strings may be translated by using the kwebapp-xliff(1) utility, which extracts translatable strings into the industry-standard XLIFF 1.2 format. The translation files may then be merged back into the configuration file, with the output piped into kwebapp-javascript(1), for a full translation sequence.

audit role-based access

% kwebapp-audit audit-example.txt user

We can audit role-based access control access with kwebapp-audit(1), kwebapp-audit-json(1), and kwebapp-audit-gv(1). By passing a role defined in the configuration to kwebapp-audit(1), we're able to see the full availability of data and operations available to the role.

In the example role-backed audit-example.txt with roles user and admin, for example, we can fully audit for the user role as seen in the exemplar audit.html. We create with kwebapp-audit-json(1). This visualisation breaks down access by structures (the foundational objects of kwebapp(5)) and then grouped by operation.