mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 14:06:08 +00:00
128 lines
4.7 KiB
Zig
128 lines
4.7 KiB
Zig
const std = @import("std");
|
|
|
|
const build_options = @import("build_options");
|
|
|
|
const jetquery = @import("jetquery");
|
|
const jetzig = @import("jetzig");
|
|
const Migrate = @import("jetquery_migrate").Migrate;
|
|
const MigrateSchema = @import("jetquery_migrate").MigrateSchema;
|
|
const Schema = @import("Schema");
|
|
|
|
const confirm_drop_env = "JETZIG_DROP_PRODUCTION_DATABASE";
|
|
const production_drop_failure_message = "To drop a production database, " ++
|
|
"set `" ++ confirm_drop_env ++ "={s}`. Exiting.";
|
|
|
|
const environment = jetzig.build_options.environment;
|
|
const config = @field(jetquery.config.database, @tagName(environment));
|
|
const Action = enum { migrate, rollback, create, drop, schema };
|
|
|
|
pub fn main() !void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer std.debug.assert(gpa.deinit() == .ok);
|
|
|
|
const gpa_allocator = gpa.allocator();
|
|
var arena = std.heap.ArenaAllocator.init(gpa_allocator);
|
|
defer arena.deinit();
|
|
|
|
const allocator = arena.allocator();
|
|
|
|
const args = try std.process.argsAlloc(allocator);
|
|
|
|
if (args.len < 2) return error.JetzigMissingDatabaseArgument;
|
|
|
|
const map = std.StaticStringMap(Action).initComptime(.{
|
|
.{ "migrate", .migrate },
|
|
.{ "rollback", .rollback },
|
|
.{ "create", .create },
|
|
.{ "drop", .drop },
|
|
.{ "schema", .schema },
|
|
});
|
|
const action = map.get(args[1]) orelse return error.JetzigUnrecognizedDatabaseArgument;
|
|
|
|
switch (action) {
|
|
.migrate => {
|
|
var repo = try migrationsRepo(action, allocator);
|
|
defer repo.deinit();
|
|
try Migrate(config.adapter).init(&repo).migrate();
|
|
},
|
|
.rollback => {
|
|
var repo = try migrationsRepo(action, allocator);
|
|
defer repo.deinit();
|
|
try Migrate(config.adapter).init(&repo).rollback();
|
|
},
|
|
.create => {
|
|
var repo = try migrationsRepo(action, allocator);
|
|
defer repo.deinit();
|
|
try repo.createDatabase(config.database, .{});
|
|
},
|
|
.drop => {
|
|
if (environment == .production) {
|
|
const confirm = std.process.getEnvVarOwned(allocator, confirm_drop_env) catch |err| {
|
|
switch (err) {
|
|
error.EnvironmentVariableNotFound => {
|
|
std.log.err(production_drop_failure_message, .{config.database});
|
|
std.process.exit(1);
|
|
},
|
|
else => return err,
|
|
}
|
|
};
|
|
if (std.mem.eql(u8, confirm, config.database)) {
|
|
var repo = try migrationsRepo(action, allocator);
|
|
defer repo.deinit();
|
|
try repo.dropDatabase(config.database, .{});
|
|
} else {
|
|
std.log.err(production_drop_failure_message, .{config.database});
|
|
std.process.exit(1);
|
|
}
|
|
} else {
|
|
var repo = try migrationsRepo(action, allocator);
|
|
defer repo.deinit();
|
|
try repo.dropDatabase(config.database, .{});
|
|
}
|
|
},
|
|
.schema => {
|
|
var cwd = try jetzig.util.detectJetzigProjectDir();
|
|
defer cwd.close();
|
|
|
|
const Repo = jetquery.Repo(config.adapter, Schema);
|
|
var repo = try Repo.loadConfig(
|
|
allocator,
|
|
std.enums.nameCast(jetquery.Environment, environment),
|
|
.{ .context = .migration },
|
|
);
|
|
const reflect = @import("jetquery_reflect").Reflect(config.adapter, Schema).init(
|
|
allocator,
|
|
&repo,
|
|
.{
|
|
.import_jetquery =
|
|
\\@import("jetzig").jetquery
|
|
,
|
|
},
|
|
);
|
|
const schema = try reflect.generateSchema();
|
|
const path = try cwd.realpathAlloc(
|
|
allocator,
|
|
try std.fs.path.join(allocator, &.{ "src", "app", "database", "Schema.zig" }),
|
|
);
|
|
try jetzig.util.createFile(path, schema);
|
|
std.log.info("Database schema written to `{s}`.", .{path});
|
|
},
|
|
}
|
|
}
|
|
|
|
const MigrationsRepo = jetquery.Repo(config.adapter, MigrateSchema);
|
|
fn migrationsRepo(action: Action, allocator: std.mem.Allocator) !MigrationsRepo {
|
|
return try MigrationsRepo.loadConfig(
|
|
allocator,
|
|
std.enums.nameCast(jetquery.Environment, environment),
|
|
.{
|
|
.admin = switch (action) {
|
|
.migrate, .rollback => false,
|
|
.create, .drop => true,
|
|
.schema => undefined, // We use a separate repo for schema reflection.
|
|
},
|
|
.context = .migration,
|
|
},
|
|
);
|
|
}
|