dexa v0.3.1
dexa
create awesome project templates turbocharged with generators/scaffolders!
dexa is a CLI tool that allows developers and teams to capture their preferred tech stacks as a project template and a set of code generators.
Each of these stacks can be distributed as a git repository. Create them in a publicly available service such as Github to encourage usage and sharing across the wider community. But you are also free to use dexa with private repositories.
Installation
Requires Node.js 14 or later!
You can install dexa as a global tool, making the dx executable available in your shell:
# install
npm install -g dexa
# verify
dx --version
dx stack listAlternatively, you can use npx to run dexa commands without installing as a global tool:
npx dexa --version
npx dexa stack listGetting started
What is a stack
Dexa allows users to create and use stacks, where each stack is a project template combined with code generators. To better understand what a stack is, let's use an existing stack in our test samples.
The hello-world-stack creates a hello world Node.js console application. To install it, use the dx stack add command, pointing to the git repo where the stack is located
dx stack add hello-world https://github.com/kaizendorks/dexa/test/stack-fixtures/hello-world-stackLet's now create a project using the stack. For this, you use the dx init command and the name you gave to the stack when installed.
dx init hello-world my-first-projectYou can see all the installed stacks with
dx init --help
Once finished, it will have created a new folder named my-first-project, which contains the project created by the stack.
Let's run the project to verify it indeed created a working project:
cd ./my-first-project
node index.js
Hello World!Awesome, looks like the stack successfully creates hello world console applications.
Let's now explore the code generators available with this stack. Any stack can define 2 flavours of generators:
- features, which are added to your project with the
dx addcommand. These are meant to be optional features that are optionally added once to each project - scaffolders, which encapsulate the boilerplate for elementes of which you can add many to your project
Each stack is defined with a particular domain in mind, so the generators implemented by each stack will be based on that context. For example, a stack for creating web applications with Vue.js and Fastify migh provide features such as
unit-test,i18norgraphQL, and scaffolders such aspage,componentorrest-api.
Let's see them in action. Begin by adding the unit-test feature:
dx add unit-testThis has added a very simple unit test to our project. For completeness, let's verify it works
node ./test/greeter.test.jsGreat, now let's scaffold a new greeter so the application says more than "Hello World"
dx generate greeter tutorialAnd verify it generated working code
node index.js
Hello World!
Hello World from the greeter tutorial!Note the parameter
tutorialprovided in the command has been used inside the template of thegreeterscaffolder.
Yay, the stack can generate code! You can cleanup with:
cd ../
rm -rf ./my-first-project
dx stack delete hello-worldHow to create a stack
The sample hello world stack we have seen above is great to get a sense on how dexa works. But chances are that you are not interested in creating more Node.js hello world applications.
The good news are that you can create your own stacks, and define whatever project templates and generators you want! Let's see how to create one.
A stack just needs to follow a certain structure organising the templates:
/init
the project template
/add
each feature has a subfolder with its template
/generate
each scaffolder has a subfolder with its templateThis is the basic structure. See the reference guide for more advanced usages
To make things even simpler, dexa comes with a predefined stack named dexa-stack that can be used to create your own stacks:
dx init dexa-stack my-stackIf you inspect the generated files, it looks like this:
my-stack
├── README.md
├── add
│ └── README.md
├── generate
│ └── README.md
└── init
├── sample-copy.md
└── sample-template.md.hbsThose various README.md files contain valuable information on how a stack works and how you can update the project template as well as creating your own code generators.
Can we now test our stack? Yes you can test it directly from its local folder, without publishing it to git.
As per the development instructions in the generated README.md file, install the stack by running in its root folder:
dx stack add my-stack $(pwd)Now on a separated terminal and folder, try generating a project using your stack:
dx init my-stack test-projectIf you inspect the generated project, you will notice the stack used the template defined inside its ./init folder.
test-project
├── sample-copy.md
└── sample-template.mdTake a moment to inspect the files inside the ./init template folder. Notice how the .hbs extension makes the file a dynamic template with placeholders. If you want to regenerate the project after modifying the files, use the same init command with the override flag (--override or -o):
dx init my-stack test-project --overrideHow to add code generators to a stack
Let's now see how to define code generators. Each generator is just a folder containing a template similar to the ./init template. The template folder for a feature generator lives inside the ./add folder, while the template folder for a scaffolder lives inside the ./generate folder.
You can manually create these folders, or use the commands provided by the dexa-stack stack. For example, lets add a feature template using:
dx generate feature my-featureYour stack should now like follows:
my-stack
├── README.md
├── add
│ ├── README.md
│ └── my-feature
│ └── README.md
├── generate
│ └── README.md
└── init
├── sample-copy.md
└── sample-template.md.hbsTake a moment to create some files and subfolder inside the ./add/my-feature folder.
Once you are ready, navigate to the folder where you created the test-project. Let's try your feature generator:
dx add my-featureAwesome! You have created your first feature generator.
Try the same with the scaffolder. Back at the root of the stack definition, run (please bear with me):
dx generate generator my-generatorNotice there is a new folder ./generate/my-generator which contains the template for the new generator.
my-stack
├── README.md
├── add
│ ├── README.md
│ └── my-feature
│ └── README.md
├── generate
│ ├── README.md
│ └── my-generator
│ └── README.md
└── init
├── sample-copy.md
└── sample-template.md.hbsAs before, take another moment to update/create files inside the template folder ./generate/my-generator.
When a user invokes a
dx generatecommand, in addition to the name of the generator, there is a second parameter which is the name of that particular instance of the generator. For example, assume a generator that creates new REST APIs. You might rundx generate rest-api customeranddx generate rest-api profileto create the customer and profile APIs respectively The__name__part of any of the template file/folder names will be replaced withcustomerandprofilerespectively. Inside any.hbsfiles of the template, you can similarly use the placeholder{{ userOptions.name }}.
Once you are ready, navigate to the test-project folder and give it a go:
dx generate my-generator fooGreat! And this finishes the basics on how to create your own stacks.
Check the reference section for more advanced scenarios like adding extra input parameters or defining functions to run when invoking the code generators.
The only remaining (optional) step is to publish your stack so others can use it. Simply publish the stack to a git repo, allowing anyone with access to that repo to install it using a command like dx stack add https://github.com/username/reponame.
Reference
Installing stacks
TBC
Using stacks
TBC
Creating stacks
TBC
API
TBC
Examples
See test stacks
FAQ
How can dexa help you?
Imagine you work in a team that frequently creates web applications with Vue3 and fastify. You probably have an opinionated way of setting these up, so you can capture your project template in a repo. This way you can dx stack add your repo as a stack in dexa, so you can later create projects with dx init my-vue-fastify-template.
You might sometimes use docker, you can then expand your stack repo with another template that adds docker and compose files so you can dx add docker. In some projects you might use postgre while in others you might use mongoDB, you can then capture 2 further templates that allow you to dx add postgre or dx add mongo to your project.
You will likely find yourself regularly creating elements like pages or apis to your web application. Dexa can also help you by expanding your stack with template generators so you can dx generate page new-page or dx generate api new-api!
This means you can create your dexa stack as a repo with the following structure:
/
|__ /init
| |__ fileA // can be any extension (and copied as is) or `.hbs` (with replacements and helpers)
| |__ /some/folder/fileB
| |__ ... more template files and folders
|__ /add
| |__ /docker
| | |__ ...
| |__ /postgre
| | |__ ...
| |__ /mongo
| |__ ...
|__ /generate
| |__ /api
| | |__ ...
| |__ /page
| |__ ...
|__ dexa.js // optional file, defines additional metadata/options/arguments for each templateOnce the stack is defined in a repo:
- Install the stack by pointing to the repo, as in
dx stack add git@github.com:DaniJG/my-stack.git - Create a new project using the name of the stack, as in
dx init my-stack - Add stack features to a generated project by running
dx addcommands within the project root folder, as indx add docker - Generate code by running
dx generatecommands within the project root folder, as indx generate page my-new-page
Is it limited to JavaScript or web projects?
Absolutely not! While dexa is written in JavaScript, you can define stack templates for any language. In a nutshell, dexa will render the templates you define, what those templates contain is entirely up to you.
For example, you could create a terraform stack so you can dx init terraform. This stack could define features such as S3 or azure blob remote storage so you can dx add remote-aws-s3 or dx add remote-azure-blob. In a similar fashion, you could then create generators for any common terraform modules you typically use, allowing you to dx generate s3-bucket or dx generate aws-kubernetes.
Can I use a project template without generators?
You can define a stack by pointing to a repo that contains just a project template like this vue-vite-tailwind starter
dx stack add vue-vite https://github.com/web2033/vite-vue3-tailwind-starterYou will be able to create new projects using that template as in dx init vue-vite, but here will be no dx add or dx generate commands available for those generated projects.
This is similar to using degit, except you can keep track of these templates as dexa stacks.
Changelog and Roadmap
See CHANGELOG.md
License
MIT © by its authors
See LICENSE.md