This repository contains the full backend for the Stari Kolomoni open fantasy translation project.
TODO :=)
This section describes how to set up for development.
See 1. Deployment
for production instructions.
Before proceeding, verify that you have the following:
Rust 1.65
or newer - install with rustupPostgreSQL 15.3
or newer - install or extract portable toPATH
.If on Windows, Powershell helper scripts are available in
scripts/database
. To simplify things you can also simply download a portable PostgreSQL archive instead of installing it. You can then, instead of adding it toPATH
, extract itspgsql
directory toscripts/database
(i.e. so that thescripts/database/pgsql/bin
directory exists).SeaORM CLI
, installed withcargo install sea-orm-cli
. This will be used to manage database migrations.
Important: use nightly rustfmt.
Use nightly rustfmt
(cargo +nighly fmt
or
equivalent IDE support) for formatting your
Rust code in this repository. Current rules can be seen in rustfmt.toml
- you're welcome to adapt the rules to better
fit the codebase as the repository evolves.
Setup for Visual Studio Code (with rust-analyzer
)
This configuration requires
rust-analyzer
to be installed and enabled in Visual Studio Code.
If you're using Visual Studio Code, you can use something akin to the configuration below to
enable clippy
and rustfmt
as described above. Add these entries into your project-local .vscode/settings.json
,
creating the file if necessary:
{
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
},
"rust-analyzer.check.overrideCommand": [
"cargo",
"clippy",
"--workspace",
"--message-format=json",
"--all-targets",
],
"rust-analyzer.rustfmt.extraArgs": [
"+nightly"
],
"rust-analyzer.cargo.features": "all"
}
Alongside rust-analyzer
and this configuration, we would like to suggest the following extensions:
- (highly recommended) EditorConfig,
- (good-to-have) Even Better TOML, and
- (optional; highlights comments) Better Comments.
For Better Comments, the following configuration might be of use — add this to .vscode/settings.json
after installing the extension:
{
// ...
"better-comments.tags": [
{
"tag": "todo",
"color": "#77BAF5",
"strikethrough": false,
"underline": false,
"backgroundColor": "transparent",
"bold": false,
"italic": false
},
{
"tag": "debugonly",
"color": "#c4b1e5",
"strikethrough": false,
"underline": false,
"backgroundColor": "transparent",
"bold": false,
"italic": false
},
{
"tag": "deprecated",
"color": "#F5A867",
"strikethrough": false,
"underline": false,
"backgroundColor": "transparent",
"bold": false,
"italic": false
},
{
"tag": "fixme",
"color": "#f26344",
"strikethrough": false,
"underline": false,
"backgroundColor": "transparent",
"bold": false,
"italic": false
},
]
// ...
}
First off, initialize the PostgreSQL database.
If you're on Windows, you can use the scripts/database/init-database.ps1
and scripts/database/run-database.ps1
scripts for easy setup and running.
Note that this script should only be used for development as it uses --auth=trust
.
The generated user is kolomon
(password kolomon
) and the database name is kolomondb
.
The database will run on 127.0.0.1
on default port 5432
.
Then, copy data/configuration.TEMPLATE.toml
to data/configuration.toml
and
fill out the configuration fields (see comments in the template for explanations).
Build the project by running cargo build
.
This will be a fresh build, so it might take a few minutes (around 2 minutes on a hard drive with a 16-core CPU at 3.6 GHz).
Subsequent builds will be much faster.
To start the backend server, execute cargo run
(or run the binary in ./target/debug
).
Migrations are managed by SeaORM and are applied onto the database on startup (if needed).
The process of modifying the database schema or creating new tables is described below. SeaORM calls this order "schema-first", and we tend to follow this recommendation.
It is important to note that here, unlike in frameworks like Django, we must write our migrations by hand (create a table, add fields, add indexes, ...). This is all written in Rust code to be as database-agnostic as possible. See existing migrations as examples and additional guidance in
A.1 Create a migration
.
First off, create an .env
file in the root of the cloned repository and set the DATABASE_URL
environment variable.
The following represents the correct username, password and database name for the development setup created with ./scripts/database/init-database.ps1
:
DATABASE_URL=postgres://kolomon:kolomon@localhost/kolomondb
Then choose an appropriate name for your migration, e.g. create_users_table
. You can then create a new migration by running:
sea-orm-cli migrate generate --universal-time --migration-dir ./kolomoni_migrations create_users_table
This will create a new file in the ./kolomoni_migrations/src
directory.
Remove the todo!()
calls and redundant comments.
Then write your own up
and down
implementation for your new migration.
Keep in mind that the newly-added migration will be applied last, after all existing migrations
(see migrations/src/lib.rs
for the order - don't modify it unless you know what you're doing).
As for a guide on writing migrations: see existing ones for some examples, but you can learn more about SeaORM migrations in SeaORM - Writing Migration.
The API documentation for the SchemaManager
parameter you're provided in the up
and down
methods
is available on docs.rs - sea_orm_migration::manager::SchemaManager.
Un-applied migrations will be performed when the backend starts, but you may perform the migration manually if you like by running:
sea-orm-cli migrate up --database-url=postgres://username:password@host:port/database_name --migration-dir migrationsYou can also check which migrations have already been applied by running:
sea-orm-cli migrate status --database-url=postgres://username:password@host:port/database_name --migration-dir migrations
The following takes place in the
kolomoni_database
crate.
The entities
module is supposed to be auto-generated by SeaORM and as such you should not modify it.
If you added a migration and wish to update the entities to the current schema, you must first apply the migrations (see above). Afterwards, run:
sea-orm-cli generate entity --output-dir=./kolomoni_database/src/entities --expanded-format
Again: do not modify this auto-generated code! Your changes will be overwritten the next time someone runs this command.
The following takes place in the
kolomoni_database
crate.
While not enforced by SeaORM, we want to avoid non-database code (especially actix routes) touching the defined entities in database::entities
directly.
Instead of querying and updating those entities manually, here is a pattern for accessing and modifying anything in the database (names are examples, adapt to the relevant entity):
crate::query::user_permission::UserPermissionQuery
is the struct that has public async methods that allow the rest of the application to query data (find by id, name, ...), but not to modify it. A single query struct should generally operate only on one entity.crate::mutation::user_permission::UserPermissionMutation
is the struct that has public async methods that allow the rest of the application to modify the data of the given entity (or related entities, up to you).
Query and mutation structs are then re-exported in src/mutation.rs
and src/query.rs
to eliminate unnecesarry nesting.
As a general rule, it probably makes sense to write query and mutation methods as we grow the application to need them, and not every operation up front after defining the entity.
As for the SeaORM documentation related to fetching and updating database data, the SeaORM - Basic CRUD chapter might be of much help.
We've introduced a few new types to easily ?
-return common Result
errors,
see documentation for api::v1::errors::APIError
for more information.