diff --git a/src/babashka/cli.cljc b/src/babashka/cli.cljc index 68afc2c..05451ff 100644 --- a/src/babashka/cli.cljc +++ b/src/babashka/cli.cljc @@ -1291,6 +1291,11 @@ (when (:cmds node) (throw (ex-info "A tree node contains :cmds (table entry syntax): nest children under :cmd, or pass a table (vector of entries)" {:node node}))) + #?(:squint nil :cljd nil :default + (doseq [k (if (vector? (:cmd node)) (map first (:cmd node)) (keys (:cmd node)))] + (when-not (or (string? k) (symbol? k) (keyword? k)) + (throw (ex-info (str "Command name " (pr-str k) " is not a string, symbol or keyword") + {:node node :key k}))))) (let [;; a vector `:cmd` (pairs `[[name child] ...]`) preserves child order without ;; relying on map iteration order; fold it into the lookup map + `::cmd-order` node (if (vector? (:cmd node)) diff --git a/test/babashka/cli_test.cljc b/test/babashka/cli_test.cljc index 5793bc8..81569ec 100644 --- a/test/babashka/cli_test.cljc +++ b/test/babashka/cli_test.cljc @@ -781,6 +781,13 @@ (take-while #(str/starts-with? % " ")) (mapv #(str/trim %))))))))) +#?(:squint nil :cljd nil :default + (deftest cmd-key-guard-test + (testing "a :cmd key that is not a name throws with an explanation" + (is (thrown-with-msg? + Exception #"is not a string, symbol or keyword" + (cli/dispatch {:cmd {identity {:fn identity}}} ["x"])))))) + (deftest dispatch-exec-fn-test (testing ":exec-fn is called with just the parsed opts; :fn with the whole map" (is (= {:foo 1 :bar true}