Denxi Guide
Here you learn what Denxi is, what it can do for you, and how to practice using it.
For all documentation, see Denxi Documentation.
1 Introduction
Denxi White Paper covers the thinking behind Denxi.
Denxi is a programming model for distributing data. It reduces the cost of producing package managers, storefronts, operating systems, and CI/CD systems. Denxi can work as a library, as a framework, or as a standalone application.
Denxi Reference covers hundreds of functions. This guide briefly introduces core concepts and directs you to example programs. Use them to understand Denxi Reference.
By doing this you’ll gain a few benefits.
Denxi practices zero-trust principles to avoid many problems. Denxi only performs side-effects that it can trace back to your explicit, informed consent.
Denxi can manage dependencies for projects written in any language, or your whole operating system.
If you don’t like how a software installation affects your system, you can override it.
If you don’t like Denxi itself, you can use it to create and distribute an alternative. It creates package managers like Racket creates languages.
(npm users) You’ll have more safety checks to protect your system.
(raco pkg users) You won’t mutate your Racket installation when installing software.
(PLaneT users) You can install multiple versions of a project without generating non-eq? bindings.
(Guix/Nix users) You get the benefits you expect on Windows, macOS, and GNU/Linux distributions out of the box.
2 Setup
After installing Denxi, you will have a denxi command available for your system.
First, make sure the following programs are available in your PATH.
SQLite 3.24.0+. Verify with sqlite3 -version
Racket 7.0+. Verify with racket -v
To build from source, clone or download Denxi from GitHub and run make in the source directory.
Next, run raco pkg install denxi. If this fails, then make sure you do not have a conflicting version installed.
The denxi command should now be available.
3 Package Definitions
A package definition is a program, and this one creates a familiar greeting in a text file.
"definition.rkt"
#lang denxi (input "hello.txt" (artifact (text-source "Hello, world!") #f #f)) (output "default" (keep-input "hello.txt"))
We define an input as a named source of data. You’ll later learn what the other terms mean, and how they can be adjusted to use the network, verify downloads, and even use your own notation for external resources.
We define an output as a named subprogram that turns inputs into files. We’ll install that output in the next section.
4 Launchers
This launcher program starts and controls Denxi.
"my-denxi.rkt"
#lang denxi/launcher (module+ main (launch-denxi!))
Denxi built-in launcher is called denxi, and it actually has the same implementation! The difference is that we control our launchers. Save the above code into my-denxi.rkt and give it the definition from the previous section.
$ racket my-denxi.rkt do ++install-abbreviated definition.rkt |
This command will give you first of many reasons for why it won’t work, because all launchers start with zero-trust. You must explicitly allow all relevant details for security. We won’t neglect security, but we’ll use this production-unsafe launcher until you can work with zero-trust.
"my-denxi.rkt"
#lang denxi/launcher (current-chfs (list snake-oil-chf)) (DENXI_TRUST_BAD_DIGEST #t) (module+ main (launch-denxi!))
This launcher has a low bar, so run the same do command. A symbolic link will appear. Compare the definition to output to start connecting some dots. To uninstall the output, delete the link and run the garbage collection command.
$ rm my-first-package && racket my-denxi.rkt gc |
Recovered 13 bytes |
To recap, launchers build software from package definitions and issue links to their outputs.
To be fair, this is a toy example, and toy examples are illustrative at best. The good news is that you are now equipped to review working examples. As the examples become more advanced, they incorporate more real-world information.
5 Practice
You installed Denxi, wrote a package definition, wrote a launcher, then used the launcher to (un)install something.
This guide leaves out a lot of detail to make one point: everything boils down to launchers and package definitions. Now that you know what both are, you can read built-in examples and write your own. Doing so will help you understand Denxi Reference.
The toy examples we covered in this guide are for context only. The built-in examples are more interesting. You will learn how to define a host’s OpenSSL instance as a cryptographic backend, resolve package conflicts, manage multiple Racket versions, and prevent two lexically identical structs from generating non-eq? bindings.
You may review the examples through the links above, but all of the examples have been shipped to you in Denxi’s source. Run this command to print the examples directory on your disk. Go to that directory and look for a README. The README picks up from immediately after this guide, and shows you a suggested reading order.
racket -e '(~a (collection-file-path "examples" "denxi"))' |
With enough practice you will write a custom launcher that is useful to others. You can distribute that custom launcher using denxi, which creates more confidence in both Denxi and your launcher.
Thank you for trying Denxi, and I hope it brings you good fortune. My name is Sage, and you can reach me through my website.