Migrate
Frizzante comes with a default sqlite database setup which you can initialize and migrate through Go and Sql code.

Create Migration Files
Migration files usually live under migrate/migrations .

You can either create these files manually, or use frizzante generate migration which will create a migration file using the local date, time and timezone.



Each migration file has a -- migrate: up and a -- migrate: down sections, which are executed respectively when a migration runs forwards and backwards.
-- migration: down
drop table if exists sessions;
drop table if exists todos;

-- migration: up
create table if not exists sessions(
id varchar(36) primary key,
created_at datetime not null,
updated_at datetime not null,
roles varchar(256) not null default 'user',
user_id varchar(256) not null default 'guest',
error text not null default ''
);
create table if not exists todos(
    id varchar(36) primary key,
    session_id varchar(36) not null,
    description varchar(256) not null default '',
    checked int not null default 0,
    foreign key (session_id) references sessions(id)
);
Note
The order in which these sections are defined is irrelevant.

Create Migrate Program
You can automate initialization and migration of your database by defining a ./migrate program at the root of your project.
package main

import (
    "database/sql"
    "embed"
    "log"
    "main/lib/databases"
)

//go:embed migrations
var efs embed.FS

func main() {
    // no need to close database connection,
    // this program runs once and dies immediately
    var err error
    var database *sql.DB
    if database, _, err = databases.Connect(); err != nil {
        log.Fatal(err)
    }
    if err = databases.Migrate(databases.MigrateOptions{
        Efs:      efs,
        Database: database,
        Offset:   "first",
        Target:   "last",
    }); err != nil {
        log.Fatal(err)
    }
}
Note
Function databases.Connect() will initialize a source.sqlite database file if it doesn't already exist.

Future database solutions will probably not have this feature, this is something that can generally be done only with sqlite.
Note
Note that this program embeds the migration files.
This will run all migrations from the first one to the last one.

You can also specify a range by indicating the migration names.
package main

import (
    "database/sql"
    "embed"
    "log"
    "main/lib/databases"
)

//go:embed migrations
var efs embed.FS

func main() {
    // no need to close database connection,
    // this program runs once and dies immediately
    var err error
    var database *sql.DB
    if database, _, err = databases.Connect(); err != nil {
        log.Fatal(err)
    }
    if err = databases.Migrate(databases.MigrateOptions{
        Efs:      efs,
        Database: database,
        Offset:   "2025_01_01T09_16_00+02_00",
        Target:   "2026_07_17T09_54_35+02_00",
    }); err != nil {
        log.Fatal(err)
    }
}
Caution
File extension and parent directory path must be excluded.

This means that the following
  • 2025_01_01T09_16_00+02_00.sql
  • migrate/migrations/2025_01_01T09_16_00+02_00
  • migrate/migrations/2025_01_01T09_16_00+02_00.sql
are not valid migration names.


Execute Migration Files
Run the program
frizzante migrate
# or go run ./migrate
Note
Since the migrate program from above embeds the migration files, it's a portable binary that can single handedly create and migrate your database.