7 releases
| 0.1.6 | Dec 28, 2024 |
|---|---|
| 0.1.5 | Aug 2, 2024 |
| 0.1.4 | Apr 17, 2024 |
| 0.1.3 | Mar 18, 2024 |
| 0.1.1 | Feb 25, 2024 |
#335 in Template engine
431 downloads per month
88KB
1.5K
SLoC
About
Code generation tool meant to reduce repetitive tasks in day-to-day operations.
Generate code or text documents based on pre-defined code templates and a database schema.
Currently supports only MySQL/MariaDB databases with InnoDB table storage engine.
Code templates are written in handlebars format and support rhai scripts.
Install
Run cargo install ctgen (if this project reached the public crate stage).
Or alternatively clone the repository and run cargo build --release and then
copy target/release/ctgen to a bin path of your choice.
Or just cargo install --path .
To see some hands-on examples, check ctgen-samples.
Usage
There are 3 modes of operation (commands).
- The
initcommand is for creating a new configuration profile project. - The
configcommand is for managing existing configuration profiles. - The
runcommand is for running a generation task inside another project.
Disclaimer
Under no circumstances should you ever run generation tasks based on templates you are not very well familiar with! This poses a great security threat!
When using ctgen with templates that you did not create yourself you should read and study the code carefully before running any tasks with
that template! Ctgen can and does modify your local filesystem and has the capability to execute additional shell commands with or without user input!
Under no circumstances should you ever run ctgen as root or any other privileged account! As of time of writing ctgen does NOT have any mechanisms to
predict or prevent any potentially negative outcomes or dangerous operations. Use discretion and study the templates you use before attempting to run any tasks!
Create profile
To create your first configuration profile go somewhere in your filesystem and run ctgen init.
Optionally you can create the profile project in a new directory by running ctgen init <dirname>.
To avoid being prompted for a profile name, use the --name option: ctgen init --name backend backend_templates.
This will create a new configuration profile project and register it using the same name.
The default project layout is:
- Profile config file:
Ctgen.toml. Describes the profile behavior, templates and build targets. - Templates directory:
assets/templates. Contains allhandlebarstemplates with.hbsextension. The main part of the filename is the template name. - Scripts directory:
assets/scripts. Contains allrhaiscripts with.rhaiextension. The main part of the filename is used to register the script as handlebars helper.
Manage profiles
- To add an existing configuration profile to the registry, run
ctgen config add [path to Ctgen.toml]. If you are in the profile directory, you can just runctgen config add. Optionally you can pass--defaultto override your default profile or--name my_nameto override the profile name. Otherwise the name of the profile is used in the registry. - To list registered profiles, run
ctgen config ls. If an item in the list is blinking in red, that means that the profile is broken and the config file does not exist. - To remove a profile from the registry, run
ctgen config rm profile_name.
Run tasks
Assuming you have a valid configuration profile setup already (see above), to run a generation task you need to:
- Go inside your project:
cd my_awesome_project - Run
ctgen run - Answer prompts
- ???
- PROFIT
Check ctgen help run for extra options like:
- Choosing a profile other than the
defaultusing--profile=flutter - Overriding the profile setting for
.envfile, environment variable name, DSN string or target path - Overriding the profile prompts with the
--promptoption, for example--prompt "dummy=1". Prompts answered with command-line params will be skipped during the run.
Example runs:
Let's imagine you are generating flutter code for your mobile project. Your profile is called mobile. It doesn't know where your database is so you enter it manually. You chose to generate code for table clients and know that the profile will ask you whether you want to generate a password reset flow and also add login with Google.
Run: ctgen run --profile=mobile --dsn="mysql://[email protected]:3306/project_db" --prompt "password_reset=1" --prompt "google_auth=1" clients
Profile TOML Schema
The Ctgen.toml file describes the profile behavior and follows this set of rules:
- The first section in the file is called
profile, this section holds these fields:
- field
name: the default profile name - field
env-file: the name of the env file to look for when trying to initialize context, typically.env - field
env-var: the name of the env variable to look for in the.envfile, for exampleDATABASE_CONNECTION; the value of the variable is expected to be a valid DSN - field
dsn: ifenv-fileandenv-varare left empty, the profile could have a hardcoded database DSN instead; otherwise this field could be omitted or left blank - field
target-dir: this is the directory that should hold all build targets. It is relative to current working dir when running a generation task (ctgen run). CWD is used if left blank - field
templates-dir: this is the directory that holds all handlebars templates. It is relative to the profile containing directory. - field
scripts-dir: this is the directory that holds all rhai scripts. It is relative to the profile containing directory. - field
prompts: this is an array of strings. Every string in the array must be a valid prompt ID of a prompt defined in thepromptsections that follow. - field
targets: this is an array of strings. Every string in the array must be a valid target ID of a target defined in thetargetsections that follow.
- Any number of
promptsections after theprofilesection declare profile prompts by assigning a prompt ID as a dot-nested value to the section name, for example[prompt.dummy]. A prompt can have the following fields (properties):
- field
condition: optional, containing an inline handlebars template that should render1to trigger this prompt - field
prompt: containing plain text or an inline handlebars template that is being rendered to the user as prompt text - field
options: optional, containing either an array or table (object) of available options (for select and multiselect prompts), or string (for input prompts), or an inline handlebars template that renders a comma-separated list of options (for select and multi-select prompts) - field
multiple: optional, boolean flag indicating a multi-select; default isfalse - field
ordered: optional, boolean flag indicating that order matters for multi-select values; default isfalse - field
required: optional, boolean flag indicating that empty values will not be accepted; default isfalse
- Any number of
targetsections after thepromptsections declare profile build targets by assigning a target ID as a dot-nested value to the section name, for example[target.dummy]. A target can have the following fields (properties):
- field
condition: optional, containing an inline handlebars template that should render1to trigger this target to be rendered - field
template: string containing a template name, which should exist as a file with.hbsextension in thetemplates-dirdirectory. For exampledummy, orbackend/dummy. - field
target: string containing an inline handlebars template that should render to a file path inside thetarget-dir. Missing path elements will be created. Could also be plain text path likemain.rs. - field
formatter: optional, containing an inline handlebars template that should render a valid shell command to execute after the target has been rendered and written to disk. Could also be plain text shell command if no context conditional parameters are necessary. NOTE: The only available variable to render is{{target}}.
Notes
- If a rhai script file is named
op.rhaiinsideassets/scripts, then you will have{{op}}helper available in your handlebars templates - Rhai comes with the following additional packages enabled: rhai-chrono, rhai-sci, rhai-fs, rhai-url.
- If your template file is named
backend.hbsinsideassets/templates, to define a target that uses that template, use the namebackendas template name - Available helpers (other than handlebars' defaults) are:
{{inflect}}handlebars-inflector,{{concat}}handlebars-concat,{{datetime}}handlebars-chrono and{{{json}}}(takes the first argument and turns it into a JSON) - The context available during rendering handlebars templates looks roughly like:
{
"database": {
"name": "db_name",
"tables": [],
"constraints": [],
"metadata": {}
},
"table_name": "selected_table_name",
"table": {
"name": "selected_table_name",
"primary_key": [],
"columns": [],
"indexes": [],
"metadata": {}
},
"constraints_local": [],
"constraints_foreign": [],
"prompts": {
"dummy": "1"
},
"timestamp": "2024-03-18T21:35:09.750752900+00:00",
"ctgen_ver": "0.1.2"
}
To dump your own context for debugging purposes use {{{json this}}} in your template.
Acknowledgements
This tool relies heavily on handlebars-rust and rhai crates. ❤️
TODO
- improve error handling
- improve logging
- improve
database-reflection(add more adapters) - improve
liblayout and exports and isolateclijunk better - more data sources, different context structs and context builders
- add dump/load context option to repeat runs
- more handlebars helpers
- maybe template updates by target reverse-engineering? based on diff?
- maybe fs watch to re-run task when templates change
- comments and documentation
- init produces crappy prompt options because of toml and serde circle of hell
Dependencies
~43–61MB
~783K SLoC