This commit is contained in:
Bob Farrell 2024-11-05 17:52:23 +00:00
parent bbdcc94084
commit 51fa6bd424
5 changed files with 100 additions and 5 deletions

View File

@ -4,7 +4,7 @@ const jetquery = @import("jetquery");
/// Run the migration generator. Create a migration in `src/app/database/migrations/`
pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, help: bool) !void {
if (help or args.len != 1) {
if (help or args.len < 1) {
std.debug.print(
\\Generate a new Migration. Migrations modify the application's database schema.
\\
@ -20,6 +20,10 @@ pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, he
}
const name = args[0];
const command = if (args.len > 1)
try std.mem.join(allocator, " ", args[1..])
else
null;
const migrations_dir = try cwd.makeOpenPath(
try std.fs.path.join(allocator, &.{ "src", "app", "database", "migrations" }),
@ -28,7 +32,10 @@ pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, he
const migration = jetquery.Migration.init(
allocator,
name,
.{ .migrations_path = try migrations_dir.realpathAlloc(allocator, ".") },
.{
.migrations_path = try migrations_dir.realpathAlloc(allocator, "."),
.command = command,
},
);
try migration.save();
}

View File

@ -26,7 +26,8 @@ pub fn printFailure() void {
std.debug.print("\n", .{});
}
/// Verifies that cwd is the root of a Jetzig project
/// Detects a Jetzig project directory either in the current directory or one of its parent
/// directories.
pub fn detectJetzigProjectDir() !std.fs.Dir {
var dir = try std.fs.cwd().openDir(".", .{});
const max_parent_dirs: usize = 100; // Prevent symlink loops or other weird stuff.

View File

@ -81,6 +81,9 @@ pub fn main() !void {
}
},
.schema => {
var cwd = try jetzig.util.detectJetzigProjectDir();
defer cwd.close();
const Repo = jetquery.Repo(config.adapter, Schema);
var repo = try Repo.loadConfig(
allocator,
@ -90,9 +93,19 @@ pub fn main() !void {
const reflect = @import("jetquery_reflect").Reflect(config.adapter, Schema).init(
allocator,
&repo,
.{
.import_jetquery =
\\@import("jetzig").jetquery
,
},
);
const schema = try reflect.generateSchema();
std.debug.print("{s}\n", .{schema});
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});
},
}
}

View File

@ -11,7 +11,7 @@ else
pub const database_lazy_connect = true;
pub const jetzig_options = struct {
pub const Schema = @import("jetquery_schema");
pub const Schema = @import("Schema");
};
pub fn main() !void {

View File

@ -125,3 +125,77 @@ pub fn writeAnsi(file: std.fs.File, writer: anytype, text: []const u8) !void {
}
}
}
/// Create a file at the given location and write content. Creates subpaths if not present.
pub fn createFile(path: []const u8, content: []const u8) !void {
if (std.fs.path.dirname(path)) |dirname| {
std.fs.makeDirAbsolute(dirname) catch |err| {
switch (err) {
error.PathAlreadyExists => {},
else => return err,
}
};
}
const file = try std.fs.createFileAbsolute(path, .{ .truncate = true });
try file.writeAll(content);
file.close();
}
/// Detects a Jetzig project directory either in the current directory or one of its parent
/// directories.
pub fn detectJetzigProjectDir() !std.fs.Dir {
var dir = try std.fs.cwd().openDir(".", .{});
const max_parent_dirs: usize = 100; // Prevent symlink loops or other weird stuff.
for (0..max_parent_dirs) |_| {
if (try isPath(dir, "build.zig", .file) and try isPath(dir, "src/app/views", .dir)) return dir;
dir = dir.openDir("..", .{}) catch |err| {
switch (err) {
error.FileNotFound, error.NotDir => {
std.debug.print(
"Encountered unexpected detecting Jetzig project directory: {s}\n",
.{@errorName(err)},
);
return error.JetzigCommandError;
},
else => return err,
}
};
continue;
}
std.debug.print(
\\Exceeded maximum parent directory depth.
\\Unable to detect Jetzig project directory.
\\
,
.{},
);
return error.JetzigCommandError;
}
fn isPath(dir: std.fs.Dir, sub_path: []const u8, path_type: enum { file, dir }) !bool {
switch (path_type) {
.file => {
_ = dir.statFile(sub_path) catch |err| {
switch (err) {
error.FileNotFound => return false,
else => return err,
}
};
return true;
},
.dir => {
var test_dir = dir.openDir(sub_path, .{}) catch |err| {
switch (err) {
error.FileNotFound, error.NotDir => return false,
else => return err,
}
};
test_dir.close();
return true;
},
}
}