mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 22:16:08 +00:00
Allow mailers to modify mail template params
Remove need to add all mail template params to view response data. This was originally intended functionality but the wrong value was passed to the `deliver` function, and no `data` argument was given, making it cumbersome to create new values.
This commit is contained in:
parent
40093f3ec2
commit
65edd20092
@ -7,8 +7,8 @@
|
||||
.hash = "1220482f07f2bbaef335f20d6890c15a1e14739950b784232bc69182423520e058a5",
|
||||
},
|
||||
.zmpl = .{
|
||||
.url = "https://github.com/jetzig-framework/zmpl/archive/4457eba50bd2eff3743601aa00adbffebcd4207a.tar.gz",
|
||||
.hash = "122001d661e534ef59fc20936330bb0c3068c8aaf1b7c60f9dde9e58d9a536918754",
|
||||
.url = "https://github.com/jetzig-framework/zmpl/archive/c14683521ca48c1de0a9b2d61dfb145e1bc4dac1.tar.gz",
|
||||
.hash = "122093b741ef4aff151e916fc6005cb0c2aed747a34b77c0d4b45099ea2b561df9c7",
|
||||
},
|
||||
.jetkv = .{
|
||||
.url = "https://github.com/jetzig-framework/jetkv/archive/edfda9108c857dd5a04f87ae48667d3ed57612d9.tar.gz",
|
||||
|
@ -8,7 +8,7 @@ const util = @import("../util.zig");
|
||||
/// Command line options for the `bundle` command.
|
||||
pub const Options = struct {
|
||||
optimize: enum { Debug, ReleaseFast, ReleaseSmall } = .ReleaseFast,
|
||||
arch: enum { x86_64, aarch64, default } = .default,
|
||||
arch: enum { x86, x86_64, aarch64, default } = .default,
|
||||
os: enum { linux, macos, windows, default } = .default,
|
||||
|
||||
pub const meta = .{
|
||||
@ -190,6 +190,7 @@ fn zig_build_install(allocator: std.mem.Allocator, path: []const u8, options: Op
|
||||
|
||||
try target_buf.append("-Dtarget=");
|
||||
switch (options.arch) {
|
||||
.x86 => try target_buf.append("x86"),
|
||||
.x86_64 => try target_buf.append("x86_64"),
|
||||
.aarch64 => try target_buf.append("aarch64"),
|
||||
.default => try target_buf.append(@tagName(builtin.cpu.arch)),
|
||||
|
@ -51,7 +51,7 @@ pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, he
|
||||
\\// * env: Provides the following fields:
|
||||
\\// - logger: Logger attached to the same stream as the Jetzig server.
|
||||
\\// - environment: Enum of `{ production, development }`.
|
||||
\\pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, logger: jetzig.Logger) !void {
|
||||
\\pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, env: jetzig.jobs.JobEnv) !void {
|
||||
\\ _ = allocator;
|
||||
\\ _ = params;
|
||||
\\ // Job execution code goes here. Add any code that you would like to run in the background.
|
||||
|
@ -39,45 +39,34 @@ pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, he
|
||||
};
|
||||
|
||||
try mailer_file.writeAll(
|
||||
\\const std = @import("std");
|
||||
\\const jetzig = @import("jetzig");
|
||||
\\
|
||||
\\// Default values for this mailer.
|
||||
\\pub const defaults: jetzig.mail.DefaultMailParams = .{
|
||||
\\ .from = "no-reply@example.com",
|
||||
\\ .subject = "Default subject",
|
||||
\\};
|
||||
\\
|
||||
\\// The `deliver` function is invoked every time this mailer is used to send an email.
|
||||
\\// Use this function to modify mail parameters before the mail is delivered, or simply
|
||||
\\// to log all uses of this mailer.
|
||||
\\// Use this function to set default mail params (e.g. a default `from` address or
|
||||
\\// `subject`) before the mail is delivered.
|
||||
\\//
|
||||
\\// To use this mailer from a request:
|
||||
\\// ```
|
||||
\\// const mail = request.mail("<mailer-name>", .{ .to = &.{"user@example.com"} });
|
||||
\\// try mail.deliver(.background, .{});
|
||||
\\// ```
|
||||
\\// A mailer can provide two Zmpl templates for rendering email content:
|
||||
\\// * `src/app/mailers/<mailer-name>/html.zmpl
|
||||
\\// * `src/app/mailers/<mailer-name>/text.zmpl
|
||||
\\//
|
||||
\\// Arguments:
|
||||
\\// * allocator: Arena allocator for use during the mail delivery process.
|
||||
\\// * mail: Mail parameters. Inspect or override any values assigned when the mail was created.
|
||||
\\// * params: Params assigned to a mail (from a request, any values added to `data`). Params
|
||||
\\// can be modified before email delivery.
|
||||
\\// * mail: Mail parameters (from, to, subject, etc.). Inspect or override any values
|
||||
\\// assigned when the mail was created.
|
||||
\\// * data: Provides `data.string()` etc. for generating Jetzig Values.
|
||||
\\// * params: Template data for `text.zmpl` and `html.zmpl`. Inherits all response data
|
||||
\\// assigned in a view function and can be modified for email-specific content.
|
||||
\\// * env: Provides the following fields:
|
||||
\\// - logger: Logger attached to the same stream as the Jetzig server.
|
||||
\\// - environment: Enum of `{ production, development }`.
|
||||
\\pub fn deliver(
|
||||
\\ allocator: std.mem.Allocator,
|
||||
\\ mail: *jetzig.mail.MailParams,
|
||||
\\ data: *jetzig.data.Data,
|
||||
\\ params: *jetzig.data.Value,
|
||||
\\ env: jetzig.jobs.JobEnv,
|
||||
\\) !void {
|
||||
\\ _ = allocator;
|
||||
\\ _ = data;
|
||||
\\ _ = params;
|
||||
\\
|
||||
\\ try env.logger.INFO("Delivering email with subject: '{?s}'", .{mail.get(.subject)});
|
||||
\\}
|
||||
\\
|
||||
|
@ -17,20 +17,23 @@ pub const defaults: jetzig.mail.DefaultMailParams = .{
|
||||
//
|
||||
// Arguments:
|
||||
// * allocator: Arena allocator for use during the mail delivery process.
|
||||
// * mail: Mail parameters. Inspect or override any values assigned when the mail was created.
|
||||
// * params: Params assigned to a mail (from a request, any values added to `data`). Params
|
||||
// can be modified before email delivery.
|
||||
// * mail: Mail parameters (from, to, subject, etc.). Inspect or override any values
|
||||
// assigned when the mail was created.
|
||||
// * data: Provides `data.string()` etc. for generating Jetzig Values.
|
||||
// * params: Template data for `text.zmpl` and `html.zmpl`. Inherits all response data
|
||||
// assigned in a view function and can be modified for email-specific content.
|
||||
// * env: Provides the following fields:
|
||||
// - logger: Logger attached to the same stream as the Jetzig server.
|
||||
// - environment: Enum of `{ production, development }`.
|
||||
pub fn deliver(
|
||||
allocator: std.mem.Allocator,
|
||||
mail: *jetzig.mail.MailParams,
|
||||
data: *jetzig.data.Data,
|
||||
params: *jetzig.data.Value,
|
||||
env: jetzig.jobs.JobEnv,
|
||||
) !void {
|
||||
_ = allocator;
|
||||
_ = params;
|
||||
try params.put("email_message", data.string("Custom email message"));
|
||||
|
||||
try env.logger.INFO("Delivering email with subject: '{?s}'", .{mail.get(.subject)});
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
<div>{{.message}}</div>
|
||||
<div>{{.email_message}}</div>
|
||||
|
@ -1 +1,3 @@
|
||||
{{.message}}
|
||||
|
||||
{{.email_message}}
|
||||
|
@ -3,18 +3,14 @@ const jetzig = @import("jetzig");
|
||||
|
||||
/// This example demonstrates usage of Jetzig's background jobs.
|
||||
pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||
|
||||
// Create a new job using `src/app/jobs/example_job.zig`.
|
||||
// Prepare a job using `src/app/jobs/example.zig`.
|
||||
var job = try request.job("example");
|
||||
|
||||
// Add a param `foo` to the job.
|
||||
try job.params.put("foo", data.string("bar"));
|
||||
try job.params.put("id", data.integer(std.crypto.random.int(u32)));
|
||||
|
||||
// Schedule the job for background processing. The job is added to the queue. When the job is
|
||||
// processed a new instance of `example_job` is created and its `run` function is invoked.
|
||||
// All params are added above are available to the job by calling `job.params()` inside the
|
||||
// `run` function.
|
||||
// Schedule the job for background processing.
|
||||
try job.schedule();
|
||||
|
||||
return request.render(.ok);
|
||||
|
@ -3,7 +3,7 @@ const jetzig = @import("jetzig");
|
||||
|
||||
pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||
var root = try data.object();
|
||||
try root.put("cached_value", try request.cache.get("example"));
|
||||
try root.put("message", try request.cache.get("message"));
|
||||
|
||||
return request.render(.ok);
|
||||
}
|
||||
|
2
demo/src/app/views/cache/index.zmpl
vendored
2
demo/src/app/views/cache/index.zmpl
vendored
@ -1,3 +1,3 @@
|
||||
<div>
|
||||
<span>Cached value: {{.cached_value}}</span>
|
||||
<span>Cached value: {{.message}}</span>
|
||||
</div>
|
||||
|
@ -6,23 +6,25 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||
|
||||
// Fetch a string from the KV store. If it exists, store it in the root data object,
|
||||
// otherwise store a string value to be picked up by the next request.
|
||||
if (try request.store.fetchRemove("example-key")) |capture| {
|
||||
if (try request.store.get("example-key")) |capture| {
|
||||
try root.put("stored_string", capture);
|
||||
} else {
|
||||
try root.put("stored_string", null);
|
||||
try request.store.put("example-key", data.string("example-value"));
|
||||
}
|
||||
|
||||
// Left-pop an item from the array and store it in the root data object. This will empty the
|
||||
// Left-pop an item from an array and store it in the root data object. This will empty the
|
||||
// array after multiple requests.
|
||||
// If the array is empty or not found, append some new values to the array.
|
||||
if (try request.store.popFirst("example-array")) |value| {
|
||||
try root.put("popped", value);
|
||||
} else {
|
||||
try root.put("popped", null);
|
||||
// Store some values in an array in the KV store.
|
||||
try request.store.append("example-array", data.string("hello"));
|
||||
try request.store.append("example-array", data.string("goodbye"));
|
||||
try request.store.append("example-array", data.string("hello again"));
|
||||
|
||||
try root.put("popped", null);
|
||||
}
|
||||
|
||||
return request.render(.ok);
|
||||
|
@ -1,3 +1,4 @@
|
||||
<div>
|
||||
<span>Your email has been sent!</span>
|
||||
<div>{{.message}}</div>
|
||||
</div>
|
||||
|
@ -1 +0,0 @@
|
||||
<div>{{.data.test}}</div>
|
@ -1 +0,0 @@
|
||||
{{.data.test}}
|
@ -1 +0,0 @@
|
||||
<div>Hello</div>
|
@ -31,55 +31,55 @@ redirected: bool = false,
|
||||
rendered_multiple: bool = false,
|
||||
rendered_view: ?jetzig.views.View = null,
|
||||
start_time: i128,
|
||||
store: ArenaStore,
|
||||
cache: ArenaStore,
|
||||
store: RequestStore,
|
||||
cache: RequestStore,
|
||||
|
||||
/// Wrapper for KV store that uses the request's arena allocator for fetching values.
|
||||
pub const ArenaStore = struct {
|
||||
pub const RequestStore = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
store: *jetzig.kv.Store,
|
||||
|
||||
/// Put a String or into the key-value store.
|
||||
pub fn get(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
||||
pub fn get(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||
return try self.store.get(try self.data(), key);
|
||||
}
|
||||
|
||||
/// Get a String from the store.
|
||||
pub fn put(self: ArenaStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||
pub fn put(self: RequestStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||
try self.store.put(key, value);
|
||||
}
|
||||
|
||||
/// Remove a String to from the key-value store and return it if found.
|
||||
pub fn fetchRemove(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
||||
pub fn fetchRemove(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||
return try self.store.fetchRemove(try self.data(), key);
|
||||
}
|
||||
|
||||
/// Remove a String to from the key-value store.
|
||||
pub fn remove(self: ArenaStore, key: []const u8) !void {
|
||||
pub fn remove(self: RequestStore, key: []const u8) !void {
|
||||
try self.store.remove(key);
|
||||
}
|
||||
|
||||
/// Append a Value to the end of an Array in the key-value store.
|
||||
pub fn append(self: ArenaStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||
pub fn append(self: RequestStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||
try self.store.append(key, value);
|
||||
}
|
||||
|
||||
/// Prepend a Value to the start of an Array in the key-value store.
|
||||
pub fn prepend(self: ArenaStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||
pub fn prepend(self: RequestStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||
try self.store.prepend(key, value);
|
||||
}
|
||||
|
||||
/// Pop a String from an Array in the key-value store.
|
||||
pub fn pop(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
||||
pub fn pop(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||
return try self.store.pop(try self.data(), key);
|
||||
}
|
||||
|
||||
/// Left-pop a String from an Array in the key-value store.
|
||||
pub fn popFirst(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
||||
pub fn popFirst(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||
return try self.store.popFirst(try self.data(), key);
|
||||
}
|
||||
|
||||
fn data(self: ArenaStore) !*jetzig.data.Data {
|
||||
fn data(self: RequestStore) !*jetzig.data.Data {
|
||||
const arena_data = try self.allocator.create(jetzig.data.Data);
|
||||
arena_data.* = jetzig.data.Data.init(self.allocator);
|
||||
return arena_data;
|
||||
@ -390,7 +390,10 @@ const RequestMail = struct {
|
||||
const text = if (self.mail_params.text) |text| mail_job.data.string(text) else null;
|
||||
try mail_job.params.put("text", text);
|
||||
|
||||
if (self.request.response_data.value) |value| try mail_job.params.put("params", value);
|
||||
if (self.request.response_data.value) |value| try mail_job.params.put(
|
||||
"params",
|
||||
if (strategy == .now) try value.clone(self.request.allocator) else value,
|
||||
);
|
||||
|
||||
switch (strategy) {
|
||||
.background => try mail_job.schedule(),
|
||||
|
@ -7,14 +7,24 @@ pub const JobDefinition = struct {
|
||||
runFn: *const fn (std.mem.Allocator, *jetzig.data.Value, JobEnv) anyerror!void,
|
||||
};
|
||||
|
||||
/// Environment passed to all jobs.
|
||||
pub const JobEnv = struct {
|
||||
/// The Jetzig server logger
|
||||
logger: jetzig.loggers.Logger,
|
||||
/// The current server environment, `enum { development, production }`
|
||||
environment: jetzig.Environment.EnvironmentName,
|
||||
/// All routes detected by Jetzig on startup
|
||||
routes: []*const jetzig.Route,
|
||||
/// All mailers detected by Jetzig on startup
|
||||
mailers: []const jetzig.MailerDefinition,
|
||||
/// All jobs detected by Jetzig on startup
|
||||
jobs: []const jetzig.JobDefinition,
|
||||
/// Global key-value store
|
||||
store: *jetzig.kv.Store,
|
||||
/// Global cache
|
||||
cache: *jetzig.kv.Store,
|
||||
/// Global mutex - use with caution if it is necessary to guarantee thread safety/consistency
|
||||
/// between concurrent job workers
|
||||
mutex: *std.Thread.Mutex,
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,9 @@ pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, env: jetzig
|
||||
.defaults = mailer.defaults,
|
||||
};
|
||||
|
||||
try mailer.deliverFn(allocator, &mail_params, params, env);
|
||||
var data = jetzig.data.Data.init(allocator);
|
||||
|
||||
try mailer.deliverFn(allocator, &mail_params, &data, params.get("params").?, env);
|
||||
|
||||
const mail = jetzig.mail.Mail.init(allocator, .{
|
||||
.subject = mail_params.get(.subject) orelse "(No subject)",
|
||||
|
@ -4,6 +4,7 @@ const jetzig = @import("../../jetzig.zig");
|
||||
pub const DeliverFn = *const fn (
|
||||
std.mem.Allocator,
|
||||
*jetzig.mail.MailParams,
|
||||
*jetzig.data.Data,
|
||||
*jetzig.data.Value,
|
||||
jetzig.jobs.JobEnv,
|
||||
) anyerror!void;
|
||||
|
Loading…
x
Reference in New Issue
Block a user