openradtool (ort
) is an
open source RAD tool generating front-end code
(TypeScript) and back-end code (SQL, C, Rust, Node.js) from a straightforward data model.
The system consists of a set of source generators and analytical tools, each accepting a ort(5) configuration that describes your data and how it is accessed, modified, created, deleted. It runs on OpenBSD, NetBSD, FreeBSD, Linux (glibc and musl), Mac OS X, Solaris (SunOS), and OmniOS (IllumOS). The generated sources run on the same. Development is on OpenBSD, which has the highest level of built-in security.
The tools manage or generate the following application components.
- Database SQL schema generation (and schema upgrade commands) for your SQLite database.
- Data Layer Node.js, C, and Rust back-end source code—API and implementation—for manipulating and exporting from the database. This must be driven by your program code.
- Presentation Layer Front-end TypeScript source code populating HTML5 trees with exported data. This must be driven by your front-end code.
- Internationalisation Translation files for front-end TypeScript labels.
- Access Controls Security and accountability: role audits for studying the data accessable by user roles.
See the GitHub repository for installation and issue tracking. openradtool is a BSD.lv project, née kwebapp.
ort tools are designed to be operated by make(1) or other build tool. During development, these tools continuously keep C sources, TypeScript, translations, and so on up to date from a single ort(5) file. These files are in turn compiled or bundled into your application.
1. validate configuration
% ort db.ort
Consider an example ort(5) configuration db.ort. 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 ort(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.
This validation is superfluous, as all other tools validate during parse.
2. generate back-end code
% ort-c-header -jv
db.ort > db.h
% ort-c-source -jv
-h db.h db.ort > db.c
% ort-nodejs
db.ort > db.node.ts
% ort-rust
db.ort > db.rust.rs
C, Rust, and Node.js back-ends are available. The Rust output is still somewhat experimental.
The Node.js backend currently lacks many of the security benefits of using the C API, such as privilege separation, but is the more widely-used of languages. The generated TypeScript code is built to work within npm applications. A full application example is available in ort-nodejs(1).
The C API files may be linked to sources (usually, but not necessarily) driving a kcgi(3) CGI script. Each function and structure in the header file is documented thoroughly. The source files are also documented, though more sparsely.
The Rust output is still experimental, but is able to interface with data models in a manner similar to the Node.js output. It does not yet have integrated documentation or validation.
3. generate and initialise database
% ort-sql db.ort > db.sql
% sqlite3 db.db < db.sql
Some object fields, such as the user
structure inside of the section, are
not part of the SQL schema, but required for creating the SQL queries during runtime.
For the most part, however, all ort(5) fields map into database
columns.
The SQL schema file is thoroughly documented. Use sqliteconvert or similar tool to browse the SQL documentation for any non-trivial application.
4. update database
% ort-sqldiff
db.old.ort db.ort >
db.update.sql
% sqlite3 db.db < db.update.sql
Database upgrades are a pain: ort-sqldiff(1) programmatically tracks differences in the database schema. This allows for continuous testing of database compatibility. It also generates the correct SQL commands for properly upgrading an existing database without fear of ordering or missing field attributes.
(Update scripts should, however, always be perused for correctness.)
5. generate typescript front-end
% ort-javascript
db.ort > db.ts
The last part of the toolchain is to handle the JSON-export output in the browser itself. The ort-javascript(1) tool will also generate 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 HTML DOM trees with data. All of this is documented using tsdoc notation. For example, consider the following:
1 <div id="foobar"> 2 User 3 <span class="user-email-text"></span>: 4 company 5 <span class="user-company-obj"> 6 <span class="company-name-text"></span>. 7 </span> 8 </div>
A TypeScript file may invoke
new ort.user(res).fill
,
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.
6. translate javascript labels
% ort-xliff
db.ort > db.fr.xml
% ort-xliff -j
db.ort db.fr.xml >
db.trans.ort
The ort-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 ort.foo.format()
method as a custom
callback.
These strings may be translated by using the ort-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 ort-javascript(1), for a full translation sequence.
7. audit role-based access
% ort-audit
audit-example.ort user
Arguably the most powerful feature of ort. Audit role-based access control access with ort-audit(1) and ort-audit-json(1): see the full availability of data and operations available to the role. Role compliance in ort is guaranteed by having separate jailed database and application processes.
In the example role-backed audit-example.ort with roles
user
and admin
, for example, these tools can fully audit for the
user
role as seen in the exemplar audit.html created with
ort-audit-json(1).
This visualisation breaks down access by structures (the foundational objects of ort(5)) and then grouped by operation.