(ns blog.db (:require ["pg" :refer [Client]] [cljs.core.async :refer [go, take!, put!, !, chan]] [cljs.core.async.interop :refer-macros [js js->clj]] [blog.env :as env])) (defn create-client "Create a new client for Postgres using enviroment variables." [] (->> (env/get-database-credentials) (cljs.core/clj->js) (new Client))) (defn connect-client "Connect a client to the database" [client] (. client connect)) (defn get-articles "Reads all articles and returns via channel. It gets and returns the same channel." [client channel] (go (try (let [res (! channel (.-rows res))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn get-articles-briefly "Reads all articles and returns via channel. It gets and returns the same channel. The content will be brief (<=60 characters)." [client channel] (go (try (let [res (! channel (.-rows res))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn search-articles-briefly "Search all articles by titles and contents and returns via channel. It gets and returns the same channel. The content will be brief (<=60 characters)." [client search channel] (go (try (let [res (js [(str "%" search "%")])))] (>! channel (.-rows res))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn get-article "Reads an article with the id and returns via channel. It gets and returns the same channel. Empty collection if not found." [client id channel] (go (try (let [res (js [id])))] (>! channel (-> (.-rows res) (js->clj :keywordize-keys true) (first)))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn get-article-briefly "Reads an article with the id and returns via channel. It gets and returns the same channel. Empty collection if not found. The content will be brief (<=60 characters)." [client id channel] (go (try (let [res (js [id])))] (>! channel (-> (.-rows res) (js->clj :keywordize-keys true) (first)))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn insert-article "Insert an article and return the id via channel. It gets and returns the same channel." [client title content channel] (go (try (let [res (js [title content])))] (>! channel (-> (.-rows res) (js->clj :keywordize-keys true) (first) (:id)))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn update-article "Update an article and return the id via channel. The timestamp for created will be updated to current timestamp. It gets and returns the same channel." [client {:keys [id title content]} channel] (go (try (let [res (js [id title content])))] (>! channel (-> id))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn delete-article "Delete an article and return the id via channel. It gets and returns the same channel." [client id channel] (go (try (let [res (js [id])))] (>! channel (-> (.-rows res) (js->clj :keywordize-keys true) (first) (:id)))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn get-about "Reads the about article. It gets and returns the same channel. Empty collection if not found." [client channel] (go (try (let [res ( (.-rows res) (js->clj :keywordize-keys true) (first))] (>! channel (or about []))) (catch js/Error err (do (>! channel nil) (js/console.log (ex-cause err)))))) channel) (defn insert-about "Insert the about article and return the id via channel. It gets and returns the same channel." [client channel] (go (try (let [res (! channel (-> (.-rows res) (js->clj :keywordize-keys true) (first) (:id)))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn insert-about-if-not-exist "Insert the about article if not exist and return the id via channel. It gets and returns the same channel." [client] (go (let [channel (chan)] (try (let [about (js [content])))] (>! channel (-> 1))) (catch js/Error err (js/console.log (ex-cause err))))) channel) (defn create-tables [client] (. client query "CREATE TABLE IF NOT EXISTS articles (id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, created TIMESTAMP DEFAULT CURRENT_TIMESTAMP);") (. client query "CREATE TABLE IF NOT EXISTS about (id SERIAL PRIMARY KEY, content TEXT NOT NULL, created TIMESTAMP DEFAULT CURRENT_TIMESTAMP);") (insert-about-if-not-exist client))