Ch-ch-changes!
First, I want to give a shout out to
@goto-engineering for fixing the response duration logging code! @hammywhammy / @hweeks for all of the hard work on the docker/ci stuff!
- keyword routes
- default middleware function
- before/after functions
- a new, simpler starting template
Tired of having to define all of your routes in two different files, me too!
(route :get "/" :home)
(defn home [r])
This is how the new template works too:
(route :get "/todos" :todos/index)
(route :get "/todos/new" :todos/new)
(route :get "/todos/:id" :todos/show)
(route :post "/todos" :todos/create)
(route :get "/todos/:id/edit" :todos/edit)
(route :patch "/todos/:id" :todos/patch)
(route :delete "/todos/:id" :todos/delete)
You can imagine the corresponding functions.
Before:
(def routes (routes [:get "/" :home]))
(def app (as-> (handler routes) ?
(layout ? layout/app)
(csrf-token ?)
(session ?)
(extra-methods ?)
(query-string ?)
(body-parser ?)
(server-error ?)
(x-headers ?)
(static-files ?)
(not-found ?)
(logger ? )))
After:
(def routes (routes [:get "/" :home]))
(def app (app {:routes routes :layout layout-fn}))
You can also turn middleware on/off by changing the dictionary passed to app:
(app {:layout false :extra-methods false :session false :x-headers false :static-files false})
There are a few more options too like changing the cookie options for sessions, things like that.
Don't want to bother writing a whole middleware function just to append things to the request on certain routes? Me neither!
(before "/*" :run-before)
(defn run-before [req]
(put req :a 1))
You can use a combination of wildcard routes and the before function to modify the request dictionary before any matching routes. Make sure you return the request from your before functions.
Similarly, the after
function works the same way, except on the response, you also need to return the response as well.
.
├── Procfile
├── main.janet
├── project.janet
└── public
├── app.css
└── app.js
5 files with a Procfile! One thing I didn't add to the default template is a Dockerfile which I'm kind of fine tuning still, it works great with dokku!
That's it for now, there are a few more new things, but you can find me online anywhere or consult the docs if you want to know more
Warning Breaking changes ahead, only if you're using the css
, js
or app
functions
I try not to make too many breaking changes, but it's still early days and hopefully no one was using the js/css bundler stuff.
Also I don't plan on introducing breaking changes EVER after 1.0
In fact my strategy is if I want to break things too much, I will release a whole new repo named joy2.
Let's hope it never comes to that.
Anyway if you were using those functions change this:
(css "/style1.css" "/style2.css")
to this
(link {:href ["/style1.css" "/style2.css"]})
and the js is similar:
(js "/js1.js" "/js2.js")
to:
(script {:src ["/js1.js" "/js2.js"]})
with the added benefit now of adding other attributes, like :defer
Again, this doesn't happen often (or at all) but sometimes a new feature is just too good to pass up. If you are using the app function, it has changed to handlers, so this:
(app (handler routes1) (handler routes2))
is now this:
(handlers (handler routes1) (handler routes2))
What do you get from this breaking change?
Let me show you something really cool:
(use joy)
(defn / [request]
(text/html
[:h1 "You found joy!"]))
(def app (app))
(server app 9001) # go ahead and visit http://localhost:9001 I dare ya
That is all it takes now to get a joy app up and running!
More bug fixes and improvements
- 76f19e4 - Bump version 0.7.4
- a860b30 - Use absolute paths for bundles
- b26c7e3 - Only call layout when handler returns a tuple
- 4f98b70 - Attempt to symlink to /usr/local/bin on install
Bug fixes and improvements
- 67f1ee2 - Pass :database-url to db/connect
- bd1e98e - Bump to 0.7.3
- 5cb7d6e - Use latest joy in template
- 06b1316 - Remove joy/db import from generated routes
- c918798 - Fix route generation
A few bugfixes, notably though, headers are case-insensitive now with a new, handy headers
function:
(header request :x-csrf-token) # or whatever you want
Oh! There's also a new json-body-parser
middleware that parses incoming json requests with a content-type: application/json
header
Tiny release, just fixing up html escaping
Notable things in this release:
- Tentative postgresql support via the db library
- Better logging, where the request is always logged, even if the response isn't
- Routes can now be dynamically found within the
routes/
folder like so:
(use joy)
(defroutes routes
[:get "/" :home/index])
Assuming you have a file: src/routes/home.janet
and then within that file, this code:
(defn index [request])
- Array body parsing, so you can have inputs in a form like this:
[:input {:type "text" :name "tag[]"}]
[:input {:type "text" :name "tag[]"}]
[:input {:type "text" :name "tag[]"}]
and on the server you'll have your body look like this:
(defn a-post [request]
(def body (request :body))
(body :tag)) # => @["tag1" "tag2" "tag3"]
- session cookies now default to SameSite=Lax instead of strict
- Lots of other little bugs fixed and improvements made
This one was a doozy, but I'm fairly sure there were no breaking changes 🤞
- Add new
rescue-from
fn - Fix a regression when parsing request bodies, a space would be a + character
- Joy now sets foreign keys and journal_mode to WAL in
with-db-connection
- DB_NAME is now DATABASE_URL to help with heroku deployments (if there are any)
- Use a
dyn
for the database connection instead of opening/closing a connection on each request - Fixed a bug where the
server-error
middleware would totally ruin the handler's janet env - Fixed a bug where when you switch joy apps the cookie decryption would fail and just throw errors
- Changed the default new joy app template
It doesn't seem like a lot, but it is. Here's the gist of it:
Before:
(import joy :prefix "")
(defn index [request]
(let [{:db db} request]
(fetch-all db [:todos])))
Now:
(import joy :prefix "")
(import joy/db)
(db/connect)
(defn index [request]
(db/fetch-all [:todos])))
This change sets joy up for it's own console a la joy console
from the terminal similar to rails console
which sets up the database connection and lets you mess around with data.
- New version of tester
- Now uses janet-uri for uri encoding/decoding/parsing
- A little house cleaning with the tests
- A few /docs + docstrings added
- The request map now has the response map inside of it for things like conditional menus when people are logged in, etc.
- when is now supported in vector-html
- base64/encode now doesn't leave you with a trailing
\0
char - New rest macro
- A new uri validator !
It went from this
(label :field-name)
to this
(label :field-name "label string")
so watch out.
This:
(submit "save" [:class "red"])
to this:
(submit "save" :class "red")
Also changed, it's now:
(with-db-connection [db "dev.sqlite3"]
(delete-all db :post :where {:draft true} :limit 1))
or
(delete-all db :post)
Which will delete all rows in the post
table.
Check if static files exist in middleware first so they actually return 404s
Joy was still using the old version of cipher without jhydro. This fixes that.
- Breaking changes for routing
- No more per route middleware
- Delete json-encode/decode functions
- Rely on defglobal for routes tokens
- Handle nil responses in built in middleware
- Simplify routing by using
some
and grouping middleware per handler (defroutes name [] [])
instead of(def name (routes [] []))
- Massive anti-csrf changes: encrypting, base64 encoding and storing the token in the session + hidden form fields
- New module for base64 encoding/decoding (base64/encode), (base64/decode)
app
has been renamed tohandler
app
is still around but it runs handlers one after the other for different middleware stacks (apis, auth...)
- Add git dotfiles to template folder
- Add first pass at code generation
- Change all database interactions to auto kebab-case from and snake-case to db
- Fix duplicate body-parser middleware in template
- Add csrf-protection
- Set path and http-only on set-cookie middleware
- Marshal/unmarshal for cookie session serialization
- Escape html in attributes
- Add second pass at route code generation
- Finish up the cli
- Add a template folder and the
joy new
command - Add form,
url-for
,action-for
andredirect-to
helpers - Finish up
*.sql
migrations - Get static files working
- Stop logging static files by default
- Use
:export
instead of redefining everything injoy.janet
- Fix quite a few bugs
- Add a whole new MIT licensed http server halo
- Add form validations
- Add db functions
- Port over env, helper, logger, responder and router code from coast