- fix project structure to accommodate for minified templates and pages
إفطار سُهيل هو موقع لنشر طرق تحضير وتقديم الطعام مع ارشاد صوتي ومؤقت
so much I would like to document
In my words, it is a data oriented tool for authentication. I mainly use it in combination with refresh token to reduce database requests. here is a repository by hussein nasser.
to run uber file / jar file run java -jar jarfile
to build the directory run clojure -T:build uber
the build tool I choose is shadow-cljs. Installed using the command npm install --save-dev shadow-cljs but could get the same result with npm add shadow-cljs -D.
for development run npx shadow-cljs watch <BUILD-ID> where BUILD-ID is define in shadow-cljs.edn. As an example npx shadow-cljs watch register
STATUS: TESTING
initialized with the command npx tsc --init. Compile with npx tsc
shadcn is componentless library for react. it requires typescript.
- initilized with
npm shadcn-ui@latest init - add component with
npx shadcn-ui@latest addor just copy it tosrc/ts
we can compile css directly with tailwindcss with the command npx tailwindcss -i resources/styles/input.css -o public/css/output.css --watch and if we replace the watch flag with --minify tailwindcss will output a minified file.
Fortunately we can also watch multiple files at the same time with postcss-cli. If we store styles in resources/styles and output css to public/css then the watch command is:
npx postcss-cli resources/styles --dir public/css --watch
for live server reloading with basic html and css. Install with npm install -g browser-sync. Run with browser-sync start --server --files 'public/*' if you want a static server. In case you are using the backend run browser-sync start --proxy "localhost:3000" --files "public/**/*" "resources/**/*" "src/**/*"
used to build android and ios app with flutter, see clojuredart
inialize with clj -M:cljd init.
Run flutter emulators --launch Pixel_XL_API_34 from root directory of the project. To list emulators run flutter emulators
In root directory of project run clj -M:cljd flutter
I'm following the instructions in Github Docs, google dev and oauth2 to build a login button. I realized that for Oauth you should Have a client_id so that your users can send a request to Github (or any identity provider) to give permission to my website, then Github sends me a code to a specified url that I determine. This code is then used to get an access token for my website to issue requests on behalf of the user. Github need a client_secret in order to verify that client_id used to request code matches.
It finally clicked with me that Github api can work with JWT+refresh token in this manner: we start by user authorizing the website to get an access token to github. This redirects to a specified path in the website with a code. the server sends the code to github an get an access token which will serve to get data about the user, mainly email address and [nick]name1. There are two possibilities from here, either user has been registered or is a new user. We go by this by checking the emails in the database:
- user doesn't exist in database. the server creates a record for the user then associates a refresh token to the user, containing an identifier (ID for example). Finally the server returns the refresh token to user and a JWT token with the same data. The JWT toekn could be stored in cookies since it is required in every request. However, refresh token is only required every so often ( determined by configuration ) which leads us to store it in browser localStorage.
- user exists in database. there is no need to creat a new record. Therefore, the server returns with refresh token and JWT token.
There should also be extra care to handle the case where user does exist in a database but as a temporary user2. Meaning, the user didn't sign in with github ( or any authorization server implemented in the future) but can access an account via JWT+refresh token.
I thought of several option, first to simply send another request after receiving the page. The tradeoff is of course the extra overhead of tcp and http request. Another solution is to embed the data in html document. MDN suggests a script tag with json. For this solution to work I had to send data in a json format and specify that it is safe for templating library I use selmer. A slight modification to the last solution is to embed the data in a div tag. This has the advantage of not relying on the safe option but need to hide the div with display:hidden
Conclusion, I choose the mdn solution because it is semantically correct and doesn't have vulnerabilities
the fetch api is great for handling http requests. You can upload json, file and even abort request.
a great answer on stackoverflow. Here is the summary: there are three means to achieve redirects:
window.location="newUrl"will redirect to url and save currect page in browser history.window.location.replace="newUrl"will redirect to url but will not keep currect page in session history, simulating an HTTP redirect.window.location.href="newUrl"simulate clicking ana(anchor) tag. Same behavior as replace.
window object can be omitted since it is global.
from the runes of w3school we can see the navigator object is used to save to clipboard. here is an example:
let text="text I want to be clipped";
navigator.clipboard.writeText(text);
console.log("text in clipboard!!");I thought of using a data attribute to indicate if an image should appear or not in recipe.html but decided to go with another route instead.
Because It bugged me how testing equality is in the library I thought it would be helpful to document it for future:
data-active="{% if recipe.id = 1 %}true{% else %}false{% endif %}"
testing equality is with one equal sign like in clojure instead of two equal signs like in python. It was counter intuitive because selmer is based on django.
there are two way in javascript, first with Object.keys(obj) and second with for(let prop in obj){...}. In Clojurescript we can convert the first option to the form (js/Object.keys obj) and second solution is from stackoverflow (js-keys carouselslide)
Since I use tailwindcss it handles minifing css files and same for clojurescript and shadow-cljs. As for html, I opted for asset-minifier but unfortunately it is undocumented. Here are the info for minifying html. To use asset-minifier.core/minify-html we provide source directory, target directory and mandatory options. options are same for html-compressor/compressor. for example: simple map {:enabled true}
from stackoverflow I got the command openssl rand -base64 32. See also auth0
from sqlite.org, postgresql requires fully qualified reference in the update statement that follows on conflict. The example from sqlite main website:
CREATE TABLE vocabulary(word TEXT PRIMARY KEY, count INT DEFAULT 1); INSERT INTO vocabulary(word) VALUES('jovial') ON CONFLICT(word) DO UPDATE SET count=count+1;
should be written as:
CREATE TABLE vocabulary(word TEXT PRIMARY KEY, count INT DEFAULT 1); INSERT INTO vocabulary(word) VALUES('jovial') ON CONFLICT(word) DO UPDATE SET count=vocabulary.count+1;
A simple way to make you code repl-friendly is to derefrence the vars instead of supplying its value. Let a be a variable with value 1. if we define a function that referenced a for example (+ a 4) then when reading the function a will be replaced with 1. On the other hand, @#'a will be read as (deref (var a)). There is a video on youtube but I can't seem to find it.
to use http2 I stumbled upon ring-jetty9-adapter and had to generate a .jks file. oracle has a good tutorial how to generate it. The main tool is keytool. keystore password 1234client and file is in resources/clientkeystore.jks. There is also this answer and this https://unix.stackexchange.com/questions/347116/how-to-create-keystore-and-truststore-using-self-signed-certificate. https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html https://docs.oracle.com/cd/E19798-01/821-1751/ghlgv/index.html https://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html https://shadow-cljs.github.io/docs/UsersGuide.html#_ssl
openssl req -x509 -newkey rsa:4096 -nodes -sha256 -subj '/CN=localhost' -keyout localhost-private.pem -out localhost-cert.pem
I would like to publish the project under AGPL or a modification of it or GPL but it is incompatible with clojure[script] license. If anyone knows a way around, please contact me.
Distributed under the Eclipse Public License, the same as Clojure.