fix update-snippet
Created via bruno", Updated via bruno" does a cool thing",
This commit is contained in:
parent
d3babebcc4
commit
5fad04d04c
15 changed files with 90 additions and 102 deletions
10
README.md
10
README.md
|
|
@ -18,8 +18,16 @@ This project is written in [Clojure](https://clojure.org/) and data is stored in
|
||||||
|
|
||||||
### How to run dev server
|
### How to run dev server
|
||||||
|
|
||||||
|
Run the server
|
||||||
|
|
||||||
```
|
```
|
||||||
$ clojure -M -m snippets.infra.api
|
$ clojure -M -m snippets.main
|
||||||
|
```
|
||||||
|
|
||||||
|
Hot reload:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ fd -e clj | entr -r clojure -M -m snippets.main
|
||||||
```
|
```
|
||||||
|
|
||||||
### Repl
|
### Repl
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ post {
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"title": "TEST from Bruno",
|
"title": "Mock snippet sent via Bruno",
|
||||||
"slug": "bruno-test",
|
"slug": "bruno-test",
|
||||||
"markdown": "this is a test",
|
"markdown": "## MOCK SNIPPET\nCreated via bruno",
|
||||||
"tags": ["test"]
|
"tags": ["mock"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
delete {
|
delete {
|
||||||
url: {{host}}/api/snippet?id=d77d3463-c76e-4c53-a1d5-ecaf16c6c54e
|
url: {{host}}/api/snippet?slug=bruno-test
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
params:query {
|
params:query {
|
||||||
id: d77d3463-c76e-4c53-a1d5-ecaf16c6c54e
|
slug: bruno-test
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,18 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
patch {
|
patch {
|
||||||
url: {{host}}/api/snippet?id=680a3508-7709-4f71-b5c3-3dcbffe6f5cf
|
url: {{host}}/api/snippet?slug=bruno-test
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
params:query {
|
params:query {
|
||||||
id: 680a3508-7709-4f71-b5c3-3dcbffe6f5cf
|
slug: bruno-test
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"title": "quick way to push last jj commit to git",
|
"title": "Mock snippet sent via Bruno with updated title",
|
||||||
"tags": ["jj", "git"]
|
"markdown": "## MOCK SNIPPET\nUpdated via bruno"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
meta {
|
|
||||||
name: get_snippet
|
|
||||||
type: http
|
|
||||||
seq: 6
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{host}}/api/snippet?id=aea69336-5116-49ac-ab52-bc221bdb7830
|
|
||||||
body: none
|
|
||||||
auth: none
|
|
||||||
}
|
|
||||||
|
|
||||||
params:query {
|
|
||||||
id: aea69336-5116-49ac-ab52-bc221bdb7830
|
|
||||||
}
|
|
||||||
|
|
||||||
body:json {
|
|
||||||
{
|
|
||||||
"title": "Test Snippet",
|
|
||||||
"markdown": "## Cool Snippet\ndoes a cool thing",
|
|
||||||
"tags": ["git", "jj"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,13 +5,13 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
url: {{host}}/api/snippet-by-slug?slug=netcat-over-ping
|
url: {{host}}/api/snippet-by-slug?slug=bruno-test
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
params:query {
|
params:query {
|
||||||
slug: netcat-over-ping
|
slug: bruno-test
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
url: {{host}}/api/snippets?limit=25&skip=0
|
url: {{host}}/api/snippets?limit=2&skip=0
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
params:query {
|
params:query {
|
||||||
limit: 25
|
limit: 2
|
||||||
skip: 0
|
skip: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
url: {{host}}/api/tag?tag=git
|
url: {{host}}/api/tag?tag=mock
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
params:query {
|
params:query {
|
||||||
tag: git
|
tag: mock
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@
|
||||||
{:status 200, :body "snippet created"})
|
{:status 200, :body "snippet created"})
|
||||||
|
|
||||||
(defn handle-edit-snippet [{body :body-params params :query-params}]
|
(defn handle-edit-snippet [{body :body-params params :query-params}]
|
||||||
(let [id (get params "id")]
|
(let [slug (get params "slug")]
|
||||||
(t/log! {:level :info, :data {:body body :id id}} "Received request to edit snippet")
|
(t/log! {:level :info, :data {:body body :slug slug}} "Received request to edit snippet")
|
||||||
(let [{success :success :as res} (snippets.use-cases.edit/edit-snippet id body)]
|
(let [{success :success :as res} (snippets.use-cases.edit/edit-snippet slug body)]
|
||||||
(cond
|
(cond
|
||||||
success {:status 200, :body "snippet updated"}
|
success {:status 200, :body "snippet updated"}
|
||||||
(= (:reason res) :invalid-patch) {:status 400, :body "invalid patch"}
|
(= (:reason res) :invalid-patch) {:status 400, :body "invalid patch"}
|
||||||
|
|
@ -41,10 +41,13 @@
|
||||||
:body (snippets.use-cases.view/view-snippets nil)}))
|
:body (snippets.use-cases.view/view-snippets nil)}))
|
||||||
|
|
||||||
(defn handle-delete-snippet [{params :query-params}]
|
(defn handle-delete-snippet [{params :query-params}]
|
||||||
(let [id (get params "id")]
|
(let [slug (get params "slug")
|
||||||
(snippets.use-cases.delete/delete-snippet id)
|
res (snippets.use-cases.delete/delete-snippet slug)]
|
||||||
{:status 200
|
(if (nil? res)
|
||||||
:body (format "Deleted snippet with id: %s if it existed" id)}))
|
{:status 404
|
||||||
|
:body "No snippet with that slug found"}
|
||||||
|
{:status 200
|
||||||
|
:body (format "Deleted snippet with slug: %s if it existed" slug)})))
|
||||||
|
|
||||||
(defn handle-view-tags [_args]
|
(defn handle-view-tags [_args]
|
||||||
(let [tags (snippets.use-cases.view/view-tags)]
|
(let [tags (snippets.use-cases.view/view-tags)]
|
||||||
|
|
@ -57,9 +60,13 @@
|
||||||
:body (snippets.use-cases.view/view-snippets-by-tag tag)}))
|
:body (snippets.use-cases.view/view-snippets-by-tag tag)}))
|
||||||
|
|
||||||
(defn handle-view-snippet-by-slug [{params :query-params}]
|
(defn handle-view-snippet-by-slug [{params :query-params}]
|
||||||
(let [slug (get params "slug")]
|
(let [slug (get params "slug")
|
||||||
{:status 200
|
snippet (snippets.use-cases.view/view-snippet-by-slug slug)]
|
||||||
:body (snippets.use-cases.view/view-snippet-by-slug slug)}))
|
(if (nil? snippet)
|
||||||
|
{:status 404
|
||||||
|
:body "No snippet with that slug found"}
|
||||||
|
{:status 200
|
||||||
|
:body snippet})))
|
||||||
|
|
||||||
(defn wrap [handler id]
|
(defn wrap [handler id]
|
||||||
(fn [request]
|
(fn [request]
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,10 @@
|
||||||
db (d/db conn)
|
db (d/db conn)
|
||||||
query '[:find (pull ?e [*])
|
query '[:find (pull ?e [*])
|
||||||
:in $ ?slug
|
:in $ ?slug
|
||||||
:where [?e :snippet/slug ?slug]]]
|
:where [?e :snippet/slug ?slug]]
|
||||||
(ffirst (d/q query db slug))))
|
snippet (ffirst (d/q query db slug))]
|
||||||
|
(t/log! {:level :info, :data {:slug slug :snippet snippet}} "Got snippet by slug")
|
||||||
|
snippet))
|
||||||
|
|
||||||
(def get-snippet-by-slug
|
(def get-snippet-by-slug
|
||||||
(wrap-snippet-return get-snippet-by-slug-from-db))
|
(wrap-snippet-return get-snippet-by-slug-from-db))
|
||||||
|
|
@ -132,6 +134,7 @@
|
||||||
(def update-schema
|
(def update-schema
|
||||||
"Malli schema for a valid update to a snippet entity."
|
"Malli schema for a valid update to a snippet entity."
|
||||||
[:map
|
[:map
|
||||||
|
[:db/id :int]
|
||||||
[:snippet/title {:optional true} :string]
|
[:snippet/title {:optional true} :string]
|
||||||
[:snippet/slug {:optional true} :string]
|
[:snippet/slug {:optional true} :string]
|
||||||
[:snippet/markdown {:optional true} :string]
|
[:snippet/markdown {:optional true} :string]
|
||||||
|
|
@ -148,17 +151,23 @@
|
||||||
"Update specific fields of a snippet."
|
"Update specific fields of a snippet."
|
||||||
[slug raw-patch]
|
[slug raw-patch]
|
||||||
(let [conn (get-conn)
|
(let [conn (get-conn)
|
||||||
eid (:db/id (get-snippet-by-slug slug))
|
db (d/db conn)
|
||||||
patch (to-update raw-patch)]
|
;; query '[:find ?e
|
||||||
(t/log! {:level :info, :data {:patch patch :slug slug}} "Patching snippet")
|
;; :in $ ?slug
|
||||||
|
;; :where [?e :snippet/slug ?slug]]
|
||||||
|
;; eid (ffirst (d/q query db slug))
|
||||||
|
eid (:db/id (get-snippet-by-slug-from-db slug))
|
||||||
|
patch (merge (to-update raw-patch) {:db/id eid})]
|
||||||
|
(t/log! {:level :info, :data {:patch patch :slug slug :eid eid}} "Patching snippet")
|
||||||
(when (nil? eid)
|
(when (nil? eid)
|
||||||
(throw (ex-info "Snippet not found" {:slug slug})))
|
(throw (ex-info "Snippet not found" {:slug slug})))
|
||||||
(when-not (m/validate update-schema patch)
|
(when-not (m/validate update-schema patch)
|
||||||
(throw (ex-info "Invalid patch" {:errors (m/explain update-schema patch) :patch patch})))
|
(throw (ex-info "Invalid patch" {:errors (m/explain update-schema patch) :patch patch})))
|
||||||
(let [tx-data [(merge {:db/id eid} patch)]]
|
(d/transact conn {:tx-data [patch]})))
|
||||||
(d/transact conn {:tx-data tx-data}))))
|
|
||||||
|
|
||||||
(def update-snippet (wrap-snippet-return patch-snippet-in-db))
|
(defn update-snippet [& args]
|
||||||
|
(let [res (apply patch-snippet-in-db args)]
|
||||||
|
(t/log! {:level :info, :data {:res res :args args}} "Finished patching snippet")))
|
||||||
|
|
||||||
(defn list-snippets-in-db
|
(defn list-snippets-in-db
|
||||||
"List all the snippets"
|
"List all the snippets"
|
||||||
|
|
@ -178,10 +187,10 @@
|
||||||
[slug]
|
[slug]
|
||||||
(t/log! {:level :info, :data {:slug slug}} "Retracting snippet")
|
(t/log! {:level :info, :data {:slug slug}} "Retracting snippet")
|
||||||
(let [conn (get-conn)
|
(let [conn (get-conn)
|
||||||
eid (:db/id (get-snippet-by-slug slug))]
|
eid (:db/id (get-snippet-by-slug-from-db slug))]
|
||||||
(when (nil? eid)
|
(if (nil? eid)
|
||||||
(throw (ex-info "Snippet not found" {:slug slug})))
|
nil
|
||||||
(d/transact conn {:tx-data [[:db/retractEntity eid]]})))
|
(d/transact conn {:tx-data [[:db/retractEntity eid]]}))))
|
||||||
|
|
||||||
(defn list-tags
|
(defn list-tags
|
||||||
"List all tags used in snippets with their counts."
|
"List all tags used in snippets with their counts."
|
||||||
|
|
|
||||||
15
src/snippets/use_cases/backfill_db2.clj
Normal file
15
src/snippets/use_cases/backfill_db2.clj
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
(ns snippets.use-cases.backfill-db2
|
||||||
|
(:require
|
||||||
|
[snippets.infra.db :as old-db]
|
||||||
|
[snippets.infra.db2 :as new-db]
|
||||||
|
[taoensso.telemere :as t]))
|
||||||
|
|
||||||
|
(defn- zdt-to-date [zdt]
|
||||||
|
(java.util.Date/from (.toInstant zdt)))
|
||||||
|
|
||||||
|
(defn backfill []
|
||||||
|
(t/log! {:level :info} "Backfilling DB2")
|
||||||
|
(let [old-snippets (old-db/list-snippets {})
|
||||||
|
new-snippets (map #(assoc % :pub-date (zdt-to-date (:pub-date %))) old-snippets)]
|
||||||
|
(t/log! {:level :info :data {:count (count new-snippets)}} "Creating snippets")
|
||||||
|
(new-db/create-snippets new-snippets)))
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
(ns snippets.use-cases.backfill-from-file
|
|
||||||
(:require
|
|
||||||
[clojure.java.io :as io]
|
|
||||||
[clojure.pprint :as pprint]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[frontmatter.core :as fm]))
|
|
||||||
|
|
||||||
(defn scrape-files []
|
|
||||||
(let [dir "./old_snippets"]
|
|
||||||
(->> (io/file dir)
|
|
||||||
(.listFiles)
|
|
||||||
(map #(.getName %))
|
|
||||||
(map #(hash-map :slug (first (str/split % #"\.")) :full-path (str dir "/" %)))
|
|
||||||
;; (map #(fm/parse (:full-path %))))))
|
|
||||||
(map #(let [{frontmatter :frontmatter body :body} (fm/parse (:full-path %))]
|
|
||||||
(assoc %
|
|
||||||
:title (:title frontmatter)
|
|
||||||
:pub-date (:date frontmatter)
|
|
||||||
:markdown body
|
|
||||||
:scraped true
|
|
||||||
:tags (:snippet_types frontmatter))))
|
|
||||||
(map #(dissoc % :full-path)))))
|
|
||||||
|
|
||||||
;; used repl to do backfill
|
|
||||||
;; (doseq [s old-snippets] (xt/execute-tx db/client [[:put-docs :snippets (merge {:xt/id (:slug s)} s)]]))
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
(ns snippets.use-cases.create
|
(ns snippets.use-cases.create
|
||||||
(:require
|
(:require
|
||||||
[taoensso.telemere :as t]
|
[taoensso.telemere :as t]
|
||||||
[snippets.infra.db :as db]))
|
[snippets.infra.db2 :as db]))
|
||||||
|
|
||||||
(defn- uuid [] (str (java.util.UUID/randomUUID)))
|
|
||||||
|
|
||||||
(defn create-snippet [{:keys [title slug markdown tags]}]
|
(defn create-snippet [{:keys [title slug markdown tags]}]
|
||||||
(let [id (uuid)
|
(let [pub-date (java.util.Date.)]
|
||||||
pub-date (java.util.Date.)]
|
(t/log! {:level :info, :data {:title title :slug slug}} "Creating snippet")
|
||||||
(t/log! {:level :info, :data {:title title :slug slug :id id}} "Creating snippet")
|
(db/create-snippets [{:title title :slug slug :markdown markdown :tags tags :pub-date pub-date}])))
|
||||||
(db/put-snippet id {:title title :slug slug :markdown markdown :tags tags :pub-date pub-date})))
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(ns snippets.use-cases.delete
|
(ns snippets.use-cases.delete
|
||||||
(:require
|
(:require
|
||||||
[snippets.infra.db :as db]
|
[snippets.infra.db2 :as db]
|
||||||
[taoensso.telemere :as t]))
|
[taoensso.telemere :as t]))
|
||||||
|
|
||||||
(defn delete-snippet [key]
|
(defn delete-snippet [slug]
|
||||||
(t/log! {:level :info, :data {:key key}} "Deleting snippet by id")
|
(t/log! {:level :info, :data {:slug slug}} "Deleting snippet by slug")
|
||||||
(db/delete-snippet key))
|
(db/delete-snippet-by-slug slug))
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
(:require
|
(:require
|
||||||
[taoensso.telemere :as t]
|
[taoensso.telemere :as t]
|
||||||
[malli.core :as m]
|
[malli.core :as m]
|
||||||
[snippets.infra.db :as db]))
|
[snippets.infra.db2 :as db]))
|
||||||
|
|
||||||
(def valid-patch?
|
(def valid-patch?
|
||||||
(m/validator
|
(m/validator
|
||||||
|
|
@ -12,11 +12,11 @@
|
||||||
[:tags {:optional true} [:seqable :string]]
|
[:tags {:optional true} [:seqable :string]]
|
||||||
[:slug {:optional true} :string]]))
|
[:slug {:optional true} :string]]))
|
||||||
|
|
||||||
(defn edit-snippet [id patch]
|
(defn edit-snippet [slug patch]
|
||||||
(t/log! {:level :info, :data {:patch patch :id id}} "Editing snippet")
|
(t/log! {:level :info, :data {:patch patch :slug slug}} "Editing snippet")
|
||||||
(if (valid-patch? patch)
|
(if (valid-patch? patch)
|
||||||
(do
|
(do
|
||||||
(t/log! {:level :info, :data {:patch patch :id id}} "Valid changes editing snippet")
|
(t/log! {:level :info, :data {:patch patch :slug slug}} "Valid changes editing snippet")
|
||||||
(db/patch-snippet id patch)
|
(db/update-snippet slug patch)
|
||||||
{:success true})
|
{:success true})
|
||||||
{:success false :reason :invalid-patch}))
|
{:success false :reason :invalid-patch}))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue