From ae86e8371683e2a24f09bd3c7e9f925d56588488 Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Fri, 4 Jul 2025 13:43:20 +0200 Subject: [PATCH] start refactor to image-service-cli namespace --- .../.cache/v1/clj/cli-cms.edit.transit.json | 2 +- .../.cache/v1/clj/cli-cms.view.transit.json | 2 +- .../clj/image-service-cli.main.transit.json | 2 +- bb.edn | 4 +- config.edn | 4 +- src/image_service_cli/cli_utils.clj | 49 ----------------- src/image_service_cli/config.clj | 2 +- src/image_service_cli/create.clj | 25 --------- src/image_service_cli/delete.clj | 18 ------- src/image_service_cli/edit.clj | 54 ------------------- src/image_service_cli/index.clj | 51 ++++++++++++++++++ src/image_service_cli/main.clj | 29 +++++----- .../{view.clj => upload.clj} | 2 +- 13 files changed, 75 insertions(+), 169 deletions(-) delete mode 100644 src/image_service_cli/cli_utils.clj delete mode 100644 src/image_service_cli/create.clj delete mode 100644 src/image_service_cli/delete.clj delete mode 100644 src/image_service_cli/edit.clj create mode 100644 src/image_service_cli/index.clj rename src/image_service_cli/{view.clj => upload.clj} (97%) diff --git a/.clj-kondo/.cache/v1/clj/cli-cms.edit.transit.json b/.clj-kondo/.cache/v1/clj/cli-cms.edit.transit.json index 2f67646..90046cd 100644 --- a/.clj-kondo/.cache/v1/clj/cli-cms.edit.transit.json +++ b/.clj-kondo/.cache/v1/clj/cli-cms.edit.transit.json @@ -1 +1 @@ -["^ ","~$fetch-snippets",["^ ","~:row",10,"~:col",1,"~:fixed-arities",["~#set",[0]],"~:name","^0","~:ns","~$cli-cms.edit","~:top-ns","^7","~:type","~:fn"],"~$prompt-for-edit-type",["^ ","^1",14,"^2",1,"^3",["^4",[0]],"^5","^;","^6","^7","^8","^7","^9","^:"],"~$send-patch",["^ ","^1",24,"^2",1,"^3",["^4",[2]],"^5","^<","^6","^7","^8","^7","^9","^:"],"~$edit",["^ ","^1",30,"^2",1,"^3",["^4",[1,2]],"^5","^=","^6","^7","^8","^7","^9","^:"],"~$run",["^ ","^1",50,"^2",1,"^3",["^4",[0]],"^5","^>","^6","^7","^8","^7","^9","^:"],"~:filename","/Users/she0001t/personal_projects/image-service-cli/src/image_service_cli/edit.clj"] \ No newline at end of file +["^ ","~$fetch-snippets",["^ ","~:row",10,"~:col",1,"~:fixed-arities",["~#set",[0]],"~:name","^0","~:ns","~$cli-cms.edit","~:top-ns","^7","~:type","~:fn"],"~$prompt-for-edit-type",["^ ","^1",14,"^2",1,"^3",["^4",[0]],"^5","^;","^6","^7","^8","^7","^9","^:"],"~$send-patch",["^ ","^1",24,"^2",1,"^3",["^4",[2]],"^5","^<","^6","^7","^8","^7","^9","^:"],"~$edit",["^ ","^1",30,"^2",1,"^3",["^4",[1,2]],"^5","^=","^6","^7","^8","^7","^9","^:"],"~$run",["^ ","^1",50,"^2",1,"^3",["^4",[0]],"^5","^>","^6","^7","^8","^7","^9","^:"],"~:filename","/Users/she0001t/personal_projects/image-service-cli/src/image_service_cli/list.clj"] \ No newline at end of file diff --git a/.clj-kondo/.cache/v1/clj/cli-cms.view.transit.json b/.clj-kondo/.cache/v1/clj/cli-cms.view.transit.json index 2962823..eabbe22 100644 --- a/.clj-kondo/.cache/v1/clj/cli-cms.view.transit.json +++ b/.clj-kondo/.cache/v1/clj/cli-cms.view.transit.json @@ -1 +1 @@ -["^ ","~$fetch-snippets",["^ ","~:row",10,"~:col",1,"~:fixed-arities",["~#set",[0]],"~:name","^0","~:ns","~$cli-cms.view","~:top-ns","^7","~:type","~:fn"],"~$fetch-snippet",["^ ","^1",14,"^2",1,"^3",["^4",[1]],"^5","^;","^6","^7","^8","^7","^9","^:"],"~$view",["^ ","^1",18,"^2",1,"^3",["^4",[1]],"^5","^<","^6","^7","^8","^7","^9","^:"],"~$run",["^ ","^1",25,"^2",1,"^3",["^4",[0]],"^5","^=","^6","^7","^8","^7","^9","^:"],"~:filename","/Users/she0001t/personal_projects/image-service-cli/src/image_service_cli/view.clj"] \ No newline at end of file +["^ ","~$fetch-snippets",["^ ","~:row",10,"~:col",1,"~:fixed-arities",["~#set",[0]],"~:name","^0","~:ns","~$cli-cms.view","~:top-ns","^7","~:type","~:fn"],"~$fetch-snippet",["^ ","^1",14,"^2",1,"^3",["^4",[1]],"^5","^;","^6","^7","^8","^7","^9","^:"],"~$view",["^ ","^1",18,"^2",1,"^3",["^4",[1]],"^5","^<","^6","^7","^8","^7","^9","^:"],"~$run",["^ ","^1",25,"^2",1,"^3",["^4",[0]],"^5","^=","^6","^7","^8","^7","^9","^:"],"~:filename","/Users/she0001t/personal_projects/image-service-cli/src/image_service_cli/upload.clj"] \ No newline at end of file diff --git a/.clj-kondo/.cache/v1/clj/image-service-cli.main.transit.json b/.clj-kondo/.cache/v1/clj/image-service-cli.main.transit.json index eb28aba..9b033c0 100644 --- a/.clj-kondo/.cache/v1/clj/image-service-cli.main.transit.json +++ b/.clj-kondo/.cache/v1/clj/image-service-cli.main.transit.json @@ -1 +1 @@ -["^ ","~$-main",["^ ","~:row",9,"~:col",1,"~:varargs-min-arity",0,"~:name","^0","~:ns","~$image-service-cli.main","~:top-ns","^6","~:type","~:fn"],"~:filename","/Users/she0001t/personal_projects/image-service-cli/src/image_service_cli/main.clj"] \ No newline at end of file +["^ ","~$s3-list",["^ ","~:row",6,"~:col",1,"~:fixed-arities",["~#set",[1]],"~:name","^0","~:ns","~$image-service-cli.main","~:top-ns","^7","~:type","~:fn"],"~$prompt-for",["^ ","^1",9,"^2",1,"~:varargs-min-arity",1,"^5","^;","^6","^7","^8","^7","^9","^:"],"~$-main",["^ ","^1",15,"^2",1,"^<",0,"^5","^=","^6","^7","^8","^7","^9","^:"],"~:filename","/Users/she0001t/personal_projects/image-service-cli/src/image_service_cli/main.clj"] \ No newline at end of file diff --git a/bb.edn b/bb.edn index 4439192..7a6ffd1 100644 --- a/bb.edn +++ b/bb.edn @@ -1,2 +1,4 @@ {:paths ["src"] - :deps {}} + :deps {com.travisshears/gum-utils {:git/url "https://git.travisshears.com/travisshears/gum-utils" + :git/tag "39K" + :git/sha "748b21d358b62db0476bc3577cb5398acc533ba1"}}} diff --git a/config.edn b/config.edn index fd98ff5..2cd9100 100644 --- a/config.edn +++ b/config.edn @@ -1,2 +1,2 @@ -;; {:backend-host "http://localhost:8080"} -{:backend-host "http://aemos:5008"} +{:aws-profile "personal" + :s3-root "s3://travisshears.images/image-service/images/"} diff --git a/src/image_service_cli/cli_utils.clj b/src/image_service_cli/cli_utils.clj deleted file mode 100644 index cddaf69..0000000 --- a/src/image_service_cli/cli_utils.clj +++ /dev/null @@ -1,49 +0,0 @@ -(ns cli-cms.cli-utils - (:require - [clojure.string :as str] - [clojure.pprint :refer [pprint]] - [babashka.process :refer [shell]])) - -(defn select - "Select from a list of options using gum filter. - Args: - l list of {:item any :value string}" - [l] - (let [values (map :value l) - selected-value (str/trim (:out (apply shell {:out :string} (concat '("gum" "filter") values)))) - selected-item (:item (first (filter #(= (:value %) selected-value) l)))] - selected-item)) - -(defn color-print - ([text] (color-print text "5")) - ([text color] - (shell (format "gum style --foreground %s \"%s\"" color text)))) - -(defn print-markdown [text] - (shell (format "gum format \"%s\"" text))) - -(defn prompt-for [placeholder & {:keys [prefill]}] - (let [cmd (if prefill - (format "gum input --placeholder='%s' --value='%s'" placeholder prefill) - (format "gum input --placeholder='%s'" placeholder) - )] - (str/trim (-> (shell {:out :string} cmd) :out)))) - -(defn prompt-for-many - ([placeholder] - (let [val (prompt-for (str placeholder ", enter done to finish"))] - (println val) - (if (= val "done") - nil - (prompt-for-many placeholder `(~val))))) - ([placeholder carry] - (let [val (prompt-for (str placeholder ", enter done to finish"))] - (println val) - (if (= val "done") - carry - (prompt-for-many placeholder (conj carry val)))))) - -(defn prompt-for-long-form [placeholder & {:keys [prefill]}] - (if prefill - (-> (shell {:out :string :extra-env {"GUM_WRITE_VALUE" prefill}} (format "gum write --placeholder='%s'" placeholder)) :out) - (-> (shell {:out :string} (format "gum write --placeholder='%s'" placeholder)) :out))) diff --git a/src/image_service_cli/config.clj b/src/image_service_cli/config.clj index becc534..57634e6 100644 --- a/src/image_service_cli/config.clj +++ b/src/image_service_cli/config.clj @@ -1,4 +1,4 @@ -(ns cli-cms.config +(ns image-service-cli.config (:require [babashka.fs :as fs] [clojure.string :as str])) diff --git a/src/image_service_cli/create.clj b/src/image_service_cli/create.clj deleted file mode 100644 index 5607584..0000000 --- a/src/image_service_cli/create.clj +++ /dev/null @@ -1,25 +0,0 @@ -(ns cli-cms.create - (:require - [cli-cms.cli-utils :as utils] - [clojure.string :as str] - [cli-cms.config :refer [config]] - [babashka.http-client :as http] - [cheshire.core :as json] - [babashka.process :refer [shell]])) - -(defn create-snippet [{:keys [title slug markdown tags]}] - (http/post (str (:backend-host config) "/api/snippet") - {:headers {:content-type "application/json"} - :body (json/encode {:title title :slug slug :markdown markdown :tags tags})})) - -(defn run [] - (let [title (utils/prompt-for "title") - slug (utils/prompt-for "slug") - tags (utils/prompt-for-many "tags") - markdown (utils/prompt-for-long-form "markdown")] - ;; (utils/print "Please enter a title:") - ;; (println "Please enter a title:") - (println (format "TODO: create post with title: %s and slug %s" title slug)) - (println tags) - (println markdown) - (create-snippet {:title title :slug slug :markdown markdown :tags tags}))) diff --git a/src/image_service_cli/delete.clj b/src/image_service_cli/delete.clj deleted file mode 100644 index 8793e78..0000000 --- a/src/image_service_cli/delete.clj +++ /dev/null @@ -1,18 +0,0 @@ -(ns cli-cms.delete - (:require - [cli-cms.cli-utils :as utils] - [cli-cms.config :refer [config]] - [clojure.pprint :refer [pprint]] - [babashka.http-client :as http] - [cheshire.core :as json])) - -(defn fetch-snippets [] - (let [res (http/get (str (:backend-host config) "/api/snippets?limit=25"))] - (json/parse-string (:body res) true))) - -(defn delete-snippet [id] - (http/delete (str (:backend-host config) "/api/snippet") {:query-params {"id" id}})) - -(defn run [] - (let [selected-snippet (utils/select (map #(hash-map :value (:slug %) :item %) (fetch-snippets)))] - (delete-snippet (:id selected-snippet)))) diff --git a/src/image_service_cli/edit.clj b/src/image_service_cli/edit.clj deleted file mode 100644 index 1104d9f..0000000 --- a/src/image_service_cli/edit.clj +++ /dev/null @@ -1,54 +0,0 @@ -(ns cli-cms.edit - (:require - [babashka.http-client :as http] - [clojure.pprint :refer [pprint]] - [cli-cms.config :refer [config]] - [cli-cms.view :as view] - [cheshire.core :as json] - [cli-cms.cli-utils :as utils])) - -(defn fetch-snippets [] - (let [res (http/get (str (:backend-host config) "/api/snippets?limit=25"))] - (json/parse-string (:body res) true))) - -(defn prompt-for-edit-type [] - (utils/select (map #(hash-map :value (name %) :item %)'( - :title - :markdown - :slug - :remove-tag - :add-tags - :done - )))) - -(defn send-patch [id patch] - (http/patch (str (:backend-host config) "/api/snippet") - {:query-params {:id id} - :headers {:content-type "application/json"} - :body (json/encode patch)})) - -(defn edit - ([snippet] - (edit snippet {})) - ([snippet changes] - (case (prompt-for-edit-type) - :title (let [new-title (utils/prompt-for "title" :prefill (:title snippet))] - (edit (assoc snippet :title new-title) (assoc changes :title new-title))) - :slug (let [new-slug (utils/prompt-for "slug" :prefill (:slug snippet))] - (edit (assoc snippet :slug new-slug) (assoc changes :slug new-slug))) - :remove-tag (let [tag-to-remove (utils/select (map #(hash-map :value % :item %) (:tags snippet))) - tags (remove #(= % tag-to-remove) (:tags snippet))] - (edit (assoc snippet :tags tags) (assoc changes :tags tags))) - :add-tags (let [ - new-tags (utils/prompt-for-many "tags") - tags (concat new-tags (:tags snippet))] - (edit (assoc snippet :tags tags) (assoc changes :tags tags))) - :markdown (let [new-markdown (utils/prompt-for-long-form "markdown" :prefill (:markdown snippet))] - (edit (assoc snippet :markdown new-markdown) (assoc changes :markdown new-markdown))) - :done changes))) - -(defn run [] - (let [snippet-to-edit (utils/select (map #(hash-map :value (:slug %) :item %) (fetch-snippets)))] - (send-patch (:id snippet-to-edit) (edit snippet-to-edit)) - (println "Snippet updated successfully") - (view/view (view/fetch-snippet (:id snippet-to-edit))))) diff --git a/src/image_service_cli/index.clj b/src/image_service_cli/index.clj new file mode 100644 index 0000000..0a62c01 --- /dev/null +++ b/src/image_service_cli/index.clj @@ -0,0 +1,51 @@ +;;; Index use-case +;;; Go through all the image files in s3 and save them to sqllite db for easier searching +(ns image-service-cli.index + (:import (java.time LocalDateTime) + (java.time.format DateTimeFormatter)) + (:require + [image-service-cli.config :refer [config]] + [babashka.process :refer [shell]] + [clojure.string :as str] + [com.travisshears.gum-utils :as utils])) + +(defn s3-root-dirs [] + (let [filter-for-dirs (fn [lines] (filter #(re-find #"^\s*PRE" %) lines)) + extract-dir-name (fn [line] + (let [match (re-find #"PRE ([^\/]+)" line)] + (when match + (second match)))) + s3-output (-> + (shell {:out :string :extra-env {"AWS_PROFILE" (:aws-profile config)}} "aws s3 ls" (:s3-root config)) + :out)] + (->> + (str/split s3-output #"\n") + (filter-for-dirs) + (map extract-dir-name)))) + +(def s3-date-formatter (DateTimeFormatter/ofPattern "yyyy-MM-dd HH:mm:ss")) +(defn s3-list-dir [dir] + "List the contents of a directory in S3. Skipping nested directories" + (as-> + (shell {:out :string :extra-env {"AWS_PROFILE" (:aws-profile config)}} "aws s3 ls" (str (:s3-root config) dir "/")) x + (:out x) + (str/split x #"\n") ;; split on newline + (map #(re-find #"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+\d+\s+(.+$)" %) x) ;; convert line into date and file name + (filter #(not (nil? %)) x) ;; remove lines that didn't match + (map #(list (second %) (str dir "/" (last %))) x) ;; remove full match from regex and add dir to filename + (map #(list (LocalDateTime/parse (first %) s3-date-formatter) (second %)) x) + (map #(hash-map :date (first %) :file-name (second %)) x))) + +;; (defn fetch-snippets [] +;; (let [res (http/get (str (:backend-host config) "/api/snippets?limit=25"))] +;; (json/parse-string (:body res) true))) + +;; (defn send-patch [id patch] +;; (http/patch (str (:backend-host config) "/api/snippet") +;; {:query-params {:id id} +;; :headers {:content-type "application/json"} +;; :body (json/encode patch)})) + +(defn run [] + ;; get file names and created dates from s3 + (flatten (map image-service-cli.index/s3-list-dir (image-service-cli.index/s3-root-dirs)))) diff --git a/src/image_service_cli/main.clj b/src/image_service_cli/main.clj index 8176820..ae9a4b7 100644 --- a/src/image_service_cli/main.clj +++ b/src/image_service_cli/main.clj @@ -1,20 +1,19 @@ -(ns cli-cms.main +(ns image-service-cli.main (:require - [cli-cms.create :as create] - [cli-cms.edit :as edit] - [cli-cms.delete :as delete] - [cli-cms.cli-utils :as utils] - [cli-cms.view :as view])) + [babashka.process :refer [shell]] + [com.travisshears.gum-utils :as utils])) -(defn color-test [] - (doseq [color (range 0 255)] - (utils/color-print (str "COLOR --- " color) (str color)))) + (shell (format "gum format \"%s\"" text))) + +(defn prompt-for [placeholder & {:keys [prefill]}] +(defn s3-list [dir] + (let [cmd (if prefill + (format "gum input --placeholder='%s' --value='%s'" placeholder prefill) + (format "gum input --placeholder='%s'" placeholder))] + (str/trim (-> (shell {:out :string} cmd) :out)))) (defn -main [& args] (case (first args) - "create" (create/run) - "delete" (delete/run) - "edit" (edit/run) - "view" (view/run) - "color-test" (color-test) - (println "Missing command. Try create, edit, or delete."))) + "upload" (create/run) + "ls" (delete/run) + (println "Missing command. Try upload or ls."))) diff --git a/src/image_service_cli/view.clj b/src/image_service_cli/upload.clj similarity index 97% rename from src/image_service_cli/view.clj rename to src/image_service_cli/upload.clj index c267dea..f089086 100644 --- a/src/image_service_cli/view.clj +++ b/src/image_service_cli/upload.clj @@ -1,4 +1,4 @@ -(ns cli-cms.view +(ns image-service-cli.upload (:require [babashka.http-client :as http] [clojure.pprint :refer [pprint]]