mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 14:06:08 +00:00
Merge pull request #185 from jetzig-framework/zig-0.15
Zig 0.15 compatibility
This commit is contained in:
commit
6d522c07c5
4
.github/workflows/CI.yml
vendored
4
.github/workflows/CI.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Setup Zig
|
- name: Setup Zig
|
||||||
uses: mlugg/setup-zig@v1
|
uses: mlugg/setup-zig@v1
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: master
|
||||||
|
|
||||||
- run: zig version
|
- run: zig version
|
||||||
- run: zig env
|
- run: zig env
|
||||||
@ -51,7 +51,7 @@ jobs:
|
|||||||
JETQUERY_HOSTNAME: 'localhost'
|
JETQUERY_HOSTNAME: 'localhost'
|
||||||
JETQUERY_USERNAME: 'postgres'
|
JETQUERY_USERNAME: 'postgres'
|
||||||
JETQUERY_PASSWORD: 'postgres'
|
JETQUERY_PASSWORD: 'postgres'
|
||||||
JETQUERY_DATABASE: 'test'
|
JETQUERY_DATABASE: 'jetzig_demo_test'
|
||||||
# Assume a small amount of connections are allowed
|
# Assume a small amount of connections are allowed
|
||||||
# into postgres
|
# into postgres
|
||||||
JETQUERY_POOL_SIZE: 2
|
JETQUERY_POOL_SIZE: 2
|
||||||
|
@ -425,6 +425,8 @@ fn registerDatabaseSteps(b: *std.Build, exe_database: *std.Build.Step.Compile) v
|
|||||||
.{ "create", "Create a database for your Jetzig app." },
|
.{ "create", "Create a database for your Jetzig app." },
|
||||||
.{ "drop", "Drop your Jetzig app's database." },
|
.{ "drop", "Drop your Jetzig app's database." },
|
||||||
.{ "reflect", "Read your app's database and generate a JetQuery schema." },
|
.{ "reflect", "Read your app's database and generate a JetQuery schema." },
|
||||||
|
.{ "setup", "Create the database, run migrations, and generate schema." },
|
||||||
|
.{ "update", "Run migrations and generate schema." },
|
||||||
};
|
};
|
||||||
|
|
||||||
inline for (commands) |command| {
|
inline for (commands) |command| {
|
||||||
@ -466,10 +468,10 @@ fn getMarkdownFragmentsSource(allocator: std.mem.Allocator, source: [:0]const u8
|
|||||||
for (ast.nodes.items(.tag), 0..) |tag, index| {
|
for (ast.nodes.items(.tag), 0..) |tag, index| {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.simple_var_decl => {
|
.simple_var_decl => {
|
||||||
const decl = ast.simpleVarDecl(@intCast(index));
|
const decl = ast.simpleVarDecl(@enumFromInt(index));
|
||||||
const identifier = ast.tokenSlice(decl.ast.mut_token + 1);
|
const identifier = ast.tokenSlice(decl.ast.mut_token + 1);
|
||||||
if (std.mem.eql(u8, identifier, "markdown_fragments")) {
|
if (std.mem.eql(u8, identifier, "markdown_fragments")) {
|
||||||
return ast.getNodeSource(@intCast(index));
|
return ast.getNodeSource(@enumFromInt(index));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => continue,
|
else => continue,
|
||||||
|
@ -3,30 +3,14 @@
|
|||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.fingerprint = 0x93ad8bfa2d209022,
|
.fingerprint = 0x93ad8bfa2d209022,
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.jetquery = .{
|
|
||||||
.url = "https://github.com/jetzig-framework/jetquery/archive/6c3fa3c8557d24b8e6a022632909d162e86be5d7.tar.gz",
|
|
||||||
.hash = "jetquery-0.0.0-TNf3zjZWBgCLlUMITutBU9dP72AfSVYobcdYJ4AmJT2H",
|
|
||||||
},
|
|
||||||
.jetkv = .{
|
|
||||||
.url = "https://github.com/jetzig-framework/jetkv/archive/9d754e552e7569239a900ed9e0f313a0554ed2d3.tar.gz",
|
|
||||||
.hash = "122013f8596bc615990fd7771c833cab4d2959ecac8d05c4f6c973aa46624e43afea",
|
|
||||||
},
|
|
||||||
.jetcommon = .{
|
.jetcommon = .{
|
||||||
.url = "https://github.com/jetzig-framework/jetcommon/archive/fb4edc13759d87bfcd9b1f5fcefdf93f8c9c62dd.tar.gz",
|
.url = "https://github.com/jetzig-framework/jetcommon/archive/fb4edc13759d87bfcd9b1f5fcefdf93f8c9c62dd.tar.gz",
|
||||||
.hash = "jetcommon-0.1.0-jPY_DS1HAAAP8xp5HSWB_ZY7m9JEYUmm8adQFrse0lwB",
|
.hash = "jetcommon-0.1.0-jPY_DS1HAAAP8xp5HSWB_ZY7m9JEYUmm8adQFrse0lwB",
|
||||||
},
|
},
|
||||||
.zmpl = .{
|
|
||||||
.url = "https://github.com/jetzig-framework/zmpl/archive/3ec11289fdee2e0c70975cb5dd85d3041d723912.tar.gz",
|
|
||||||
.hash = "zmpl-0.0.1-SYFGBuZoAwAMuvHNkO_1BbutpWhg7CdSgYd8t4OaaZeR",
|
|
||||||
},
|
|
||||||
.zmd = .{
|
.zmd = .{
|
||||||
.url = "https://github.com/jetzig-framework/zmd/archive/d6c8aa9a9cde99674ccb096d8f94ed09cba8dab.tar.gz",
|
.url = "https://github.com/jetzig-framework/zmd/archive/d6c8aa9a9cde99674ccb096d8f94ed09cba8dab.tar.gz",
|
||||||
.hash = "1220d0e8734628fd910a73146e804d10a3269e3e7d065de6bb0e3e88d5ba234eb163",
|
.hash = "1220d0e8734628fd910a73146e804d10a3269e3e7d065de6bb0e3e88d5ba234eb163",
|
||||||
},
|
},
|
||||||
.httpz = .{
|
|
||||||
.url = "https://github.com/karlseguin/http.zig/archive/eced2d8c37f921a2dfc8ab639964cdc9b505a888.tar.gz",
|
|
||||||
.hash = "httpz-0.0.0-AAAAAL6qBgAeyws7FZLTv3e_Sbsjg4PKfB1Fg6AOHctf",
|
|
||||||
},
|
|
||||||
.smtp_client = .{
|
.smtp_client = .{
|
||||||
.url = "https://github.com/karlseguin/smtp_client.zig/archive/5163c66cc42cdd93176a6b1cad45f3db3a291a6a.tar.gz",
|
.url = "https://github.com/karlseguin/smtp_client.zig/archive/5163c66cc42cdd93176a6b1cad45f3db3a291a6a.tar.gz",
|
||||||
.hash = "smtp_client-0.0.1-AAAAAIJkAQCngHtRYVUMsMuncmicSHK_7ugwWibDzQ4S",
|
.hash = "smtp_client-0.0.1-AAAAAIJkAQCngHtRYVUMsMuncmicSHK_7ugwWibDzQ4S",
|
||||||
@ -35,6 +19,22 @@
|
|||||||
.url = "https://github.com/bobf/zig-args/archive/88cbade9a517a4014824f8f53f3c48c8a0b2ffe1.tar.gz",
|
.url = "https://github.com/bobf/zig-args/archive/88cbade9a517a4014824f8f53f3c48c8a0b2ffe1.tar.gz",
|
||||||
.hash = "zig_args-0.0.0-jqtN6P_NAAC97fGpk9hS2K681jkiqPsWP6w3ucb_ctGH",
|
.hash = "zig_args-0.0.0-jqtN6P_NAAC97fGpk9hS2K681jkiqPsWP6w3ucb_ctGH",
|
||||||
},
|
},
|
||||||
|
.jetkv = .{
|
||||||
|
.url = "https://github.com/jetzig-framework/jetkv/archive/5a94e3bac0a6e291efc9d6534beb2d311671ff17.tar.gz",
|
||||||
|
.hash = "jetkv-0.0.0-zCv0fmCGAgCyYqwHjk0P5KrYVRew1MJAtbtAcIO-WPpT",
|
||||||
|
},
|
||||||
|
.zmpl = .{
|
||||||
|
.url = "https://github.com/jetzig-framework/zmpl/archive/c57fc9b83027e8c1459d9625c3509f59f0fb89f3.tar.gz",
|
||||||
|
.hash = "zmpl-0.0.1-SYFGBgdqAwDeA6xm4KAhpKoNrWs5CMQK6x447zhWclCs",
|
||||||
|
},
|
||||||
|
.httpz = .{
|
||||||
|
.url = "https://github.com/karlseguin/http.zig/archive/37d7cb9819b804ade5f4b974b82f8dd0622225ed.tar.gz",
|
||||||
|
.hash = "httpz-0.0.0-PNVzrEK4BgBpHQGA2m0RPqPGEjnTdDXHodBwzjYDrmps",
|
||||||
|
},
|
||||||
|
.jetquery = .{
|
||||||
|
.url = "https://github.com/jetzig-framework/jetquery/archive/e1f969f2e3e0e1ad9cc30d56fde9739aa692fdc3.tar.gz",
|
||||||
|
.hash = "jetquery-0.0.0-TNf3zo2ABgBgcsIAvJ1Ud2B2zDzrBy9GQ31kKmTYZ7Ya",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
.hash = "zig_args-0.0.0-jqtN6P_NAAC97fGpk9hS2K681jkiqPsWP6w3ucb_ctGH",
|
.hash = "zig_args-0.0.0-jqtN6P_NAAC97fGpk9hS2K681jkiqPsWP6w3ucb_ctGH",
|
||||||
},
|
},
|
||||||
.jetquery = .{
|
.jetquery = .{
|
||||||
.url = "https://github.com/jetzig-framework/jetquery/archive/6c3fa3c8557d24b8e6a022632909d162e86be5d7.tar.gz",
|
.url = "https://github.com/jetzig-framework/jetquery/archive/e1f969f2e3e0e1ad9cc30d56fde9739aa692fdc3.tar.gz",
|
||||||
.hash = "jetquery-0.0.0-TNf3zjZWBgCLlUMITutBU9dP72AfSVYobcdYJ4AmJT2H",
|
.hash = "jetquery-0.0.0-TNf3zo2ABgBgcsIAvJ1Ud2B2zDzrBy9GQ31kKmTYZ7Ya",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
44
demo/Makefile
Normal file
44
demo/Makefile
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# Use this Makefile to set up a local Docker PostgreSQL database and run tests, or launch a local
|
||||||
|
# development database.
|
||||||
|
#
|
||||||
|
## Tests
|
||||||
|
#
|
||||||
|
# Set up test database and run application tests:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# make test
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
## Development
|
||||||
|
#
|
||||||
|
# Set up development database and launch the demo Jetzig app:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# make dev
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# TODO: Move all of this into `build.zig`
|
||||||
|
test_database=jetzig_demo_test
|
||||||
|
dev_database=jetzig_demo_dev
|
||||||
|
port=14173
|
||||||
|
|
||||||
|
export JETQUERY_HOSTNAME=localhost
|
||||||
|
export JETQUERY_USERNAME=postgres
|
||||||
|
export JETQUERY_PASSWORD=postgres
|
||||||
|
export JETQUERY_POOL_SIZE=2
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: env=JETQUERY_DATABASE=${test_database} JETQUERY_PORT=${port}
|
||||||
|
test:
|
||||||
|
docker compose up --detach --wait --renew-anon-volumes --remove-orphans --force-recreate
|
||||||
|
${env} zig build -Denvironment=testing jetzig:database:setup
|
||||||
|
${env} zig build -Denvironment=testing jetzig:test
|
||||||
|
|
||||||
|
.PHONY: dev
|
||||||
|
dev: env=JETQUERY_DATABASE=${dev_database} JETQUERY_PORT=${port}
|
||||||
|
dev:
|
||||||
|
docker compose up --detach --wait --renew-anon-volumes --remove-orphans
|
||||||
|
${env} zig build -Denvironment=testing jetzig:database:setup
|
||||||
|
${env} jetzig server
|
7
demo/compose.yml
Normal file
7
demo/compose.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:17
|
||||||
|
ports:
|
||||||
|
- 14173:5432
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: 'postgres'
|
@ -1,7 +1,16 @@
|
|||||||
pub const database = .{
|
pub const database = .{
|
||||||
|
.development = .{
|
||||||
|
.adapter = .postgresql,
|
||||||
|
.username = "postgres",
|
||||||
|
.password = "postgres",
|
||||||
|
.hostname = "localhost",
|
||||||
|
.database = "jetzig_demo_dev",
|
||||||
|
.port = 14173, // See `compose.yml`
|
||||||
|
},
|
||||||
// This configuration is used for CI
|
// This configuration is used for CI
|
||||||
// in GitHub
|
// in GitHub
|
||||||
.testing = .{
|
.testing = .{
|
||||||
.adapter = .postgresql,
|
.adapter = .postgresql,
|
||||||
|
.database = "jetzig_demo_test",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
const jetquery = @import("jetzig").jetquery;
|
const jetquery = @import("jetzig").jetquery;
|
||||||
|
|
||||||
pub const User = jetquery.Model(@This(), "users", struct {
|
pub const User = jetquery.Model(
|
||||||
id: i32,
|
@This(),
|
||||||
email: []const u8,
|
"users",
|
||||||
password_hash: []const u8,
|
struct {
|
||||||
created_at: jetquery.DateTime,
|
id: i32,
|
||||||
updated_at: jetquery.DateTime,
|
email: []const u8,
|
||||||
}, .{});
|
password_hash: []const u8,
|
||||||
|
created_at: jetquery.DateTime,
|
||||||
|
updated_at: jetquery.DateTime,
|
||||||
|
},
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
@ -390,7 +390,7 @@ fn generateRoutesForView(self: *Routes, dir: std.fs.Dir, path: []const u8) !Rout
|
|||||||
for (self.ast.nodes.items(.tag), 0..) |tag, index| {
|
for (self.ast.nodes.items(.tag), 0..) |tag, index| {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.fn_proto_multi, .fn_proto_one, .fn_proto_simple => |function_tag| {
|
.fn_proto_multi, .fn_proto_one, .fn_proto_simple => |function_tag| {
|
||||||
var function = try self.parseFunction(function_tag, index, path, source);
|
var function = try self.parseFunction(function_tag, @enumFromInt(index), path, source);
|
||||||
if (function) |*capture| {
|
if (function) |*capture| {
|
||||||
if (capture.args.len == 0) {
|
if (capture.args.len == 0) {
|
||||||
std.debug.print(
|
std.debug.print(
|
||||||
@ -414,7 +414,7 @@ fn generateRoutesForView(self: *Routes, dir: std.fs.Dir, path: []const u8) !Rout
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.simple_var_decl => {
|
.simple_var_decl => {
|
||||||
const decl = self.ast.simpleVarDecl(asNodeIndex(index));
|
const decl = self.ast.simpleVarDecl(@enumFromInt(index));
|
||||||
if (self.isStaticParamsDecl(decl)) {
|
if (self.isStaticParamsDecl(decl)) {
|
||||||
self.data.reset();
|
self.data.reset();
|
||||||
const params = try self.data.root(.object);
|
const params = try self.data.root(.object);
|
||||||
@ -452,10 +452,11 @@ fn generateRoutesForView(self: *Routes, dir: std.fs.Dir, path: []const u8) !Rout
|
|||||||
|
|
||||||
// Parse the `pub const static_params` definition and into a `jetzig.data.Value`.
|
// Parse the `pub const static_params` definition and into a `jetzig.data.Value`.
|
||||||
fn parseStaticParamsDecl(self: *Routes, decl: std.zig.Ast.full.VarDecl, params: *jetzig.data.Value) !void {
|
fn parseStaticParamsDecl(self: *Routes, decl: std.zig.Ast.full.VarDecl, params: *jetzig.data.Value) !void {
|
||||||
const init_node = self.ast.nodes.items(.tag)[decl.ast.init_node];
|
const init_node = decl.ast.init_node.unwrap() orelse return;
|
||||||
switch (init_node) {
|
|
||||||
|
switch (self.ast.nodeTag(init_node)) {
|
||||||
.struct_init_dot_two, .struct_init_dot_two_comma => {
|
.struct_init_dot_two, .struct_init_dot_two_comma => {
|
||||||
try self.parseStruct(decl.ast.init_node, params);
|
try self.parseStruct(init_node, params);
|
||||||
},
|
},
|
||||||
else => return,
|
else => return,
|
||||||
}
|
}
|
||||||
@ -488,14 +489,14 @@ fn parseArray(self: *Routes, node: std.zig.Ast.Node.Index, params: *jetzig.data.
|
|||||||
|
|
||||||
const array = maybe_array.?;
|
const array = maybe_array.?;
|
||||||
|
|
||||||
const main_token = self.ast.nodes.items(.main_token)[node];
|
const main_token = self.ast.nodeMainToken(node);
|
||||||
const field_name = self.ast.tokenSlice(main_token - 3);
|
const field_name = self.ast.tokenSlice(main_token - 3);
|
||||||
|
|
||||||
const params_array = try self.data.array();
|
const params_array = try self.data.array();
|
||||||
try params.put(field_name, params_array);
|
try params.put(field_name, params_array);
|
||||||
|
|
||||||
for (array.ast.elements) |element| {
|
for (array.ast.elements) |element| {
|
||||||
const elem = self.ast.nodes.items(.tag)[element];
|
const elem = self.ast.nodeTag(element);
|
||||||
switch (elem) {
|
switch (elem) {
|
||||||
.struct_init_dot, .struct_init_dot_two, .struct_init_dot_two_comma => {
|
.struct_init_dot, .struct_init_dot_two, .struct_init_dot_two_comma => {
|
||||||
const route_params = try self.data.object();
|
const route_params = try self.data.object();
|
||||||
@ -508,20 +509,20 @@ fn parseArray(self: *Routes, node: std.zig.Ast.Node.Index, params: *jetzig.data.
|
|||||||
try self.parseField(element, route_params);
|
try self.parseField(element, route_params);
|
||||||
},
|
},
|
||||||
.string_literal => {
|
.string_literal => {
|
||||||
const string_token = self.ast.nodes.items(.main_token)[element];
|
const string_token = self.ast.nodeMainToken(element);
|
||||||
const string_value = self.ast.tokenSlice(string_token);
|
const string_value = self.ast.tokenSlice(string_token);
|
||||||
|
|
||||||
// Strip quotes: `"foo"` -> `foo`
|
// Strip quotes: `"foo"` -> `foo`
|
||||||
try params_array.append(string_value[1 .. string_value.len - 1]);
|
try params_array.append(string_value[1 .. string_value.len - 1]);
|
||||||
},
|
},
|
||||||
.number_literal => {
|
.number_literal => {
|
||||||
const number_token = self.ast.nodes.items(.main_token)[element];
|
const number_token = self.ast.nodeMainToken(element);
|
||||||
const number_value = self.ast.tokenSlice(number_token);
|
const number_value = self.ast.tokenSlice(number_token);
|
||||||
try params_array.append(try parseNumber(number_value, self.data));
|
try params_array.append(try parseNumber(number_value, self.data));
|
||||||
},
|
},
|
||||||
inline else => {
|
inline else => {
|
||||||
@setEvalBranchQuota(10_000);
|
@setEvalBranchQuota(10_000);
|
||||||
const tag = self.ast.nodes.items(.tag)[element];
|
const tag = self.ast.nodeTag(element);
|
||||||
std.debug.print("Unexpected token: {}\n", .{tag});
|
std.debug.print("Unexpected token: {}\n", .{tag});
|
||||||
return error.JetzigStaticParamsParseError;
|
return error.JetzigStaticParamsParseError;
|
||||||
},
|
},
|
||||||
@ -531,22 +532,21 @@ fn parseArray(self: *Routes, node: std.zig.Ast.Node.Index, params: *jetzig.data.
|
|||||||
|
|
||||||
// Parse the value of a param field (recursively when field is a struct/array)
|
// Parse the value of a param field (recursively when field is a struct/array)
|
||||||
fn parseField(self: *Routes, node: std.zig.Ast.Node.Index, params: *jetzig.data.Value) anyerror!void {
|
fn parseField(self: *Routes, node: std.zig.Ast.Node.Index, params: *jetzig.data.Value) anyerror!void {
|
||||||
const tag = self.ast.nodes.items(.tag)[node];
|
switch (self.ast.nodeTag(node)) {
|
||||||
switch (tag) {
|
|
||||||
// Route params, e.g. `.index = .{ ... }`
|
// Route params, e.g. `.index = .{ ... }`
|
||||||
.array_init_dot, .array_init_dot_two, .array_init_dot_comma, .array_init_dot_two_comma => {
|
.array_init_dot, .array_init_dot_two, .array_init_dot_comma, .array_init_dot_two_comma => {
|
||||||
try self.parseArray(node, params);
|
try self.parseArray(node, params);
|
||||||
},
|
},
|
||||||
.struct_init_dot, .struct_init_dot_two, .struct_init_dot_two_comma => {
|
.struct_init_dot, .struct_init_dot_two, .struct_init_dot_two_comma => {
|
||||||
const nested_params = try self.data.object();
|
const nested_params = try self.data.object();
|
||||||
const main_token = self.ast.nodes.items(.main_token)[node];
|
const main_token = self.ast.nodeMainToken(node);
|
||||||
const field_name = self.ast.tokenSlice(main_token - 3);
|
const field_name = self.ast.tokenSlice(main_token - 3);
|
||||||
try params.put(field_name, nested_params);
|
try params.put(field_name, nested_params);
|
||||||
try self.parseStruct(node, nested_params);
|
try self.parseStruct(node, nested_params);
|
||||||
},
|
},
|
||||||
// Individual param in a params struct, e.g. `.foo = "bar"`
|
// Individual param in a params struct, e.g. `.foo = "bar"`
|
||||||
.string_literal => {
|
.string_literal => {
|
||||||
const main_token = self.ast.nodes.items(.main_token)[node];
|
const main_token = self.ast.nodeMainToken(node);
|
||||||
const field_name = self.ast.tokenSlice(main_token - 2);
|
const field_name = self.ast.tokenSlice(main_token - 2);
|
||||||
const field_value = self.ast.tokenSlice(main_token);
|
const field_value = self.ast.tokenSlice(main_token);
|
||||||
|
|
||||||
@ -557,13 +557,13 @@ fn parseField(self: *Routes, node: std.zig.Ast.Node.Index, params: *jetzig.data.
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
.number_literal => {
|
.number_literal => {
|
||||||
const main_token = self.ast.nodes.items(.main_token)[node];
|
const main_token = self.ast.nodeMainToken(node);
|
||||||
const field_name = self.ast.tokenSlice(main_token - 2);
|
const field_name = self.ast.tokenSlice(main_token - 2);
|
||||||
const field_value = self.ast.tokenSlice(main_token);
|
const field_value = self.ast.tokenSlice(main_token);
|
||||||
|
|
||||||
try params.put(field_name, try parseNumber(field_value, self.data));
|
try params.put(field_name, try parseNumber(field_value, self.data));
|
||||||
},
|
},
|
||||||
else => {
|
else => |tag| {
|
||||||
std.debug.print("Unexpected token: {}\n", .{tag});
|
std.debug.print("Unexpected token: {}\n", .{tag});
|
||||||
return error.JetzigStaticParamsParseError;
|
return error.JetzigStaticParamsParseError;
|
||||||
},
|
},
|
||||||
@ -594,16 +594,16 @@ fn isStaticParamsDecl(self: *Routes, decl: std.zig.Ast.full.VarDecl) bool {
|
|||||||
fn parseFunction(
|
fn parseFunction(
|
||||||
self: *Routes,
|
self: *Routes,
|
||||||
function_type: std.zig.Ast.Node.Tag,
|
function_type: std.zig.Ast.Node.Tag,
|
||||||
index: usize,
|
index: std.zig.Ast.Node.Index,
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
source: []const u8,
|
source: []const u8,
|
||||||
) !?Function {
|
) !?Function {
|
||||||
var buf: [1]std.zig.Ast.Node.Index = undefined;
|
var buf: [1]std.zig.Ast.Node.Index = undefined;
|
||||||
|
|
||||||
const fn_proto = switch (function_type) {
|
const fn_proto = switch (function_type) {
|
||||||
.fn_proto_multi => self.ast.fnProtoMulti(@as(u32, @intCast(index))),
|
.fn_proto_multi => self.ast.fnProtoMulti(index),
|
||||||
.fn_proto_one => self.ast.fnProtoOne(&buf, @as(u32, @intCast(index))),
|
.fn_proto_one => self.ast.fnProtoOne(&buf, index),
|
||||||
.fn_proto_simple => self.ast.fnProtoSimple(&buf, @as(u32, @intCast(index))),
|
.fn_proto_simple => self.ast.fnProtoSimple(&buf, index),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
if (fn_proto.name_token) |token| {
|
if (fn_proto.name_token) |token| {
|
||||||
@ -620,7 +620,7 @@ fn parseFunction(
|
|||||||
while (it.next()) |arg| {
|
while (it.next()) |arg| {
|
||||||
if (arg.name_token) |arg_token| {
|
if (arg.name_token) |arg_token| {
|
||||||
const arg_name = self.ast.tokenSlice(arg_token);
|
const arg_name = self.ast.tokenSlice(arg_token);
|
||||||
const node = self.ast.nodes.get(arg.type_expr);
|
const node = self.ast.nodes.get(@intFromEnum(arg.type_expr.?));
|
||||||
const type_name = try self.parseTypeExpr(node);
|
const type_name = try self.parseTypeExpr(node);
|
||||||
try args.append(.{ .name = arg_name, .type_name = type_name });
|
try args.append(.{ .name = arg_name, .type_name = type_name });
|
||||||
}
|
}
|
||||||
@ -666,10 +666,6 @@ fn parseTypeExpr(self: *Routes, node: std.zig.Ast.Node) ![]const u8 {
|
|||||||
return error.JetzigAstParserError;
|
return error.JetzigAstParserError;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asNodeIndex(index: usize) std.zig.Ast.Node.Index {
|
|
||||||
return @as(std.zig.Ast.Node.Index, @intCast(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isActionFunctionName(name: []const u8) bool {
|
fn isActionFunctionName(name: []const u8) bool {
|
||||||
inline for (@typeInfo(jetzig.views.Route.Action).@"enum".fields) |field| {
|
inline for (@typeInfo(jetzig.views.Route.Action).@"enum".fields) |field| {
|
||||||
if (std.mem.eql(u8, field.name, name)) return true;
|
if (std.mem.eql(u8, field.name, name)) return true;
|
||||||
|
@ -15,7 +15,7 @@ const production_drop_failure_message = "To drop a production database, " ++
|
|||||||
|
|
||||||
const environment = jetzig.build_options.environment;
|
const environment = jetzig.build_options.environment;
|
||||||
const config = @field(jetquery.config.database, @tagName(environment));
|
const config = @field(jetquery.config.database, @tagName(environment));
|
||||||
const Action = enum { migrate, rollback, create, drop, reflect };
|
const Action = enum { migrate, rollback, create, drop, reflect, setup, update };
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
@ -46,6 +46,8 @@ pub fn main() !void {
|
|||||||
.{ "create", .create },
|
.{ "create", .create },
|
||||||
.{ "drop", .drop },
|
.{ "drop", .drop },
|
||||||
.{ "reflect", .reflect },
|
.{ "reflect", .reflect },
|
||||||
|
.{ "setup", .setup },
|
||||||
|
.{ "update", .update },
|
||||||
});
|
});
|
||||||
const action = map.get(args[1]) orelse return error.JetzigUnrecognizedArgument;
|
const action = map.get(args[1]) orelse return error.JetzigUnrecognizedArgument;
|
||||||
|
|
||||||
@ -77,6 +79,25 @@ pub fn main() !void {
|
|||||||
defer repo.deinit();
|
defer repo.deinit();
|
||||||
try repo.createDatabase(database, .{});
|
try repo.createDatabase(database, .{});
|
||||||
},
|
},
|
||||||
|
.setup => {
|
||||||
|
{
|
||||||
|
var repo = try migrationsRepo(.create, allocator, repo_env);
|
||||||
|
defer repo.deinit();
|
||||||
|
try repo.createDatabase(database, .{});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var repo = try migrationsRepo(.update, allocator, repo_env);
|
||||||
|
defer repo.deinit();
|
||||||
|
try Migrate(config.adapter).init(&repo).migrate();
|
||||||
|
try reflectSchema(allocator, repo_env);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.update => {
|
||||||
|
var repo = try migrationsRepo(action, allocator, repo_env);
|
||||||
|
defer repo.deinit();
|
||||||
|
try Migrate(config.adapter).init(&repo).migrate();
|
||||||
|
try reflectSchema(allocator, repo_env);
|
||||||
|
},
|
||||||
.drop => {
|
.drop => {
|
||||||
if (environment == .production) {
|
if (environment == .production) {
|
||||||
const confirm = std.process.getEnvVarOwned(allocator, confirm_drop_env) catch |err| {
|
const confirm = std.process.getEnvVarOwned(allocator, confirm_drop_env) catch |err| {
|
||||||
@ -103,33 +124,7 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.reflect => {
|
.reflect => {
|
||||||
var cwd = try jetzig.util.detectJetzigProjectDir();
|
try reflectSchema(allocator, repo_env);
|
||||||
defer cwd.close();
|
|
||||||
|
|
||||||
const Repo = jetquery.Repo(config.adapter, Schema);
|
|
||||||
var repo = try Repo.loadConfig(
|
|
||||||
allocator,
|
|
||||||
std.enums.nameCast(jetquery.Environment, environment),
|
|
||||||
.{ .context = .migration, .env = repo_env },
|
|
||||||
);
|
|
||||||
const reflect = @import("jetquery_reflect").Reflect(config.adapter, Schema).init(
|
|
||||||
allocator,
|
|
||||||
&repo,
|
|
||||||
.{
|
|
||||||
.import_jetquery =
|
|
||||||
\\@import("jetzig").jetquery
|
|
||||||
,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const schema = try reflect.generateSchema();
|
|
||||||
const project_dir = try jetzig.util.detectJetzigProjectDir();
|
|
||||||
const project_dir_realpath = try project_dir.realpathAlloc(allocator, ".");
|
|
||||||
const path = try std.fs.path.join(
|
|
||||||
allocator,
|
|
||||||
&.{ project_dir_realpath, "src", "app", "database", "Schema.zig" },
|
|
||||||
);
|
|
||||||
try jetzig.util.createFile(path, schema);
|
|
||||||
std.log.info("Database schema written to `{s}`.", .{path});
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,12 +136,43 @@ fn migrationsRepo(action: Action, allocator: std.mem.Allocator, repo_env: anytyp
|
|||||||
std.enums.nameCast(jetquery.Environment, environment),
|
std.enums.nameCast(jetquery.Environment, environment),
|
||||||
.{
|
.{
|
||||||
.admin = switch (action) {
|
.admin = switch (action) {
|
||||||
.migrate, .rollback => false,
|
.migrate, .rollback, .update => false,
|
||||||
.create, .drop => true,
|
.create, .drop => true,
|
||||||
.reflect => unreachable, // We use a separate repo for schema reflection.
|
.reflect => unreachable, // We use a separate repo for schema reflection.
|
||||||
|
.setup => unreachable, // Setup uses `create` and then `update`
|
||||||
},
|
},
|
||||||
.context = .migration,
|
.context = .migration,
|
||||||
.env = repo_env,
|
.env = repo_env,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reflectSchema(allocator: std.mem.Allocator, repo_env: anytype) !void {
|
||||||
|
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, .env = repo_env },
|
||||||
|
);
|
||||||
|
const reflect = @import("jetquery_reflect").Reflect(config.adapter, Schema).init(
|
||||||
|
allocator,
|
||||||
|
&repo,
|
||||||
|
.{
|
||||||
|
.import_jetquery =
|
||||||
|
\\@import("jetzig").jetquery
|
||||||
|
,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const schema = try reflect.generateSchema();
|
||||||
|
const project_dir = try jetzig.util.detectJetzigProjectDir();
|
||||||
|
const project_dir_realpath = try project_dir.realpathAlloc(allocator, ".");
|
||||||
|
const path = try std.fs.path.join(
|
||||||
|
allocator,
|
||||||
|
&.{ project_dir_realpath, "src", "app", "database", "Schema.zig" },
|
||||||
|
);
|
||||||
|
try jetzig.util.createFile(path, schema);
|
||||||
|
std.log.info("Database schema written to `{s}`.", .{path});
|
||||||
|
}
|
||||||
|
@ -6,11 +6,15 @@ const jetzig = @import("../../jetzig.zig");
|
|||||||
const buffer_size = jetzig.config.get(usize, "log_message_buffer_len");
|
const buffer_size = jetzig.config.get(usize, "log_message_buffer_len");
|
||||||
const max_pool_len = jetzig.config.get(usize, "max_log_pool_len");
|
const max_pool_len = jetzig.config.get(usize, "max_log_pool_len");
|
||||||
|
|
||||||
const List = std.DoublyLinkedList(Event);
|
const List = std.DoublyLinkedList;
|
||||||
|
const ListNode = struct {
|
||||||
|
event: Event,
|
||||||
|
node: std.DoublyLinkedList.Node = .{},
|
||||||
|
};
|
||||||
const Buffer = [buffer_size]u8;
|
const Buffer = [buffer_size]u8;
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
node_allocator: std.heap.MemoryPool(List.Node),
|
node_allocator: std.heap.MemoryPool(ListNode),
|
||||||
buffer_allocator: std.heap.MemoryPool(Buffer),
|
buffer_allocator: std.heap.MemoryPool(Buffer),
|
||||||
list: List,
|
list: List,
|
||||||
read_write_mutex: std.Thread.Mutex,
|
read_write_mutex: std.Thread.Mutex,
|
||||||
@ -18,7 +22,7 @@ condition: std.Thread.Condition,
|
|||||||
condition_mutex: std.Thread.Mutex,
|
condition_mutex: std.Thread.Mutex,
|
||||||
writer: Writer = undefined,
|
writer: Writer = undefined,
|
||||||
reader: Reader = undefined,
|
reader: Reader = undefined,
|
||||||
node_pool: std.ArrayList(*List.Node),
|
node_pool: std.ArrayList(*ListNode),
|
||||||
buffer_pool: std.ArrayList(*Buffer),
|
buffer_pool: std.ArrayList(*Buffer),
|
||||||
position: usize,
|
position: usize,
|
||||||
stdout_is_tty: bool = undefined,
|
stdout_is_tty: bool = undefined,
|
||||||
@ -42,13 +46,13 @@ const Event = struct {
|
|||||||
pub fn init(allocator: std.mem.Allocator) LogQueue {
|
pub fn init(allocator: std.mem.Allocator) LogQueue {
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.node_allocator = initPool(allocator, List.Node),
|
.node_allocator = initPool(allocator, ListNode),
|
||||||
.buffer_allocator = initPool(allocator, Buffer),
|
.buffer_allocator = initPool(allocator, Buffer),
|
||||||
.list = List{},
|
.list = List{},
|
||||||
.condition = std.Thread.Condition{},
|
.condition = std.Thread.Condition{},
|
||||||
.condition_mutex = std.Thread.Mutex{},
|
.condition_mutex = std.Thread.Mutex{},
|
||||||
.read_write_mutex = std.Thread.Mutex{},
|
.read_write_mutex = std.Thread.Mutex{},
|
||||||
.node_pool = std.ArrayList(*List.Node).init(allocator),
|
.node_pool = std.ArrayList(*ListNode).init(allocator),
|
||||||
.buffer_pool = std.ArrayList(*Buffer).init(allocator),
|
.buffer_pool = std.ArrayList(*Buffer).init(allocator),
|
||||||
.position = 0,
|
.position = 0,
|
||||||
};
|
};
|
||||||
@ -237,8 +241,8 @@ fn append(self: *LogQueue, event: Event) !void {
|
|||||||
|
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
node.* = .{ .data = event };
|
node.* = .{ .event = event };
|
||||||
self.list.append(node);
|
self.list.append(&node.node);
|
||||||
|
|
||||||
self.condition.signal();
|
self.condition.signal();
|
||||||
}
|
}
|
||||||
@ -249,16 +253,17 @@ fn popFirst(self: *LogQueue) !?Event {
|
|||||||
defer self.read_write_mutex.unlock();
|
defer self.read_write_mutex.unlock();
|
||||||
|
|
||||||
if (self.list.popFirst()) |node| {
|
if (self.list.popFirst()) |node| {
|
||||||
const value = node.data;
|
const list_node: *ListNode = @fieldParentPtr("node", node);
|
||||||
|
const value = list_node.event;
|
||||||
self.position -= 1;
|
self.position -= 1;
|
||||||
if (self.position < self.node_pool.items.len) {
|
if (self.position < self.node_pool.items.len) {
|
||||||
self.node_pool.items[self.position] = node;
|
self.node_pool.items[self.position] = list_node;
|
||||||
} else {
|
} else {
|
||||||
if (self.node_pool.items.len >= max_pool_len) {
|
if (self.node_pool.items.len >= max_pool_len) {
|
||||||
self.node_allocator.destroy(node);
|
self.node_allocator.destroy(list_node);
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
} else {
|
} else {
|
||||||
try self.node_pool.append(node);
|
try self.node_pool.append(list_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user