jacobobryant / biff Goto Github PK
View Code? Open in Web Editor NEWA Clojure web framework for solo developers.
Home Page: https://biffweb.com
License: MIT License
A Clojure web framework for solo developers.
Home Page: https://biffweb.com
License: MIT License
crux has had some breaking changes, hence I haven't done this already
Include:
We'll need terraform config for a load balancer and multiple web servers. I think query subscriptions will work without any changes. Subscription state is stored in memory, but it's coupled to the client's web socket session. if they disconnect and reconnect to a different web server, the state should be cleared out from the old machine and instantiated on the new machine already. Triggers will need some work though. If we used multiple web servers now, triggers would be executed on each one. So we may need some kind of queue.
I'm pretty sure that's all that's needed. I'll double check the code base though.
instead of starting the process with clj -m biff.core
, we should start it with clj -m yourapp.core
. start-biff
should include the code that's currently in the biff.core/init
and biff.core/web-server
components. So from yourapp.core/-main
, you'd just call start-biff
and that's it. no need for the component system.
Fun fact: the component system, which includes searching the classpath for namespaces with ^:biff
metadata, is a historical artifact from when biff was going to be a package manager for open-source web apps. You'd install web apps by adding them to deps.edn
(via a web interface, so non-programmers could do it too). So you had to start with clj -m biff.core
because you didn't even know what apps were going to be installed.
I've been thinking lately about how the :yourapp.biff/foo
vs :biff/foo
thing is confusing and in most cases unnecessary. The purpose of it was to allow multiple start-biff calls in the same process, i.e. so they could have non-conflicting namespaces. But most people will likely only be running one biff instance, at least at first, so maybe better to turn off the namespace shenanigans by default but keep them as an option for those who want to run multiple instances.
On several occasions I've had spikes in /api/chsk requests from Sente. For example, my machine sent 150 of these over the course of 12 seconds:
[IP] - - [08/Jun/2020:04:03:04 +0000] "POST /api/chsk HTTP/1.1" 200 4 "https://findka.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0"
Need to figure out if this is a bug in Sente or in Biff/Findka.
Interesting that a retry is being triggered even though it's a 200 response; that should be investigated. Normally there's an increasing pause between retries, though it looks like in this case there shouldn't be a retry at all.
Right now, read permissions can only be defined on a per-document basis (not per-key). Sometimes you have to split information into multiple documents to support granular permissions. It would be pretty easy to let read auth fns return a filtered version of the given document based on who the client is.
Yogthos has a replacement that'll work with Sente:
https://www.reddit.com/r/Clojure/comments/h15jxh/biff_is_officially_released_web_framework/ftqh8pq/
https://github.com/luminus-framework/ring-undertow-adapter
https://github.com/ptaoussanis/sente/pull/372/files
e.g. you can:
clj -m biff.core
to clj -m example.core
start-biff
with its contents (and repeat as needed)Reitit now has a handler for the filesystem instead of just resources. See if we can replace Biff's custom file handler with that.
I answered some questions on the slack channel today, and it might be useful to put the info in the docs. Saving here so it doesn't get lost. This is a raw copy-paste (thank you, slack, for getting rid of raw markup. ugh).
Just looked through domino-clj's readme. Hadn't seen it before. Looks interesting. Your Intention and Theory sections both seem on track to me. For your questions:
What are the steps that I need to do to add a new table of 'facts' (or any other datatype)?
I follow roughly these steps, using the :public-users (i.e. public information about a user) table from the example app:
Define a spec for the datatype (https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/rules.clj#L13 and https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/rules.clj#L10) Define rules for the datatype, which reference the spec and also include authorization functions (https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/rules.clj#L33) Subscribe to the datatype on the client (https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/client/app/db.cljs#L55) Set up reactions for the datatype (https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/client/app/db.cljs#L30) Use the datatype in the UI (https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/client/app/components.cljs#L33) Set up mutations for the datatype (https://github.com/jacobobryant/biff/blob/f368d110bc35e52ff293d8306627eeac429fee66/example/src/example/client/app/components.cljs#L36 and https://github.com/jacobobryant/biff/blob/master/example/src/example/client/app/mutations.cljs#L23) should I be thinking about biff as starting point to using crux, or as an open-source firebase? When should I use crux directly?
I don't quite understand the first question, but I think the answer is "the former". (I went with "tables" mainly for personal aesthetic taste and because it's shorter to type). Generally speaking, Biff provides a layer of abstraction on top of Crux. That abstraction layer gives you (1) subscriptions, (2) integration with rules, (3) some higher level operations in transactions (e.g. :db/merge). But there likely will be times when you want to bypass Biff and use Crux directly.For transactions, I pretty much always go through biff. I haven't documented it, but there's a biff.crux/submit-tx function (
) which lets you submit biff transactions from the backend as a trusted user. The changes will be checked against the specs for your table to make sure you didn't make a mistake, but the authorization function (which verifies that the current user is allowed to submit the transaction) won't run. However if going through biff feels like an annoyance, it's easy enough to use crux.api/submit-tx instead.Biff's query support only includes subscriptions, not one-time queries, and it supports a very limited subset of Crux's query features. So I always use crux.api/q when querying on the backend. It could also be useful on the frontend (via a custom sente event handler/http handler) if you need more complex queries and you can live without Biff's subscription support. I have a branch of Findka that does that for paginating some queries (Biff doesn't have a pagination story at the moment).Line 522 in f368d11
Do I need to edit handlers.clj with a custom handler new type, or is there a standardized way of doing it with biff?
Not necessarily. If all the frontend's writes can be authorized easily using the rules system, then you can just submit biff transactions from the frontend; no need for setting up custom event handlers. This is often the case for CRUD apps. However, some writes, like complex state transitions, are easier to handle with a custom event. Since the example app is a board game, it includes these kinds of writes. In general, adding custom handlers in Biff apps is more of a one-off thing, not something you do whenever you add a new datatype. (Let me know if I misunderstood this question).
So instead of (start-biff sys 'yourapp.biff)
, you'd just do (start-biff sys 'yourapp)
.
I vaguely remember this being a thing. Need to see if the event router should use futures or something. or just leave it up to the application.
It'll make them slightly less convenient to use, but as it is, cross-site requests can see if you're signed in and sign you out.
"util" is about as good of a name as "stuff"
There are currently print calls sprinkled throughout the codebase.
perhaps store session in crux instead?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.