Current section
Files
Jump to
Current section
Files
src/refrakt@cli@templates.erl
-module(refrakt@cli@templates).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/refrakt/cli/templates.gleam").
-export([gleam_toml/2, gitignore/0, readme/1, main_module/2, config_module/1, context_module/2, router_module/2, home_handler/1, error_handler/1, root_layout/0, flash_component/0, repo_module/2, app_css/0, app_js/0, main_test/1, home_handler_test/1, resource_handler/6, resource_domain_type/2]).
-file("src/refrakt/cli/templates.gleam", 13).
-spec gleam_toml(binary(), refrakt@cli@types:db_choice()) -> binary().
gleam_toml(Name, Db) ->
Db_dep = case Db of
postgres ->
<<"\npog = \">= 4.1.0 and < 5.0.0\""/utf8>>;
sqlite ->
<<"\nsqlight = \">= 1.0.0 and < 2.0.0\""/utf8>>;
no_db ->
<<""/utf8>>
end,
<<<<<<<<"name = \""/utf8, Name/binary>>/binary,
"\"
version = \"0.1.0\"
target = \"erlang\"
gleam = \">= 1.14.0\"
[dependencies]
gleam_stdlib = \">= 0.44.0 and < 2.0.0\"
gleam_erlang = \">= 0.34.0 and < 2.0.0\"
gleam_http = \">= 4.3.0 and < 5.0.0\"
envoy = \">= 1.1.0 and < 2.0.0\"
mist = \">= 5.0.0 and < 6.0.0\"
wisp = \">= 2.2.0 and < 3.0.0\"
lustre = \">= 5.6.0 and < 6.0.0\"
gleam_json = \">= 3.1.0 and < 4.0.0\"
refrakt = \">= 0.1.0 and < 1.0.0\""/utf8>>/binary,
Db_dep/binary>>/binary,
"
[dev-dependencies]
gleeunit = \">= 1.0.0 and < 2.0.0\"
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 41).
-spec gitignore() -> binary().
gitignore() ->
<<"/build/
.DS_Store
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 47).
-spec readme(binary()) -> binary().
readme(Name) ->
<<<<"# "/utf8, Name/binary>>/binary,
"
A web application built with [Refrakt](https://github.com/raskell-io/refrakt).
## Development
```bash
gleam run # Start the server at http://localhost:4000
gleam test # Run tests
```
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 65).
-spec main_module(binary(), refrakt@cli@types:db_choice()) -> binary().
main_module(Name, Db) ->
Db_import = case Db of
postgres ->
<<<<"\nimport "/utf8, Name/binary>>/binary, "/data/repo"/utf8>>;
sqlite ->
<<<<"\nimport "/utf8, Name/binary>>/binary, "/data/repo"/utf8>>;
no_db ->
<<""/utf8>>
end,
Db_ctx = case Db of
postgres ->
<<"\n let assert Ok(db) = repo.connect(cfg)\n let ctx = context.Context(config: cfg, db: db)"/utf8>>;
sqlite ->
<<"\n let db_path = repo.database_path(cfg)\n let ctx = context.Context(config: cfg, db_path: db_path)"/utf8>>;
no_db ->
<<"\n let ctx = context.Context(config: cfg)"/utf8>>
end,
<<<<<<<<<<<<<<<<<<<<"import gleam/erlang/process
import gleam/io
import mist
import "/utf8,
Name/binary>>/binary,
"/config
import "/utf8>>/binary,
Name/binary>>/binary,
"/context
import "/utf8>>/binary,
Name/binary>>/binary,
"/router
import wisp
import wisp/wisp_mist"/utf8>>/binary,
Db_import/binary>>/binary,
"
pub fn main() {
wisp.configure_logger()
let cfg = config.load()"/utf8>>/binary,
Db_ctx/binary>>/binary,
"
let assert Ok(_) =
wisp_mist.handler(router.handle_request(_, ctx), cfg.secret_key_base)
|> mist.new
|> mist.port(cfg.port)
|> mist.start
io.println(\"Listening on http://localhost:\" <> cfg.port_string)
process.sleep_forever()
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 106).
-spec config_module(binary()) -> binary().
config_module(_) ->
<<"import envoy
import gleam/int
import gleam/result
pub type Config {
Config(
port: Int,
port_string: String,
secret_key_base: String,
env: Env,
)
}
pub type Env {
Dev
Test
Prod
}
pub fn load() -> Config {
let port =
envoy.get(\"PORT\")
|> result.try(int.parse)
|> result.unwrap(4000)
let secret_key_base =
envoy.get(\"SECRET_KEY_BASE\")
|> result.unwrap(
\"dev-secret-key-base-that-is-at-least-64-bytes-long-for-security!!\",
)
let env = case envoy.get(\"APP_ENV\") {
Ok(\"prod\") -> Prod
Ok(\"test\") -> Test
_ -> Dev
}
Config(
port: port,
port_string: int.to_string(port),
secret_key_base: secret_key_base,
env: env,
)
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 154).
-spec context_module(binary(), refrakt@cli@types:db_choice()) -> binary().
context_module(Name, Db) ->
Db_field = case Db of
postgres ->
<<", db: pog.Connection"/utf8>>;
sqlite ->
<<", db_path: String"/utf8>>;
no_db ->
<<""/utf8>>
end,
Db_import = case Db of
postgres ->
<<"\nimport pog"/utf8>>;
_ ->
<<""/utf8>>
end,
<<<<<<<<<<<<"import "/utf8, Name/binary>>/binary, "/config"/utf8>>/binary,
Db_import/binary>>/binary,
"
pub type Context {
Context(config: config.Config"/utf8>>/binary,
Db_field/binary>>/binary,
")
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 174).
-spec router_module(binary(), refrakt@cli@types:db_choice()) -> binary().
router_module(Name, _) ->
<<<<<<<<<<<<<<<<"import gleam/http
import "/utf8, Name/binary>>/binary,
"/context.{type Context}
import "/utf8>>/binary,
Name/binary>>/binary,
"/web/error_handler
import "/utf8>>/binary,
Name/binary>>/binary,
"/web/home_handler
import wisp.{type Request, type Response}
pub fn handle_request(req: Request, ctx: Context) -> Response {
use req <- middleware(req)
case wisp.path_segments(req), req.method {
[], http.Get -> home_handler.index(req, ctx)
_, _ -> error_handler.not_found(req)
}
}
fn middleware(
req: Request,
next: fn(Request) -> Response,
) -> Response {
let req = wisp.method_override(req)
use <- wisp.log_request(req)
use <- wisp.rescue_crashes
use <- wisp.serve_static(req, under: \"/static\", from: priv_static())
next(req)
}
fn priv_static() -> String {
let assert Ok(priv) = wisp.priv_directory(\""/utf8>>/binary,
Name/binary>>/binary,
"\")
priv <> \"/static\"
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 208).
-spec home_handler(binary()) -> binary().
home_handler(Name) ->
<<<<<<<<<<<<"import lustre/attribute.{class}
import lustre/element.{text}
import lustre/element/html.{h1, p, section}
import "/utf8,
Name/binary>>/binary,
"/context.{type Context}
import "/utf8>>/binary,
Name/binary>>/binary,
"/web/layouts/root_layout
import wisp.{type Request, type Response}
pub fn index(_req: Request, _ctx: Context) -> Response {
section([class(\"hero\")], [
h1([], [text(\"Welcome to "/utf8>>/binary,
Name/binary>>/binary,
"\")]),
p([], [text(\"Built with Refrakt — a convention-first web framework for Gleam.\")]),
])
|> root_layout.wrap(\"Home\")
|> wisp.html_response(200)
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 227).
-spec error_handler(binary()) -> binary().
error_handler(_) ->
<<"import lustre/attribute.{class}
import lustre/element.{text}
import lustre/element/html.{h1, p, section}
import wisp.{type Request, type Response}
pub fn not_found(_req: Request) -> Response {
section([class(\"error-page\")], [
h1([], [text(\"404\")]),
p([], [text(\"Page not found.\")]),
])
|> element.to_string
|> wisp.html_response(404)
}
pub fn internal_error(_req: Request) -> Response {
section([class(\"error-page\")], [
h1([], [text(\"500\")]),
p([], [text(\"Something went wrong.\")]),
])
|> element.to_string
|> wisp.html_response(500)
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 253).
-spec root_layout() -> binary().
root_layout() ->
<<"import lustre/attribute.{charset, class, content, href, name, rel}
import lustre/element.{type Element}
import lustre/element/html.{body, head, html, link, main, meta, title}
pub fn wrap(inner: Element(Nil), page_title: String) -> String {
html([], [
head([], [
meta([charset(\"utf-8\")]),
meta([name(\"viewport\"), content(\"width=device-width, initial-scale=1\")]),
title([], page_title),
link([rel(\"stylesheet\"), href(\"/static/css/app.css\")]),
]),
body([], [main([class(\"container\")], [inner])]),
])
|> element.to_document_string
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 273).
-spec flash_component() -> binary().
flash_component() ->
<<"import lustre/attribute.{class}
import lustre/element.{type Element, text}
import lustre/element/html.{div, p}
import gleam/option.{type Option, None, Some}
pub fn render(message: Option(String)) -> Element(Nil) {
case message {
Some(msg) ->
div([class(\"flash\")], [
p([], [text(msg)]),
])
None -> text(\"\")
}
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 291).
-spec repo_module(binary(), refrakt@cli@types:db_choice()) -> binary().
repo_module(Name, Db) ->
case Db of
postgres ->
<<<<<<<<<<<<<<<<"import "/utf8, Name/binary>>/binary,
"/config.{type Config}
import gleam/erlang/process
import gleam/result
import pog
pub fn connect(cfg: Config) -> Result(pog.Connection, Nil) {
let db_url = case cfg.env {
config.Test -> \"postgres://localhost:5432/"/utf8>>/binary,
Name/binary>>/binary,
"_test\"
_ -> \"postgres://localhost:5432/"/utf8>>/binary,
Name/binary>>/binary,
"_dev\"
}
let pool_name = process.new_name(prefix: \""/utf8>>/binary,
Name/binary>>/binary,
"_db\")
use db_config <- result.try(pog.url_config(pool_name, db_url))
case pog.start(db_config) {
Ok(_started) -> Ok(pog.named_connection(pool_name))
Error(_) -> Error(Nil)
}
}
"/utf8>>;
sqlite ->
<<<<<<<<"import "/utf8, Name/binary>>/binary,
"/config.{type Config}
/// Get the SQLite database path for the current environment.
pub fn database_path(cfg: Config) -> String {
case cfg.env {
config.Test -> \":memory:\"
_ -> \""/utf8>>/binary,
Name/binary>>/binary,
".db\"
}
}
"/utf8>>;
no_db ->
<<""/utf8>>
end.
-file("src/refrakt/cli/templates.gleam", 330).
-spec app_css() -> binary().
app_css() ->
<<"/* Refrakt default styles */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--font-sans: system-ui, -apple-system, sans-serif;
--font-mono: ui-monospace, \"Cascadia Code\", \"Fira Code\", monospace;
--color-bg: #fafafa;
--color-text: #1a1a1a;
--color-muted: #666;
--color-border: #e5e5e5;
--color-accent: #5b21b6;
--color-accent-light: #7c3aed;
--color-error: #dc2626;
--max-width: 48rem;
}
body {
font-family: var(--font-sans);
color: var(--color-text);
background: var(--color-bg);
line-height: 1.6;
}
.container {
max-width: var(--max-width);
margin: 0 auto;
padding: 2rem 1rem;
}
/* Hero */
.hero {
text-align: center;
padding: 4rem 0;
}
.hero h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.hero p {
color: var(--color-muted);
font-size: 1.125rem;
}
/* Links */
a {
color: var(--color-accent);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* Buttons */
.btn {
display: inline-block;
padding: 0.5rem 1rem;
background: var(--color-accent);
color: white;
border: none;
border-radius: 0.25rem;
font-size: 0.875rem;
cursor: pointer;
text-decoration: none;
}
.btn:hover {
background: var(--color-accent-light);
text-decoration: none;
}
/* Forms */
.field {
margin-bottom: 1rem;
}
.field label {
display: block;
font-weight: 500;
margin-bottom: 0.25rem;
}
.field input[type=\"text\"],
.field input[type=\"email\"],
.field input[type=\"password\"],
.field textarea,
.field select {
width: 100%;
padding: 0.5rem;
border: 1px solid var(--color-border);
border-radius: 0.25rem;
font-size: 1rem;
font-family: inherit;
}
.field textarea {
min-height: 8rem;
resize: vertical;
}
.field .error {
color: var(--color-error);
font-size: 0.875rem;
margin-top: 0.25rem;
}
/* Flash */
.flash {
padding: 0.75rem 1rem;
border-radius: 0.25rem;
background: #dbeafe;
border: 1px solid #93c5fd;
margin-bottom: 1rem;
}
/* Error pages */
.error-page {
text-align: center;
padding: 4rem 0;
}
.error-page h1 {
font-size: 4rem;
color: var(--color-muted);
}
/* Lists */
.post-list {
list-style: none;
}
.post-list li {
padding: 0.75rem 0;
border-bottom: 1px solid var(--color-border);
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.actions {
margin-top: 1.5rem;
display: flex;
gap: 0.5rem;
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 491).
-spec app_js() -> binary().
app_js() ->
<<"// Refrakt client-side JavaScript
// Add your client-side code here.
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 501).
-spec main_test(binary()) -> binary().
main_test(_) ->
<<"import gleeunit
pub fn main() {
gleeunit.main()
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 510).
-spec home_handler_test(binary()) -> binary().
home_handler_test(_) ->
<<"import gleeunit/should
pub fn placeholder_test() {
1 + 1
|> should.equal(2)
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 524).
-spec resource_handler(
binary(),
binary(),
binary(),
binary(),
binary(),
refrakt@cli@types:db_choice()
) -> binary().
resource_handler(App_name, Resource_plural, Resource_singular, Type_name, _, Db) ->
Db_arg = case Db of
sqlite ->
<<"ctx.db_path"/utf8>>;
_ ->
<<"ctx.db"/utf8>>
end,
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"import gleam/int
import "/utf8,
App_name/binary>>/binary,
"/context.{type Context}
import "/utf8>>/binary,
App_name/binary>>/binary,
"/data/"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo
import "/utf8>>/binary,
App_name/binary>>/binary,
"/web/error_handler
import "/utf8>>/binary,
App_name/binary>>/binary,
"/web/forms/"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form
import "/utf8>>/binary,
App_name/binary>>/binary,
"/web/layouts/root_layout
import "/utf8>>/binary,
App_name/binary>>/binary,
"/web/"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views
import refrakt/flash
import wisp.{type Request, type Response}
pub fn index(_req: Request, ctx: Context) -> Response {
let items = "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo.list("/utf8>>/binary,
Db_arg/binary>>/binary,
")
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views.index_view(items)
|> root_layout.wrap(\""/utf8>>/binary,
Type_name/binary>>/binary,
"s\")
|> wisp.html_response(200)
}
pub fn show(req: Request, ctx: Context, id: String) -> Response {
case int.parse(id) {
Error(_) -> error_handler.not_found(req)
Ok(id) ->
case "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo.get("/utf8>>/binary,
Db_arg/binary>>/binary,
", id) {
Error(_) -> error_handler.not_found(req)
Ok(item) ->
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views.show_view(item)
|> root_layout.wrap(\""/utf8>>/binary,
Type_name/binary>>/binary,
"\")
|> wisp.html_response(200)
}
}
}
pub fn new(_req: Request, _ctx: Context) -> Response {
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views.form_view("/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form.empty(), [])
|> root_layout.wrap(\"New "/utf8>>/binary,
Type_name/binary>>/binary,
"\")
|> wisp.html_response(200)
}
pub fn create(req: Request, ctx: Context) -> Response {
use form_data <- wisp.require_form(req)
case "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form.decode(form_data) {
Error(errors) ->
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views.form_view(
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form.from_form_data(form_data),
errors,
)
|> root_layout.wrap(\"New "/utf8>>/binary,
Type_name/binary>>/binary,
"\")
|> wisp.html_response(422)
Ok(params) ->
case "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo.create("/utf8>>/binary,
Db_arg/binary>>/binary,
", params) {
Ok(item) ->
wisp.redirect(\"/"/utf8>>/binary,
Resource_plural/binary>>/binary,
"/\" <> int.to_string(item.id))
|> flash.set_flash(req, \"info\", \""/utf8>>/binary,
Type_name/binary>>/binary,
" created\")
Error(_) -> error_handler.internal_error(req)
}
}
}
pub fn edit(req: Request, ctx: Context, id: String) -> Response {
case int.parse(id) {
Error(_) -> error_handler.not_found(req)
Ok(id) ->
case "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo.get("/utf8>>/binary,
Db_arg/binary>>/binary,
", id) {
Error(_) -> error_handler.not_found(req)
Ok(item) ->
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views.form_view("/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form.from_"/utf8>>/binary,
Resource_singular/binary>>/binary,
"(item), [])
|> root_layout.wrap(\"Edit "/utf8>>/binary,
Type_name/binary>>/binary,
"\")
|> wisp.html_response(200)
}
}
}
pub fn update(req: Request, ctx: Context, id: String) -> Response {
use form_data <- wisp.require_form(req)
case int.parse(id) {
Error(_) -> error_handler.not_found(req)
Ok(id) ->
case "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form.decode(form_data) {
Error(errors) ->
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_views.form_view(
"/utf8>>/binary,
Resource_singular/binary>>/binary,
"_form.from_form_data(form_data),
errors,
)
|> root_layout.wrap(\"Edit "/utf8>>/binary,
Type_name/binary>>/binary,
"\")
|> wisp.html_response(422)
Ok(params) ->
case "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo.update("/utf8>>/binary,
Db_arg/binary>>/binary,
", id, params) {
Ok(_) ->
wisp.redirect(\"/"/utf8>>/binary,
Resource_plural/binary>>/binary,
"/\" <> int.to_string(id))
|> flash.set_flash(req, \"info\", \""/utf8>>/binary,
Type_name/binary>>/binary,
" updated\")
Error(_) -> error_handler.internal_error(req)
}
}
}
}
pub fn delete(req: Request, ctx: Context, id: String) -> Response {
case int.parse(id) {
Error(_) -> error_handler.not_found(req)
Ok(id) -> {
let _ = "/utf8>>/binary,
Resource_singular/binary>>/binary,
"_repo.delete("/utf8>>/binary,
Db_arg/binary>>/binary,
", id)
wisp.redirect(\"/"/utf8>>/binary,
Resource_plural/binary>>/binary,
"\")
|> flash.set_flash(req, \"info\", \""/utf8>>/binary,
Type_name/binary>>/binary,
" deleted\")
}
}
}
"/utf8>>.
-file("src/refrakt/cli/templates.gleam", 702).
-spec do_list_reverse(list(AGIN), list(AGIN)) -> list(AGIN).
do_list_reverse(Items, Acc) ->
case Items of
[] ->
Acc;
[First | Rest] ->
do_list_reverse(Rest, [First | Acc])
end.
-file("src/refrakt/cli/templates.gleam", 698).
-spec list_reverse(list(AGIK)) -> list(AGIK).
list_reverse(Items) ->
do_list_reverse(Items, []).
-file("src/refrakt/cli/templates.gleam", 687).
-spec do_list_map_join(list(AGIG), fun((AGIG) -> binary()), list(binary())) -> list(binary()).
do_list_map_join(Items, F, Acc) ->
case Items of
[] ->
list_reverse(Acc);
[First | Rest] ->
do_list_map_join(Rest, F, [F(First) | Acc])
end.
-file("src/refrakt/cli/templates.gleam", 677).
-spec list_map_join(list(AGIE), fun((AGIE) -> binary()), binary()) -> binary().
list_map_join(Items, F, Separator) ->
_pipe = Items,
_pipe@1 = do_list_map_join(_pipe, F, []),
gleam@string:join(_pipe@1, Separator).
-file("src/refrakt/cli/templates.gleam", 650).
-spec resource_domain_type(binary(), list({binary(), binary()})) -> binary().
resource_domain_type(Type_name, Fields) ->
Field_defs = begin
_pipe = Fields,
list_map_join(
_pipe,
fun(Field) ->
{Name, Gleam_type} = Field,
<<<<<<<<" "/utf8, Name/binary>>/binary, ": "/utf8>>/binary,
Gleam_type/binary>>/binary,
","/utf8>>
end,
<<"\n"/utf8>>
)
end,
<<<<<<<<<<<<"pub type "/utf8, Type_name/binary>>/binary, " {
"/utf8>>/binary,
Type_name/binary>>/binary,
"(
id: Int,
"/utf8>>/binary,
Field_defs/binary>>/binary,
"
)
}
"/utf8>>.