mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 22:16:08 +00:00
WIP
This commit is contained in:
parent
c62c93a397
commit
bbdcc94084
65
build.zig
65
build.zig
@ -142,6 +142,14 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn
|
||||
.target = target,
|
||||
},
|
||||
);
|
||||
|
||||
const jetquery_dep = jetzig_dep.builder.dependency("jetquery", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.jetquery_migrations_path = @as([]const u8, "src/app/database/migrations"),
|
||||
.jetquery_config_path = @as([]const u8, "config/database.zig"),
|
||||
});
|
||||
|
||||
const jetzig_module = jetzig_dep.module("jetzig");
|
||||
const zmpl_module = jetzig_dep.module("zmpl");
|
||||
const zmd_module = jetzig_dep.module("zmd");
|
||||
@ -149,6 +157,7 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn
|
||||
const jetquery_module = jetzig_dep.module("jetquery");
|
||||
const jetcommon_module = jetzig_dep.module("jetcommon");
|
||||
const jetquery_migrate_module = jetzig_dep.module("jetquery_migrate");
|
||||
const jetquery_reflect_module = jetquery_dep.module("jetquery_reflect");
|
||||
|
||||
const build_options = b.addOptions();
|
||||
build_options.addOption(Environment, "environment", environment);
|
||||
@ -316,41 +325,14 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_database.root_module.addImport("jetquery", jetquery_module);
|
||||
exe_database.root_module.addImport("jetzig", jetzig_module);
|
||||
exe_database.root_module.addImport("jetcommon", jetcommon_module);
|
||||
exe_database.root_module.addImport("jetquery_migrate", jetquery_migrate_module);
|
||||
exe_database.root_module.addOptions("build_options", build_options);
|
||||
exe_database.root_module.addImport("jetquery_reflect", jetquery_reflect_module);
|
||||
exe_database.root_module.addImport("Schema", schema_module);
|
||||
// exe_database.root_module.addOptions("build_options", build_options);
|
||||
|
||||
const database_migrate_step = b.step(
|
||||
"jetzig:database:migrate",
|
||||
"Migrate your Jetzig app's database.",
|
||||
);
|
||||
const run_database_migrate_cmd = b.addRunArtifact(exe_database);
|
||||
run_database_migrate_cmd.addArg("migrate");
|
||||
database_migrate_step.dependOn(&run_database_migrate_cmd.step);
|
||||
|
||||
const database_rollback_step = b.step(
|
||||
"jetzig:database:rollback",
|
||||
"Roll back a migration in your Jetzig app's database.",
|
||||
);
|
||||
const run_database_rollback_cmd = b.addRunArtifact(exe_database);
|
||||
run_database_rollback_cmd.addArg("rollback");
|
||||
database_rollback_step.dependOn(&run_database_rollback_cmd.step);
|
||||
|
||||
const database_create_step = b.step(
|
||||
"jetzig:database:create",
|
||||
"Create a database for your Jetzig app.",
|
||||
);
|
||||
const run_database_create_cmd = b.addRunArtifact(exe_database);
|
||||
run_database_create_cmd.addArg("create");
|
||||
database_create_step.dependOn(&run_database_create_cmd.step);
|
||||
|
||||
const database_drop_step = b.step(
|
||||
"jetzig:database:drop",
|
||||
"Drop your Jetzig app's database.",
|
||||
);
|
||||
const run_database_drop_cmd = b.addRunArtifact(exe_database);
|
||||
run_database_drop_cmd.addArg("drop");
|
||||
database_drop_step.dependOn(&run_database_drop_cmd.step);
|
||||
registerDatabaseSteps(b, exe_database);
|
||||
|
||||
exe_routes.root_module.addImport("jetzig", jetzig_module);
|
||||
exe_routes.root_module.addImport("routes", routes_module);
|
||||
@ -359,6 +341,25 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn
|
||||
routes_step.dependOn(&run_routes_cmd.step);
|
||||
}
|
||||
|
||||
fn registerDatabaseSteps(b: *std.Build, exe_database: *std.Build.Step.Compile) void {
|
||||
const commands = .{
|
||||
.{ "migrate", "Migrate your Jetzig app's database." },
|
||||
.{ "rollback", "Roll back a migration in your Jetzig app's database." },
|
||||
.{ "create", "Create a database for your Jetzig app." },
|
||||
.{ "drop", "Drop your Jetzig app's database." },
|
||||
.{ "schema", "Read your app's database and generate a JetQuery schema." },
|
||||
};
|
||||
|
||||
inline for (commands) |command| {
|
||||
const action = command[0];
|
||||
const description = command[1];
|
||||
const step = b.step("jetzig:database:" ++ action, description);
|
||||
const run_cmd = b.addRunArtifact(exe_database);
|
||||
run_cmd.addArg(action);
|
||||
step.dependOn(&run_cmd.step);
|
||||
}
|
||||
}
|
||||
|
||||
fn generateMarkdownFragments(b: *std.Build) ![]const u8 {
|
||||
const file = std.fs.cwd().openFile(b.pathJoin(&.{ "src", "main.zig" }), .{}) catch |err| {
|
||||
switch (err) {
|
||||
|
@ -10,11 +10,13 @@ const migrate = @import("database/migrate.zig");
|
||||
const rollback = @import("database/rollback.zig");
|
||||
const create = @import("database/create.zig");
|
||||
const drop = @import("database/drop.zig");
|
||||
const schema = @import("database/schema.zig");
|
||||
pub const confirm_drop_env = "JETZIG_DROP_PRODUCTION_DATABASE";
|
||||
|
||||
/// Command line options for the `database` command.
|
||||
pub const Options = struct {
|
||||
pub const meta = .{
|
||||
.usage_summary = "[migrate|rollback|create|drop]",
|
||||
.usage_summary = "[migrate|rollback|create|drop|schema]",
|
||||
.full_text =
|
||||
\\Manage the application's database.
|
||||
\\
|
||||
@ -38,12 +40,13 @@ pub fn run(
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
const Action = enum { migrate, rollback, create, drop };
|
||||
const Action = enum { migrate, rollback, create, drop, schema };
|
||||
const map = std.StaticStringMap(Action).initComptime(.{
|
||||
.{ "migrate", .migrate },
|
||||
.{ "rollback", .rollback },
|
||||
.{ "create", .create },
|
||||
.{ "drop", .drop },
|
||||
.{ "schema", .schema },
|
||||
});
|
||||
|
||||
const action = if (main_options.positionals.len > 0)
|
||||
@ -71,6 +74,7 @@ pub fn run(
|
||||
.rollback => rollback.run(alloc, cwd, sub_args, options, T, main_options),
|
||||
.create => create.run(alloc, cwd, sub_args, options, T, main_options),
|
||||
.drop => drop.run(alloc, cwd, sub_args, options, T, main_options),
|
||||
.schema => schema.run(alloc, cwd, sub_args, options, T, main_options),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn run(
|
||||
\\Example:
|
||||
\\
|
||||
\\ jetzig database create
|
||||
\\ jetzig --environment testing database create
|
||||
\\ jetzig --environment=testing database create
|
||||
\\
|
||||
, .{});
|
||||
|
||||
|
@ -15,14 +15,17 @@ pub fn run(
|
||||
_ = options;
|
||||
if (main_options.options.help or args.len != 0) {
|
||||
std.debug.print(
|
||||
\\Run database migrations.
|
||||
\\Drop database.
|
||||
\\
|
||||
\\Example:
|
||||
\\
|
||||
\\ jetzig database migrate
|
||||
\\ jetzig --environment testing database migrate
|
||||
\\ jetzig --environment=testing database migrate
|
||||
\\
|
||||
, .{});
|
||||
\\To drop a production database, set the environment variable `{s}` to the name of the database you want to drop, e.g.:
|
||||
\\
|
||||
\\ {0s}=my_production_production jetzig --environment=production database drop
|
||||
, .{cli.database.confirm_drop_env});
|
||||
|
||||
return if (main_options.options.help) {} else error.JetzigCommandError;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn run(
|
||||
\\Example:
|
||||
\\
|
||||
\\ jetzig database migrate
|
||||
\\ jetzig --environment testing database migrate
|
||||
\\ jetzig --environment=testing database migrate
|
||||
\\
|
||||
, .{});
|
||||
|
||||
|
@ -15,12 +15,12 @@ pub fn run(
|
||||
_ = options;
|
||||
if (main_options.options.help or args.len != 0) {
|
||||
std.debug.print(
|
||||
\\Run database migrations.
|
||||
\\Roll back a database migration.
|
||||
\\
|
||||
\\Example:
|
||||
\\
|
||||
\\ jetzig database migrate
|
||||
\\ jetzig --environment testing database migrate
|
||||
\\ jetzig database rollback
|
||||
\\ jetzig --environment=testing database rollback
|
||||
\\
|
||||
, .{});
|
||||
|
||||
|
35
cli/commands/database/schema.zig
Normal file
35
cli/commands/database/schema.zig
Normal file
@ -0,0 +1,35 @@
|
||||
const std = @import("std");
|
||||
|
||||
const cli = @import("../../cli.zig");
|
||||
const util = @import("../../util.zig");
|
||||
|
||||
pub fn run(
|
||||
allocator: std.mem.Allocator,
|
||||
cwd: std.fs.Dir,
|
||||
args: []const []const u8,
|
||||
options: cli.database.Options,
|
||||
T: type,
|
||||
main_options: T,
|
||||
) !void {
|
||||
_ = cwd;
|
||||
_ = options;
|
||||
if (main_options.options.help or args.len != 0) {
|
||||
std.debug.print(
|
||||
\\Generate a JetQuery schema file and save to `src/app/database/Schema.zig`.
|
||||
\\
|
||||
\\Example:
|
||||
\\
|
||||
\\ jetzig database schema
|
||||
\\
|
||||
, .{});
|
||||
|
||||
return if (main_options.options.help) {} else error.JetzigCommandError;
|
||||
}
|
||||
|
||||
try util.execCommand(allocator, &.{
|
||||
"zig",
|
||||
"build",
|
||||
util.environmentBuildOption(main_options.options.environment),
|
||||
"jetzig:database:schema",
|
||||
});
|
||||
}
|
@ -3,12 +3,18 @@ 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 `JETZIG_DROP_PRODUCTION_DATABASE={s}`. Exiting.";
|
||||
"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(.{}){};
|
||||
@ -24,40 +30,29 @@ pub fn main() !void {
|
||||
|
||||
if (args.len < 2) return error.JetzigMissingDatabaseArgument;
|
||||
|
||||
const Action = enum { migrate, rollback, create, drop };
|
||||
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;
|
||||
|
||||
const environment = build_options.environment;
|
||||
const config = @field(jetquery.config.database, @tagName(environment));
|
||||
|
||||
const Repo = jetquery.Repo(config.adapter, MigrateSchema);
|
||||
var repo = try Repo.loadConfig(
|
||||
allocator,
|
||||
std.enums.nameCast(jetquery.Environment, environment),
|
||||
.{
|
||||
.admin = switch (action) {
|
||||
.migrate, .rollback => false,
|
||||
.create, .drop => true,
|
||||
},
|
||||
.context = .migration,
|
||||
},
|
||||
);
|
||||
defer repo.deinit();
|
||||
|
||||
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 => {
|
||||
@ -72,14 +67,48 @@ pub fn main() !void {
|
||||
}
|
||||
};
|
||||
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 => {
|
||||
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,
|
||||
);
|
||||
const schema = try reflect.generateSchema();
|
||||
std.debug.print("{s}\n", .{schema});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ else
|
||||
pub const database_lazy_connect = true;
|
||||
|
||||
pub const jetzig_options = struct {
|
||||
pub const Schema = @import("Schema");
|
||||
pub const Schema = @import("jetquery_schema");
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
|
@ -26,7 +26,8 @@ pub const DateTime = jetcommon.types.DateTime;
|
||||
pub const Time = jetcommon.types.Time;
|
||||
pub const Date = jetcommon.types.Date;
|
||||
|
||||
pub const environment = @import("build_options").environment;
|
||||
pub const build_options = @import("build_options");
|
||||
pub const environment = build_options.environment;
|
||||
|
||||
/// The primary interface for a Jetzig application. Create an `App` in your application's
|
||||
/// `src/main.zig` and call `start` to launch the application.
|
||||
|
Loading…
x
Reference in New Issue
Block a user