diff --git a/figwheel-main/.dir-locals.el b/figwheel-main/.dir-locals.el deleted file mode 100644 index 166468dc..00000000 --- a/figwheel-main/.dir-locals.el +++ /dev/null @@ -1,7 +0,0 @@ -((nil - (eval . (cider-register-cljs-repl-type - 'fm - "(require 'figwheel.main)(figwheel.main/start \"dev\")" - 'cider-verify-piggieback-is-present - )) - (cider-default-cljs-repl . fm))) diff --git a/figwheel-main/.gitignore b/figwheel-main/.gitignore deleted file mode 100644 index d70430a6..00000000 --- a/figwheel-main/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target -.cpcache -*.log diff --git a/figwheel-main/CHANGES.md b/figwheel-main/CHANGES.md deleted file mode 100644 index a7542a43..00000000 --- a/figwheel-main/CHANGES.md +++ /dev/null @@ -1,36 +0,0 @@ -# 0.1.3 - -* enable reloading of dependents, configurable with :reload-dependents -* bump rebel-readline-cljs dep to latest -* fix the helper app so that it only attempts to operate on a DOM node if it is present -* added new evalback functionality which gives the client the ability to evaluate cljs - through the figwheel REPL connection -* fixed a problem where js/require couldn't be invoked from the REPL in Node -* ensure that repl warnings don't make it into the source code for a required ns -* added some helper content for the new figwheel-main-template -* validate that symbols in config don't start with quotes (a very common mistake) - -# 0.1.2 Fix for Java 9/10 - -* fix classloader bug that prevented figwheel.main from starting Java 9/10 -* fix NPE when nonexistant namespace is provided as main ns - -# 0.1.1 Classpath Repair, Devtools and Helper App - -* add helper app to provide contextual information when launching `figwheel.main` -* fix case when target directory is on the classpath but does not - exist, as resources will not resolve in this case -* warn when there is a `resources/public/index.html` and the `resources` - directory is not on the classpath -* ensure that the watched directories are on the classpath -* ensure that the watched directories have source files -* ensure the directory, that the `:main` ns is in, is on the classpath -* auto include `binaryage/devtools` in opt none builds targeting the browser -* fixed bug where providing a `:ring-handler` in build metadata didn't work -* fixed bug where single compiles with the -c option were not working for optimization - levels other than none -* add `:client-log-level` option to set the level for client side logging -* fixed problem where node target builds were launching a browser -* fixed undefined var warnings in the REPL by ensuring full analysis on REPL start - -# 0.1.0 Initial Release diff --git a/figwheel-main/Makefile b/figwheel-main/Makefile deleted file mode 100644 index f902c689..00000000 --- a/figwheel-main/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# makefile for figwheel.main -PROJECT_FILES=../figwheel-core/project.clj ../figwheel-repl/project.clj project.clj -DOC_FILES=README.md helper-content/*.md -DEPS_FILES=deps.edn - -# sed commands for changing version strings -CHANGE_LEIN_DEPS=sed -i '' -e "s|\[com.bhauman/figwheel-\([^[:space:]]*\) \"[^\"]*\"\]|[com.bhauman/figwheel-\1 \"$(VERSION)\"]|g" -CHANGE_TOOLS_DEPS=sed -i '' -e "s|com.bhauman/figwheel-\([^[:space:]]*\) {:mvn/version \"[^\"]*\"}|com.bhauman/figwheel-\1 {:mvn/version \"$(VERSION)\"}|g" -CHANGE_TOOLS_DEPS_ESC=sed -i '' -e "s|com.bhauman/figwheel-\([^[:space:]]*\) {:mvn/version \\\\\"[^\"]*\\\\\"}|com.bhauman/figwheel-\1 {:mvn/version \\\\\"$(VERSION)\\\\\"}|g" -MARKDOWN=ruby scripts/kram.rb - -deps-version: - sed -i '' -e "s|defproject com.bhauman/figwheel-\([^[:space:]]*\) \"[^\"]*\"|defproject com.bhauman/figwheel-\1 \"$(VERSION)\"|g" $(PROJECT_FILES) - $(CHANGE_LEIN_DEPS) $(PROJECT_FILES) - $(CHANGE_TOOLS_DEPS) $(DEPS_FILES) - -docs-version: - $(CHANGE_LEIN_DEPS) $(DOC_FILES) - $(CHANGE_TOOLS_DEPS) $(DOC_FILES) - $(CHANGE_TOOLS_DEPS_ESC) $(DOC_FILES) - -snapshot-version: deps-version - -release-version: deps-version docs-version - -helper-docs: - $(MARKDOWN) helper-content/* - -opt-docs: - clojure -Adocs - -docs: helper-docs opt-docs - -helper: - clojure -Abuild-helper - -clean: - rm -rf target - -clean-m2: - rm -rf ~/.m2/repository/com/bhauman - rm -rf .cpcache - -install: clean - pushd ../figwheel-core; lein install; popd; pushd ../figwheel-repl; lein install; popd; lein install - -test10: clean - jenv local 10.0 - lein test - jenv local 1.8 - -testit: clean - lein test - -testall: testit test10 - -deploy: clean install docs helper testall - pushd ../figwheel-core; lein deploy clojars; popd; pushd ../figwheel-repl; lein deploy clojars; popd; lein deploy clojars diff --git a/figwheel-main/README.md b/figwheel-main/README.md index e56ebd68..72af08f5 100644 --- a/figwheel-main/README.md +++ b/figwheel-main/README.md @@ -1,359 +1,5 @@ -# figwheel-main +# Figwheel Main has moved -[![Clojars Project](https://img.shields.io/clojars/v/com.bhauman/figwheel-main.svg)](https://clojars.org/com.bhauman/figwheel-main) +Figwheel Main now has it's own repository at +[https://github.com/bhauman/figwheel-main](https://github.com/bhauman/figwheel-main) -Figwheel Main is intended to provide a `cljs.main` like command line -experience for ClojureScript that also provides the many features that -were first developed in `lein-figwheel` but better. - -* Hot Code Reloading -* Stable multiplexing REPL connection -* CSS reloading -* Heads-up display for compile time errors -* Pop to editor from heads-up display -* Built in ring development server - -`figwheel-main` is a **complete rewrite** of original figwheel. All of the -above features have been improved significantly. - -* Hot code reloading has been significantly revamped. -* The REPL now only evals on one client and allows you to choose which one at runtime. -* The built-in ring server is now the ring-jetty-adapter which will - allow the use of HTTPS, and extensive configuration of the server itself -* the built-in ring server now uses `ring-defaults` and allows - extensive configuration of the middleware -* the amount of config needed to get started has been significantly - reduced -* the configuration options have been simplified - -The new architecture also makes it trivial to add your own development -tools that can communicate from the server to your client. - -> Currently ONLY works for a browser and Node environments - -> Currently still undergoing heavy development. Stuff will most certainly change. - -> This documentation is incomplete and intended to help you take the new figwheel -> for a spin before its official release. - -## Get started with the template - -Get a working example up and running quickly with the [figwheel.main template](http://rigsomelight.com/figwheel-main-template/) - -## Quick Usage - -> It is assumed that you have perused https://clojurescript.org/guides/quick-start - -First, make sure you have the [Clojure CLI Tools](https://clojure.org/guides/getting_started) -installed. - -On Mac OSX with brew: - - brew install clojure - -Now launch a ClojureScript REPL with: - -``` -clj -Sdeps "{:deps {com.bhauman/figwheel-main {:mvn/version \"0.1.3\"}}}}" -m figwheel.main -``` - -This will first compile browser REPL code to a temp directory, and -then a browser will open and a `cljs.user=>` prompt will appear. - -From here you can do REPL driven development of ClojureScript. - -You can also use `leiningen` by adding it to `:dependencies` in your -`project.clj` and launching it like so: - -``` -lein run -m figwheel.main -``` - -**With Rebel Readline for much better REPL experience** - -Figwheel main will automatically use `rebel-readline-cljs` it is -available. So you can get Rebel Readline behavior by simply adding it -to your dependencies. - -``` -clojure -Sdeps "{:deps {com.bhauman/figwheel-main {:mvn/version \"0.1.3\"} com.bhauman/rebel-readline-cljs {:mvn/version \"0.1.4\"}}}}" -m figwheel.main -``` - -As of right now Rebel readline does create some startup overhead -(hoping to correct this in the near future), so you may want to choose -use it only when you are going to interact at the REPL. - -**Creating a build** - -To define a build which will allow you work on a set of files and hot -reload them. - -Ensure your `deps.edn` file has `figwheel.main` dependencies: - -```clojure -{:deps {com.bhauman/figwheel-main {:mvn/version "0.1.3"} - com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}} - ;; setup common development paths that you may be used to - ;; from lein - :paths ["src" "target" "resources"]} -``` - -Create a file `dev.cljs.edn` build file: - -```clojure -{:main example.core} -``` - -And in `src/example/core.cljs` - -```clojure -(ns example.core) -(enable-console-print!) -(prn "hello world!") -``` - -and run the command: - -``` -clojure -m figwheel.main -b dev -r -``` - -This will launch a REPL and start autobuilding and reloading the `src` -directory so that any files you add or change in that directory will -be automatically hot reloaded into the browser. - -The `-b` or `--build` flag is indicating that we should read -`dev.cljs.edn` for configuration. - -The `-r` or `--repl` flag indicates that a repl should be launched. - -Interesting to note that the above command is equivalent to: - -``` -clojure -m figwheel.main -co dev.cljs.edn -c -r -``` - -Note: that if you want to add your own `index.html` file to host your -application, if you have added `resources` to your "deps.edn" `:paths` -key, as demonstrated above, you can place the `index.html` in -`resources/public/index.html` - -## Configuring Figwheel Main - -If you need to configure figwheel.main, place a `figwheel-main.edn` -in the same directory that you will be executing it from. - -If you need to override some of the figwheel configuration options for a -particular build, simply add those options as meta data on the build edn. - -For example if you want to have `:watch-dirs` that are specific to the -"dev" build then in `dev.cljs.edn` - -```clojure -^{:watch-dirs ["cljs-src"] - :css-dirs ["resources/public/css"]} -{:main example.core} -``` - -All the available configuration options are documented here: -https://github.com/bhauman/lein-figwheel/blob/master/figwheel-main/doc/figwheel-main-options.md - -All the available configuration options specs are here: -https://github.com/bhauman/lein-figwheel/blob/master/figwheel-main/src/figwheel/main/schema.clj - -## Classpaths, Classpaths, Classpaths - -Understanding of the Java Classpath can be very helpful when working -with ClojureScript. - -ClojureScript searches for source files on the Classpath. When you add -a `re-frame` dependency like so: - -```clojure -{:deps {com.bhauman/figwheel-main {:mvn/version "0.1.3"} - com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"} - ;; adding re-frame - re-frame {:mvn/version "1.10.5"}} - :paths ["src" "target" "resources"]} -``` - -The source files in `re-frame` are on the Classpath and the -ClojureScript compiler can find `re-frame.core` when you require it. - -Your sources will need to be on the Classpath so that the Compiler can -find them. For example, if you have a file -`cljs-src/example/core.cljs` you should add `cljs-src` to the `:paths` -key so that the ClojureScript compiler can find your `example.core` -namespace. It is important to note that the `src` directory is on your -Classpath by default. - -In Figwheel, the embedded HTTP server serves its files from the Java -Classpath. - -It actually serves any file it finds in on a Classpath in a `public` -sub-directory. This is why we added `target` and `resources` to the -`:paths` key in the `deps.edn` file above. With `target` and -`resources` both on the Classpath the server will be able to serve -anyfile in `target/public` and `resources/public`. - -The compiler by default compiles artifacts to `target` for easy cleaning. - -It is custmary to put your `index.html`, CSS files, and other -web artifacts in the `resources/public` directory. - -## Working with Node.js - -Unlike `cljs.main`, with `figwheel.main` you will not specify a -`--repl-env node` because the `figwheel.repl` handles Node.js REPL -connections in addition to others. - -You can launch a Node REPL like so: - - clojure -m figwheel.main -t node -r - -You can quickly get a hot reloading CLJS node build up an running using the -`deps.edn`, `example.core` and `dev.cljs.edn` above. Simply add a `--target node` -or `-t node` to the compile command. - - clojure -m figwheel.main -t node -b dev -r - -This will launch a CLJS Node REPL initialized with `example.core` you -can now edit `example/core.cljs` and it will be hot reloaded. - -Of course if you add `:target :nodejs` to `dev.cljs.edn` like so: - -```clojure -{:main example.core - :target :nodejs} -``` - -You be able to run the build more simply: - - clojure -m figwheel.main -b dev -r - -## Reload hooks - -It is common to want to provide callbacks to do some housekeeping -before or after a hot reload has occurred. - -You can conveniently configure hot reload callbacks at runtime with -metadata. You can see and example of providing callbacks below: - -```clojure -;; first notify figwheel that this ns has callback defined in it -(ns ^:figwheel-hooks example.core) - -;; mark the hook functions with ^:before-load and ^:after-load -;; metadata - -(defn ^:before-load my-before-reload-callback [] - (println "BEFORE reload!!!")) - -(defn ^:after-load my-after-reload-callback [] - (println "AFTER reload!!!")) -``` - -The reload hooks will be called before and after every hot code reload. - -## Quick way for experienced devs to understand the command line options - -You can supply a `-pc` or `--pprint-config` flag to `figwheel.main` -and it will print out the computed configuration instead of running -the command. - -For example: - -``` -clojure -m figwheel.main -pc -b dev -r -``` - -Will output: - -```clojure ----------------------- Figwheel options ---------------------- -{:ring-server-options {:port 9550}, - :client-print-to [:repl :console], - :pprint-config true, - :watch-dirs ("src"), - :mode :repl} ----------------------- Compiler options ---------------------- -{:main exproj.core, - :preloads [figwheel.core figwheel.main figwheel.repl.preload], - :output-to "target/public/cljs-out/dev-main.js", - :output-dir "target/public/cljs-out/dev", - :asset-path "cljs-out/dev", - :aot-cache false, - :closure-defines - #:figwheel.repl{connect-url - "ws://localhost:9550/figwheel-connect?fwprocess=c8712b&fwbuild=dev", - print-output "repl,console"}} -``` - -## Using figwheel.main from a script - -See the `figwheel.main/start` function and the `figwheel.main/start-join` functions. - -## Contributing to the Helper App - -Figwheel main comes with a helper Ring app that is served when there -is no other html page to host the REPL JavaScript env. - -If you are interested in contributing to this app: - -First hit me up in #figwheel-main channel on the clojurians Slack so -that we can coordinate a bit. - -To work on the helper app: - -Checkout this repository and change directory to the `figwheel-main` -directory where this README is located. - -Then the command - -```shell -clj -m figwheel.main -b helper -r -``` - -should launch a live development workflow for the Helper application. - -**tweaking the CSS** - -The **CSS** files for the helper app are located at -`helper-resources/public/com/bhauman/figwheel/helper/css` and you -should be able to edit them live. - -**working on the app itself** - -Both the server-side and client side code are located in -`src/figwheel/main/helper.cljc` and you should be able to work on them -live. - -If you change the behavior of the CLJS in -`src/figwheel/main/helper.cljc` it will not be reflected in the actual -helper app until you compile with `make helper` - -**editing helper content** - -The helper app content is generated from the Markdown files in the -`helper-content` directory. You must compile the markdown with `make -helper-docs` this currently requires `ruby` and **kramdown** (`gem -install kramdown`) - -**keep it simple** - -The helper app is intended to be very simple in structure. We do not want to -add more dependencies and slow the startup time of `figwheel.main`, -and we also do not want to do anything that will interfere with the -users running code. - -## More to come ... - -Figwheel Main aims to honor all the flags provided by `cljs.main`, as -of right now, your mileage may vary. - -## License - -Copyright © 2018 Bruce Hauman - -Distributed under the Eclipse Public License either version 1.0 or any -later version. diff --git a/figwheel-main/deps.edn b/figwheel-main/deps.edn deleted file mode 100644 index f239b412..00000000 --- a/figwheel-main/deps.edn +++ /dev/null @@ -1,44 +0,0 @@ -{:deps {org.clojure/clojure {:mvn/version "1.9.0"} - org.clojure/clojurescript {:mvn/version "1.10.238"} - com.bhauman/figwheel-repl {:mvn/version "0.1.3"} - com.bhauman/figwheel-core {:mvn/version "0.1.3"} - - ;; server - ring {:mvn/version "1.6.3"} - org.eclipse.jetty.websocket/websocket-servlet {:mvn/version "9.2.21.v20170120"} - org.eclipse.jetty.websocket/websocket-server {:mvn/version "9.2.21.v20170120"} - - ;; file watching - hawk {:mvn/version "0.2.11"} - - ;; possibly external - binaryage/devtools {:mvn/version "0.9.10"} - - ;; going to make validation seperate? - expound {:mvn/version "0.7.0"} - com.bhauman/spell-spec {:mvn/version "0.1.0"}} - - :paths ["src" "helper-resources"] - - :aliases {:build-helper - {:main-opts ["-m" - "figwheel.main" - "-co" "helper.cljs.edn" - "-o" - "helper-resources/public/com/bhauman/figwheel/helper.js" - "-O" - "advanced" - "-c" - "figwheel.main.helper"]} - :docs - {:extra-paths ["dev"] - :main-opts ["-e" (build-option-docs)]} - :rebel - {:extra-deps {com.bhauman/rebel-readline-cljs {:mvn/version "0.1.3"}}} - :dev - {:extra-deps - {com.bhauman/figwheel-core {:local/root "/Users/bhauman/workspace/lein-figwheel/figwheel-core"} - com.bhauman/figwheel-repl {:local/root "/Users/bhauman/workspace/lein-figwheel/figwheel-repl"}} - :extra-paths ["target" "devel" "dev"]}} - - } diff --git a/figwheel-main/dev/user.clj b/figwheel-main/dev/user.clj deleted file mode 100644 index 3d0abd94..00000000 --- a/figwheel-main/dev/user.clj +++ /dev/null @@ -1,6 +0,0 @@ -(ns user - (:require [figwheel.server.ring] - [figwheel.main.schema.config])) - -(defn build-option-docs [] - (figwheel.main.schema.core/output-docs "doc/figwheel-main-options.md")) diff --git a/figwheel-main/devel/exproj/core.cljs b/figwheel-main/devel/exproj/core.cljs deleted file mode 100644 index a270f4e9..00000000 --- a/figwheel-main/devel/exproj/core.cljs +++ /dev/null @@ -1,46 +0,0 @@ -(ns exproj.core - (:require - [goog.events] - [goog.object :as gobj] - [clojure.string :as string] - [exproj.other] - [cljs.test :refer [deftest is]])) - -(enable-console-print!) - -(defn hello [] - "hello exproj") - -(defn ^:after-load after-hook [] - (js/console.log "Called the AFTER hook!!!")) - -(defn ^:before-load befor-hook [& args] - (js/console.log "Called the before hook!!!")) - -(deftest this-is-a-test - (prn "hello") - (is false)) - - - -#_(d) - -;; stable reference -#_(defonce after-load (fn [e] (prn :after (.. e -data)))) -;; idempotent with stable reference -#_(.addEventListener js/document.body "figwheel.after-load" after-load) -#_(cljs.pprint/pprint (deref js/figwheel.core.state)) -#_(defonce before-load (fn [e] (prn :before (.. e -data)))) -;; idempotent with stable reference -#_(.addEventListener js/document.body "figwheel.before-load" before-load) - -#_(defonce after-css-load (fn [e] (prn :after-css-load (.. e -data)))) -;; idempotent with stable reference -#_(.addEventListener js/document.body "figwheel.after-css-load" after-css-load) - -(defn -main [& args] - (prn 35) - 35) - -#_(defn) -#_(d d d d d d d) diff --git a/figwheel-main/devel/exproj/other.cljs b/figwheel-main/devel/exproj/other.cljs deleted file mode 100644 index 8b9d93b0..00000000 --- a/figwheel-main/devel/exproj/other.cljs +++ /dev/null @@ -1,5 +0,0 @@ -(ns exproj.other) - -(defn hello-there [] "hello there") - - diff --git a/figwheel-main/devel/exproj/server.clj b/figwheel-main/devel/exproj/server.clj deleted file mode 100644 index eac9b885..00000000 --- a/figwheel-main/devel/exproj/server.clj +++ /dev/null @@ -1,6 +0,0 @@ -(ns exproj.server) - -(defn handler [r] - {:status 404 - :headers {"Content-Type" "text/html"} - :body "Server is working"}) diff --git a/figwheel-main/devver.cljs.edn b/figwheel-main/devver.cljs.edn deleted file mode 100644 index 9a29ba3f..00000000 --- a/figwheel-main/devver.cljs.edn +++ /dev/null @@ -1,3 +0,0 @@ -^{:watch-dirs ["src"]} -{:main exproj.core - :hi 1} diff --git a/figwheel-main/doc/command-line-semantics.md b/figwheel-main/doc/command-line-semantics.md deleted file mode 100644 index 65845560..00000000 --- a/figwheel-main/doc/command-line-semantics.md +++ /dev/null @@ -1,95 +0,0 @@ -# Questions/Explorations about the semantics of command line combinations - -#### What command line args will cause figwheel to autobuild and insert code to establish a repl connection? - -For the following examples assume `dev.cljs.edn` is in the current -directory and contains: - -```clojure -{:main example.core} -``` - -Acknowledge that there is need to simply autobuild without a server or -server connection. - - -w src -c example.core - -This should autobuild without a server or repl connection. If one -wants to supply the compile options resident in a figwheel build -config file (i.e. dev.cljs.edn) one can simply pass that config as a -normal `cljs.main` `-co` flag arg: - - -w src -co dev.cljs.edn -c - -and the above will not insert any repl or figwheel functionality into -the build or build process. - -The same is true for a single compile without watching of any kind. - - -co dev.cljs.edn -c - -and - - -c example.core - -should only compile once and have no figwheel libraries or -other functionality inserted into it. - -But once you add a `--repl` or `-serve` flag to the operation and the -compile `:optimizations` level is `:none` then figwheel specific -functionality will come into play. - -So for a command of: - - -co dev.cljs.edn -c -r - -Figwheel main will take actions to try and create a figwheel -autobuilding development session. - -1. a build name `dev` will be infered from the `dev.cljs.edn` file name -1. if no configured watch directories are found `figwheel.main` will - try to infer one from the given namespace if it can find it -2. it will insert `[figwheel.repl.preload figwheel.core figwheel.main]` into - the `:preloads` of the compile options -3. it will add a `figwheel.repl/connect-url` and perhaps some other - configuration into `:closure-defines` of the compile options -4. it will start a server, repl, and launch a browser to connect to - the repl server - -When you only ask for a server via: - - -co dev.cljs.edn -c -s - -A REPL will not be launched but all of the above steps will still be taken. - -There is a shortcut *main* option flag `-b` or `--build` which can be -used in place of the `-c` flag. - -The following examples are equivalient - - -b dev -r == -co dev.cljs.edn -c -r - - -b dev -s == -co dev.cljs.edn -c -s - - -b dev == -co dev.cljs.edn -c -s - -So when you use the `--build` flag you will normally get a server as well. - -#### How to build once with the `--build-once` or `-bo` flag - -#### Background builds and the `--bb` flag - -#### Turning various features off - -#### How do I better determine the behavior of a set of command line args? - -There is a `--pprint-config` or `-pc` *init* arg which when added to -the command line like so: - - -pc -co dev.cljs.edn -c example.core -s - -Will print out useful information about the resulting configuration. - - - - diff --git a/figwheel-main/doc/figwheel-main-options.md b/figwheel-main/doc/figwheel-main-options.md deleted file mode 100644 index 2179c4de..00000000 --- a/figwheel-main/doc/figwheel-main-options.md +++ /dev/null @@ -1,407 +0,0 @@ -# Figwheel Main Configuration Options - -The following options can be supplied to `figwheel.main` via the `figwheel-main.edn` file. - -# Commonly used options (in order of importance) - -## :watch-dirs - -A list of ClojureScript source directories to be watched and compiled on change. - - :watch-dirs ["cljs-src"] - -## :css-dirs - -A list of CSS source directories to be watched and reloaded into the browser. - - :css-dirs ["resource/public/css"] - -## :ring-handler - -A symbol or string indicating a ring-handler to embed in the -figwheel.repl server. This aids in quickly getting a dev server up and -running. If the figwheel server doesn't meet your needs you can simply -start your own server, the figwheel.client will still be able to -connect to its websocket endpoint. -Default: none - - :ring-handler my-project.server/handler - -## :ring-server-options - -All the options to forward to the `ring-jetty-adapter/run-jetty` function -which figwheel.main uses to run its ring server. - -All the available options are documented here: -https://github.com/ring-clojure/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj#L127 - -This will normally be used to set the `:port` and `:host` of the server. - -Most uses of these options are considered advanced if you find -yourself using many of these options you problably need to run your -own server outside of figwheel.main. - -## :rebel-readline - -By default Figwheel engauges a Rebel readline editor when it starts -the ClojureScript Repl in the terminal that it is launched in. - -This will only work if you have `com.bhauman/rebel-readline-cljs` in -your dependencies. - -More about Rebel readline: -https://github.com/bhauman/rebel-readline - -Default: true - - :rebel-readline false - -## :pprint-config - -When `:pprint-config` is set to true. The `figwheel.main` will print the -computed config information and will terminate the process. Useful for -understanding what figwheel.main adds to your configuration before it -compiles your build. - -Default: false - - :pprint-config true - -## :open-file-command - -A path to an executable shell script that will be passed a file and -line information for a particular compilation error or warning. - -A script like this would work -ie. in ~/bin/myfile-opener - - #! /bin/sh - emacsclient -n +$2:$3 $1 - -The add this script in your config: - - :open-file-command "myfile-opener" - -But thats not the best example because Figwheel handles `emacsclient` -as a special case so as long as `emacsclient` is on the shell path you can -simply do: - - :open-file-command "emacsclient" - -and Figwheel will call emacsclient with the correct args. - -## :figwheel-core - -Wether to include the figwheel.core library in the build. This - enables hot reloading and client notification of compile time errors. - Default: true - - :figwheel-core false - -## :hot-reload-cljs - -Whether or not figwheel.core should hot reload compiled -ClojureScript. Only has meaning when :figwheel is true. -Default: true - - :hot-reload-cljs false - -## :reload-dependents - -Whether or not figwheel.core should reload reload the namespaces -that `depend` on the changed namespaces in addition to the changed -namespaces themselves. Only has meaning when :figwheel is true. -Default:true - - :reload-dependents false - -## :connect-url - -The url that the figwheel repl client will use to connect back to -the server. - -This url is actually a template that will be filled in. For example -the default `:connect-url` is: - - "ws://[[config-hostname]]:[[server-port]]/figwheel-connect" - -The available template variables are: - -For the server side: - - [[config-hostname]] the host supplied in :ring-server-options > :host or "localhost" - [[server-hostname]] the java.InetAddress localhost name - "Bruces-MacBook-Pro.local" on my machine - [[server-ip]] the java.InetAddress localhost ip interface - normally 192.168.x.x - [[server-port]] the port supplied in :ring-server-options > :port or the default port 9500 - -On the client side: - - [[client-hostname]] the js/location.hostname on the client - [[client-port]] the js/location.port on the client - -If the url starts with a Websocket scheme "ws://" a websocket -connection will be established. If the url starts with an http scheme -"http" an http long polling connection will be established. - -## :open-url - -Either a boolean value `false` or a string that indicates the url -that the figwheel repl will open in the browser after the source code -has been compiled. A `false` value will disable this behavior. - -The string value is actually a template that can provide optional -template variables. For example the default `:open-url` is: - - "http://[[server-hostname]]:[[server-port]]" - -The available template variables are: - -For the server side: - - [[server-hostname]] the host supplied in :ring-server-options > :host or "localhost" - [[server-port]] the port supplied in :ring-server-options > :port or the default port 9500 - -## :reload-clj-files - -Figwheel naively reloads `clj` and `cljc` files on the `:source-paths`. -It doesn't reload clj dependent files like tools.namspace. - -Figwheel does note if there is a macro in the changed `clj` or `cljc` file -and then marks any cljs namespaces that depend on the `clj` file for -recompilation and then notifies the figwheel client that these -namespaces have changed. - -If you want to disable this behavior: - - :reload-clj-files false - -Or you can specify which suffixes will cause the reloading - - :reload-clj-files #{:clj :cljc} - -## :log-file - -The name of a file to redirect the figwheel.main logging to. This -will only take effect when a REPL has been started. - - :log-file "figwheel-main.log" - -## :log-level - -The level to set figwheel.main java.util.logger to. -Can be one of: `:error` `:info` `:debug` `:trace` `:all` `:off` - - :log-level :error - -## :client-log-level - -The log level to set the client side goog.log.Logger to for -figwheel.repl and figwheel.core. Can be one of: -`:severe` `:warning` `:info` `:config` `:fine` `:finer` `:finest` - - :client-log-level :warning - -## :log-syntax-error-style - -figwheel.main logging prints out compile time syntax errors which -includes displaying the erroneous code. -Setting `:log-syntax-error-style` to `:concise` will cause the logging to -not display the erroneous code. -Available options: `:verbose`, `:concise` -Default: `:verbose` - - :log-syntax-error-style :concise - -## :load-warninged-code - -If there are warnings in your code emitted from the compiler, figwheel -does not refresh. If you would like Figwheel to load code even if -there are warnings generated set this to true. -Default: false - - :load-warninged-code true - -## :ansi-color-output - -Figwheel makes an effort to provide colorful text output. If you need -to prevent ANSI color codes in figwheel output set `:ansi-color-output` -to false. Default: true - - :ansi-color-output false - -## :validate-config - -Whether to validate the figwheel-main.edn and build config (i.e.".cljs.edn") files. -Default: true - - :validate-config false - -## :validate-cli - -Whether to validate the figwheel-main command line options -Default: true - - :validate-cli false - -## :target-dir - -A String that specifies the target directory component of the path -where figwheel.main outputs compiled ClojureScript - -The default `:output-dir` is composed of: - - [[:target-dir]]/public/cljs-out/[[build-id]] - -The default `:output-to` is composed of: - - [[:target-dir]]/public/cljs-out/[[build-id]]-main.js - -If you are using the default figwheel.repl server to serve compiled -assets, it is very important that the :target-dir be on the classpath. - -The default value of `:target-dir` is "target" - - :target-dir "cljs-target" - -## :launch-node - -A boolean that indicates wether you want figwheel to automatically -launch Node. Defaults to true. - -## :inspect-node - -A boolean that indicates wether you want figwheel to enable remote -inspection by adding "--inspect" when it launches Node. -Defaults to true. - -## :node-command - -A String indicating the Node.js executable to launch Node with. -Defaults to "node" - -## :cljs-devtools - -A boolean that indicates wether to include binaryage/devtools into -the your clojurescript build. Defaults to true when the target is a -browser and the :optimizations level is :none, otherwise it is false. - - :cljs-devtools false - -# Rarely used options - -## :client-print-to - -The `figwheel.repl` client can direct printed (via pr) output to the -repl and or the console. `:client-print-to` is a list of where you -want print output directed. The output choices are `:console` and `:repl` -Default: [:console :repl] - - :client-print-to [:console] - -## :ring-stack - -The fighweel server has a notion of a `:ring-stack`. The -`:ring-stack` is a composition of basic ring-middleware (think -sessions) to wrap around a supplied `:ring-handler`. - -The default `:ring-stack` is a slightly modified -`ring.middleware.defaults/wrap-defaults` - -## :ring-stack-options - -The fighweel.repl server has a notion of a `:ring-stack`. The -`:ring-stack` is a composition of basic ring-middleware to wrap around -a supplied `:ring-handler`. - -The default `:ring-stack` is a slightly modified -ring.middleware.defaults/wrap-defaults. - -`:ring-stack-options` are the options that figwheel.repl supplies to -`ring.middleware.defaults/wrap-defaults`. - -The default options are slightly modified from `ring.middleware.defaults/site-defaults`: - -``` -{:params - {:urlencoded true, :multipart true, :nested true, :keywordize true}, - :cookies true, - :session - {:flash true, :cookie-attrs {:http-only true, :same-site :strict}}, - :static {:resources "public"}, - :responses {:content-types true, :default-charset "utf-8"}, - :figwheel.server.ring/dev - {:figwheel.server.ring/fix-index-mime-type true, - :figwheel.server.ring/resource-root-index true, - :figwheel.server.ring/wrap-no-cache true, - :ring.middleware.not-modified/wrap-not-modified true, - :co.deps.ring-etag-middleware/wrap-file-etag true, - :ring.middleware.cors/wrap-cors true, - :ring.middleware.stacktrace/wrap-stacktrace true}} -``` - -You can override these options by suppling your own to `:ring-stack-options` - -If these options are changed significantly don't be suprised if the -figwheel stops behaving correctly :) - -## :wait-time-ms - -The number of milliseconds to wait before issuing reloads. Set this -higher to wait longer for changes. This is the interval from when the first -file change occurs until we finally issue a reload event. - -Default: 50 - - :wait-time-ms 50 - -## :mode - -The `:mode` indicates the behavior that occurs after a compile. -Options: `:repl` `:serve` or `:build-once` - -* `:repl` indicates that repl sill be started -* `:serve` indicates that a server will be started -* `:build-once` indicates that a compile will not be follwed by any action - -This is mainly intended for use when you are launching figwheel.main from a script. - -Normally defaults to `:repl` - -## :broadcast-reload - -Figwheel broadcasts hot reloads to all clients that have connected -since the figwheel process has started. Set `:broadcast-reload` to -`false` if you want to only send hot-reloads to the client where the -REPL eval occurs. -Default: true - - :broadast-reload false - -## :broadcast - -In the past figwheel would broadcast REPL evaluations to all -connected clients and then print the first result received in the -REPL. Setting `:broadcast` to `true` will give you back this legacy -behavior. Default: false - - :broadcast true - -## :repl-eval-timeout - -The time (in milliseconds) it takes for the repl to timeout. -Evaluating any given expression in cljs can take some time. -The repl is configured to throw a timeout exception as to not hang forever. - -This config option will determine how long the repl waits for the result of an eval -before throwing. - -Default: 8000 - - :repl-eval-timeout 10000 ;;waits for 10 seconds instead of 8 - -## :hawk-options - -If you need to watch files with polling instead of FS events. This can -be useful for certain docker environments. - - :hawk-options {:watcher :polling} \ No newline at end of file diff --git a/figwheel-main/helper-content/creating_a_build_cli_tools.md b/figwheel-main/helper-content/creating_a_build_cli_tools.md deleted file mode 100644 index 1d34c7c3..00000000 --- a/figwheel-main/helper-content/creating_a_build_cli_tools.md +++ /dev/null @@ -1,145 +0,0 @@ -# Setting up a Figwheel build - -If you are ready to start working on a project with Figwheel Main then -it will be most helpful to set up a **build**. - -> A **build** is the configuration of a compile task, that determines -> what files get compiled with a certain set of compile options. A -> build also optionally configures the which features Figwheel -> enguages while you are working on your application. - -#### deps.edn - -First off, it is assumed that if you made it this far you already have -a `deps.edn` file in the directory that you launched this REPL from. - -If don't have a `deps.edn` file let's create one now: - -```clojure -{:deps {com.bhauman/figwheel-main {:mvn/version "0.1.3"} - ;; add rebel-readline for advanced REPL readline editing - com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}} - :paths ["src" "target" "resources"]} -``` - -#### dev.cljs.edn - -Next you will need to create a minimal **build** configuration. We will -create a configuration file for a build named `dev`. - -In `dev.cljs.edn`: - -```clojure -{:main hello.core} -``` - -At the very least you will need to define the entry point to your -build, i.e. the top level namespace for your build. - -There are many other -[compile options](https://clojurescript.org/reference/compiler-options) -that you can configure in this file. For most cases however all you -will need is the above. - -### src/hello/core.cljs - -Next let's create an initial ClojureScript file for our project. - -In `src/hello/core.cljs` put: - -```clojure -(ns hello.core) - -(enable-console-print!) - -(defn hello [] "hello There") - -;; uncomment this to alter the provided "app" DOM element -;; (set! (.-innerHTML (js/document.getElementById "app") (hello))) - -(println (hello)) -``` - -### resources/public/index.html (optional) - -The `resources/public/index.html` file is optional because Figwheel -provides a default one (much like the page you are looking at now) and -you can get pretty far overriding the html element `
`. - -If you want to provide your own `index.html` here's one you can start -from the following example. - -In `resources/public/index.html` put: - -```html - - - - - -
- - - -``` - -## Building the build - -Once you have your files in place, the file tree should at least look like this: - -```text -hello-world -├─ dev.cljs.edn -├─ deps.edn -└─ src - └─ hello_world <- underscore is very important here - └─ core.cljs -``` - -Now you can start an auto-building / hot-reloading process. - -In the directory that is the root of the project (the `hello-world` directory), -execute the following shell command. - -```shell -clojure -m figwheel.main -b dev -r -``` - -This will launch and autobuild process that compiles your code as you -save it. A browser window will pop open and the terminal that you -launched the command from will now be running a ClojureScript REPL that -is attached to the browser. - -From here you will be able to edit the ClojureScript file and have it -hot loaded into the browser on save. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/figwheel-main/helper-content/creating_a_build_lein.md b/figwheel-main/helper-content/creating_a_build_lein.md deleted file mode 100644 index 8b0e3e73..00000000 --- a/figwheel-main/helper-content/creating_a_build_lein.md +++ /dev/null @@ -1,122 +0,0 @@ -# Setting up a Figwheel build with leiningen - -If you are ready to start working on a project with Figwheel Main and -[Leiningen](https://leiningen.org/) then it will be most helpful to -set up a **build**. - -> A **build** is the configuration of a compile task, that determines -> what files get compiled with a certain set of compile options. A -> build also optionally configures the which features Figwheel -> enguages while you are working on your application. - -#### project.clj - -First off, it is assumed that if you made it this far you already have -a `project.clj` file in the directory that you launched this REPL from. - -If don't have a `project.clj` file let's create one now: - -```clojure -(defproject lein-main "0.1.0-SNAPSHOT" - :profiles {:dev {:dependencies - [[com.bhauman/figwheel-main "0.1.3"] - [com.bhauman/rebel-readline-cljs "0.1.4"]]}} - :aliases {"fig" ["trampoline" "run" "-m" "figwheel.main"]}) -``` - -Above we created an alias to help us launch figwheel as a leiningen task. - -#### dev.cljs.edn - -Next you will need to create a minimal **build** configuration. We will -create a configuration file for a build named `dev`. - -In `dev.cljs.edn`: - -```clojure -{:main hello.core} -``` - -At the very least you will need to define the entry point to your -build, i.e. the top level namespace for your build. - -There are many other -[compile options](https://clojurescript.org/reference/compiler-options) -that you can configure in this file. For most cases however all you -will need is the above. - -### src/hello/core.cljs - -Next let's create an initial ClojureScript file for our project. - -In `src/hello/core.cljs` put: - -```clojure -(ns hello.core) - -(enable-console-print!) - -(defn hello [] "hello There") - -;; uncomment this to alter the provided "app" DOM element -;; (set! (.-innerHTML (js/document.getElementById "app") (hello))) - -(println (hello)) -``` - -### resources/public/index.html (optional) - -The `resources/public/index.html` file is optional because Figwheel -provides a default one (much like the page you are looking at now) and -you can get pretty far overriding the html element `
`. - -If you want to provide your own `index.html` here's one you can start -from the following example. - -In `resources/public/index.html` put: - -```html - - - - - -
- - - -``` - -## Building the build - -Once you have your files in place, the file tree should at least look like this: - -```text -hello-world -├─ dev.cljs.edn -├─ deps.edn -└─ src - └─ hello_world <- underscore is very important here - └─ core.cljs -``` - -Now you can start an auto-building / hot-reloading process. - -In the directory that is the root of the project (the `hello-world` directory), -execute the following shell command. - -```shell -lein fig -- -b dev -r -``` - -> Keep in mind that when you invoke the `fig` alias, you will always -> want to include `--` after the `fig` and before any figwheel.main -> args. - -This will launch and autobuild process that compiles your code as you -save it. A browser window will pop open and the terminal that you -launched the command from will now be running a ClojureScript REPL that -is attached to the browser. - -From here you will be able to edit the ClojureScript file and have it -hot loaded into the browser on save. diff --git a/figwheel-main/helper-content/css_reloading.md b/figwheel-main/helper-content/css_reloading.md deleted file mode 100644 index aabd5232..00000000 --- a/figwheel-main/helper-content/css_reloading.md +++ /dev/null @@ -1,75 +0,0 @@ -# Live Reloading CSS - -> **TLDR**: add a `:css-dirs ["resources/public/css"]` entry to the -> meta-data of your build `.cljs.edn` file or -> `figwheel-main.edn` - -Figwheel will hot reload your CSS while you work on it. Figwheel just -needs to know where your CSS files are so it can watch and reload -them. - -This will only work if the HTML file that is hosting your CLJS project -has included valid links to your CSS files. - -You can normally place your CSS files anywhere below the -`resources/public` directory. For clarity we will place them at -`resources/public/css`. - -Example CSS file at `resources/public/css/style.css`: -```css -/* hot stuff */ -h1 { color: red; } -``` - -And as an example we can include it on the -`resources/public/index.html` page like so: - -```html - - - - - - - - -
-
- - - -``` - -# Tell Figwheel to watch and reload CSS - -You will use the `:css-dirs` config key to tell figwheel to which -directories to watch for CSS file changes. - -You can do this one of two ways in the **build file** or in the -`figwheel-main.edn` file. - -In the current example we are assuming a `dev.cljs.edn` build -file. You can add `:css-dirs` config to the meta-data in the build -file like so: - -```clojure -^{:css-dirs ["resources/public/css"]} -{:main example.core} -``` - -Or you can set it for all builds and compiles in the `figwheel-main.edn`: - -```clojure -{:css-dirs ["resources/public/css"] - ;; rest of the config - } -``` - -Then you restart your build: - -```shell -cljs -m figwheel.main -b dev -r -``` - -Now you should be able to change the `style.css` file and see the changes -rendered live in your application. diff --git a/figwheel-main/helper-content/missing_index.md b/figwheel-main/helper-content/missing_index.md deleted file mode 100644 index bb59d39b..00000000 --- a/figwheel-main/helper-content/missing_index.md +++ /dev/null @@ -1,53 +0,0 @@ -# Welcome to Figwheel's default dev page - -> **TLDR**: you can use your own `index.html` page instead of this helper page -> by adding creating a `resources/public/index.html` file as detailed -> [here](#providing-your-own-indexhtml) - -This page is currently hosting your application code and REPL (Read -Eval Print Loop). As you change your code and save it, the -changed code will be hot loaded into this browser page. - -If you return to the terminal where you launched `figwheel` and enter -valid ClojureScript code at the `cljs.user=>` prompt, the code will be -compiled to Javascript and evaluated in the JavaScript environment on -this page. - -If you close this page the REPL will cease to function. - -# Index.html not provided - -You are here because you have not provided your own `index.html` page -to host your application yet. - -There is nothing wrong with this. You can use this page as a scaffold -to develop your project on for as long as its helpful. - -If your code needs to work with HTML elements on this page there is a -convenient `
` provided for this purpose. When you -replace the contents of the `app` element it will remove all the -current content and style from this page. - -> An file named `index.html` does not have to be provided. You can -> provide any other html file as a host page. For example -> `resources/public/app.html`. In this case, you may want to change -> `:open-url` to -> `"http://[[server-hostname]]/[[server-port]]/app.html"` in order to -> change the launch page. - -# Providing your own index.html - -You can create your own `index.html` and place it in -`resources/public/index.html` and it will be displayed instead of this -page. - -The most important part of creating your `index.html` page is ensuring -that your compiled ClojureScript gets loaded onto the page. - -To get started place the following HTML code at `resources/public/index.html`: - - - - - - diff --git a/figwheel-main/helper-content/repl_welcome.md b/figwheel-main/helper-content/repl_welcome.md deleted file mode 100644 index 750bb757..00000000 --- a/figwheel-main/helper-content/repl_welcome.md +++ /dev/null @@ -1,30 +0,0 @@ -# Welcome to ClojureScript! - -This page hosts the evaluation environment for the Read Eval Print -Loop (REPL) that you just launched. You can test the connection by -returning to the REPL and typing - -```javascript -cljs.user=> (js/alert "Hi!") -``` - -# New to ClojureScript? - -If you are new to the magical world of ClojureScript you may want to -spend some time at the REPL prompt `cljs.user=>`. This guide to -[Javascript/ClojureScript synonyms](https://kanaka.github.io/clojurescript/web/synonym.html){:target="_blank"} -is pretty helpful. Exploring this -[cheetsheet](http://cljs.info/cheatsheet/){:target="_blank"} will also provide some -bearings for you while you explore this new terrain. - -# What is figwheel.main? - -`figwheel.main` is a tool that is very similar in function to -[`cljs.main`](https://clojurescript.org/guides/quick-start){:target="_blank"}, if you -are unfamiliar with `cljs.main` you should really take some time to to -read the -[ClojureScript Quick Start](https://clojurescript.org/guides/quick-start){:target="_blank"}. It -will be time well spent. - -The main difference between `figwheel.main` and `cljs.main` in that it -will hot reload your code as you work on it. diff --git a/figwheel-main/helper-content/server_only_welcome.md b/figwheel-main/helper-content/server_only_welcome.md deleted file mode 100644 index 547ac29e..00000000 --- a/figwheel-main/helper-content/server_only_welcome.md +++ /dev/null @@ -1,67 +0,0 @@ -# Server Only mode - -You are here because you launched `figwheel.main` in server only mode -**and** you have not provided a default `index.html` file. - -**Server only mode** is entered when specify `--server` or -`-s` as the only **main option** to `figwheel.main`. - -**Server only mode** only serve files and ring endpoints defined -`:ring-handler`. This mode does not compile your source code or create -a REPL connection to this web page. If you are wanting to compile -ClojureScript source files as well as create a REPL connection to the -browser you will probably want to use the `--build` or `-b` option. - -# Index.html not provided - -You are here because you have not provided your own `index.html` page -to host your application yet. - -There is nothing wrong with this. You can use this page as a scaffold -to develop your project on for as long as its helpful. - -If your code needs to work with HTML elements on this page there is a -convenient `
` provided for this purpose. When you -replace the contents of the `app` element it will remove all the -current content and style from this page. - -> An file named `index.html` does not have to be provided. You can -> provide any other html file as a host page. For example -> `resources/public/app.html`. In this case, you may want to change -> `:open-url` to -> `"http://[[server-hostname]]/[[server-port]]/app.html"` in order to -> change the launch page. - -# Providing your own index.html - -You can create your own `index.html` and place it in -`resources/public/index.html` and it will be displayed instead of this -page. - -The most important part of creating your `index.html` page is ensuring -that your compiled ClojureScript gets loaded onto the page. - -If you are compiling a build named `dev` then you are probably going -to want to include this script tag right before ``. - -```html - -``` - -To get started, place the following HTML code at `resources/public/index.html`: - -```html - - - - - - -
- - - -``` - - - diff --git a/figwheel-main/helper-content/template_index.md b/figwheel-main/helper-content/template_index.md deleted file mode 100644 index 25004d5b..00000000 --- a/figwheel-main/helper-content/template_index.md +++ /dev/null @@ -1,21 +0,0 @@ -# Welcome to the template generated index.html - -> **TLDR**: you can find and edit this file at `resources/public/index.html` - -This page is currently hosting your application code and REPL (Read -Eval Print Loop). As you change your code and save it, the -changed code will be hot loaded into this browser page. - -If you return to the terminal where you launched `figwheel` and enter -valid ClojureScript code at the `cljs.user=>` prompt, the code will be -compiled to Javascript and evaluated in the JavaScript environment on -this page. - -If you close this page the REPL will cease to function. - -# Editing this index.html - -When you view the content of `resources/public/index.html` there will -be comments that show you how to remove this initial content. It is -important that you keep the final ` - -" - (str header) - (str body) - (str - (when-not (:dev-mode options) - "")) - (str - (when (and output-to - (.isFile (io/file output-to))) - (-> (slurp output-to) - (string/replace #"<\/script" "<\\\\/script")))))) - - -(defn main-action [req options] - {:status 200 - :headers {"Content-Type" "text/html"} - :body (main-wrapper options)}) - -(defn dev-endpoint [req] - (let [method-uri ((juxt :request-method :uri) req)] - (when (= method-uri [:get "/"]) - (main-action req {:output-to "target/public/cljs-out/helper-main.js" - :dev-mode true - :header "Dev Mode" - :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/repl_welcome.html"))})))) - -(defn middleware [handler options] - (fn [req] - (let [method-uri ((juxt :request-method :uri) req)] - (cond - (and (= [:get "/figwheel/helper/welcome"] method-uri) (:body options)) - {:status 200 - :headers {"Content-Type" "text/html"} - :body (:body options)} - (= method-uri [:get "/"]) - (main-action req options) - :else (handler req))))) - -(defn missing-index-middleware [handler options] - (fn [r] - (let [method-uri ((juxt :request-method :uri) r)] - (cond - (and (= [:get "/figwheel/helper/welcome"] method-uri) - (:body options)) - {:status 200 - :headers {"Content-Type" "text/html"} - :body (:body options)} - :else - (let [res (handler r)] - (if (and (= [:get "/"] method-uri) - (= 404 (:status res))) - (main-action r options) - res)))))) - -(defn default-index-code [output-to] - (let [path (best-guess-script-path output-to)] - (str - "
" - "
" - "
"
-     "<!DOCTYPE html>\n"
-     "<html>\n"
-     "  <head>\n"
-     "    <meta charset=\"UTF-8\">\n"
-     "  </head>\n"
-     "  <body>\n"
-     "    <div id=\"app\">\n"
-     "    </div>\n"
-     "    <script src=\""
-     (if path path
-         (str "[correct-path-to "
-              (or output-to "main.js file")
-              "]"))
-     "\" type=\"text/javascript\"></script>\n"
-     "  </body>\n"
-     "</html>\n"
-     "
"))) - -(defn missing-index [handler options] - (missing-index-middleware - handler - (merge - {:header "Figwheel Default Dev Page" - :body (str - (slurp (io/resource "public/com/bhauman/figwheel/helper/content/missing_index.html")) - (default-index-code (:output-to options)))} - options))) - -(defn serve-only-middleware [handler options] - (missing-index-middleware - handler - (merge - {:header "Server Only Page" - :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/server_only_welcome.html"))} - options))) - -)) ;; clj conditional reader end diff --git a/figwheel-main/src/figwheel/main/logging.clj b/figwheel-main/src/figwheel/main/logging.clj deleted file mode 100644 index bc452e9c..00000000 --- a/figwheel-main/src/figwheel/main/logging.clj +++ /dev/null @@ -1,207 +0,0 @@ -(ns figwheel.main.logging - (:require - [clojure.java.io :as io] - [clojure.string :as string] - [figwheel.core] - [figwheel.main.ansi-party :as ap :refer [format-str]] - [figwheel.main.util :as util] - [figwheel.tools.exceptions :as fig-ex]) - (:import [java.util.logging - Logger Level LogRecord - Handler - ConsoleHandler - FileHandler - Formatter])) - -(defprotocol Log - (fwlog! [logger level msg throwable]) - (fwsetlevel! [logger level])) - -(def levels-map - {:error Level/SEVERE - :fatal Level/SEVERE - :warn Level/WARNING - :info Level/INFO - :config Level/CONFIG - :debug Level/FINE - :trace Level/FINEST}) - -(extend java.util.logging.Logger - Log - {:fwlog! - (fn [^java.util.logging.Logger logger level msg ^Throwable throwable] - (let [^java.util.logging.Level lvl - (get levels-map level Level/INFO)] - (when (.isLoggable logger lvl) - (if throwable - (.log logger lvl msg throwable) - (.log logger lvl msg))))) - :fwsetlevel! - (let [levels-map* (merge levels-map {:all Level/ALL :off Level/OFF})] - (fn [^java.util.logging.Logger logger level] - (some->> - level - (get levels-map*) - (.setLevel logger))))}) - -(defn format-log-record [^LogRecord record] - (let [lvl (.getLevel record)] - (str "[Figwheel" - (when-not (= lvl Level/INFO) - (str ":" (.getName lvl))) - "] " - (.getMessage record) "\n" - (when-let [m (.getThrown record)] - (with-out-str - (clojure.pprint/pprint (Throwable->map m))))))) - -(def fig-formatter - (proxy [Formatter] [] - (format [^LogRecord record] - (format-log-record record)))) - -;; this supports rebel-readline better -;; TODO need to determine the best thing to do here -(defn writer-handler [] - (proxy [Handler] [] - (close []) - (flush [] (flush)) - (publish [^LogRecord record] - (if-let [formatter (.getFormatter this)] - (println (string/trim-newline (.format formatter record))) - (println (string/trim-newline (.getMessage record))))))) - -(defn default-logger - ([n] (default-logger n (if (util/rebel-readline?) - (writer-handler) - (ConsoleHandler.)))) - ([n handler] - (let [l (Logger/getLogger n)] - (when (empty? (.getHandlers l)) - (.addHandler l (doto handler - (.setFormatter fig-formatter) - ;; set level ALL here - (.setLevel java.util.logging.Level/ALL)))) - (.setUseParentHandlers l false) - l))) - -(def ^:dynamic *logger* (default-logger "figwheel.logg")) - -(defn remove-handlers [logger] - (doseq [h (.getHandlers logger)] - (.removeHandler logger h))) - -(defn switch-to-file-handler! [fname] - (alter-var-root #'ap/*use-color* (fn [_] false)) - (remove-handlers *logger*) - (.addHandler - *logger* - (doto (FileHandler. fname) - (.setFormatter fig-formatter) - (.setLevel java.util.logging.Level/ALL)))) - -(defn set-level [lvl-key] - (fwsetlevel! *logger* lvl-key)) - -(defn info [& msg] - (fwlog! *logger* :info (string/join " " msg) nil)) - -(defn warn [& msg] - (fwlog! *logger* :warn (string/join " " msg) nil)) - -(defn error [msg & [e]] - (fwlog! *logger* :error msg e)) - -(defn debug [& msg] - (fwlog! *logger* :debug (string/join " " msg) nil)) - -(defn trace [& msg] - (fwlog! *logger* :trace (string/join " " msg) nil)) - -(defn succeed [& msg] - (info (format-str [:green (string/join " " msg)]))) - -(defn failure [& msg] - (info (format-str [:red (string/join " " msg)]))) - -;; -------------------------------------------------------------------------------- -;; Logging Syntax errors -;; -------------------------------------------------------------------------------- - -(def ^:dynamic *syntax-error-style* :verbose) - -(defn exception-title [{:keys [tag warning-type]}] - (if warning-type - "Compile Warning" - (condp = tag - :clj/compiler-exception "Couldn't load Clojure file" - :cljs/analysis-error "Could not Analyze" - :tools.reader/eof-reader-exception "Could not Read" - :tools.reader/reader-exception "Could not Read" - :cljs/general-compile-failure "Could not Compile" - "Compile Exception"))) - -(defn file-line-col [{:keys [line column file] :as ex}] - [:file-line-col - (when file (str file " ")) - (when line (str "line:" line " ")) - (when column (str "column:" column))]) - -(defn exception-message [ex] - [:cyan (exception-title ex) " " (file-line-col ex)]) - -(defn exception-with-excerpt [e] - (fig-ex/add-excerpt (fig-ex/parse-exception e))) - -(defn except-data->format-lines-data [except-data] - - (let [data (figwheel.core/inline-message-display-data except-data) - longest-number (->> data (keep second) (reduce max 0) str count) - number-fn #(format (str " %" (when-not (zero? longest-number) - longest-number) - "s ") %)] - (apply vector :lines - (map - (fn [[k n s]] - (condp = k - :code-line [:yellow (number-fn n) s "\n"] - :error-in-code [:line [:yellow (number-fn n) ] [:bright s] "\n"] - :error-message [:yellow (number-fn "") (first (string/split s #"\^---")) "^---\n"])) - ;; only one error message - (let [[pre post] (split-with #(not= :error-message (first %)) data)] - (concat pre (take 1 post) - (filter #(not= :error-message (first %)) - post))))))) - -(defn except-data->format-data [{:keys [message] :as except-data}] - [:exception - (when message [:yellow " " message "\n"]) - "\n" - (except-data->format-lines-data except-data)]) - -(defn format-exception-warning [data] - [:lines (exception-message data) "\n\n" - (except-data->format-data data)]) - -(defn format-exception-warning-concise [{:keys [message] :as data}] - [:lines - [:cyan (exception-title data) ": "] - (when message [:yellow message " "]) - [:cyan (file-line-col data)]]) - -(defn format-ex [data] - (if (or (= *syntax-error-style* :concise) (not (:file-excerpt data))) - (format-exception-warning-concise data) - (format-exception-warning data))) - -(defn syntax-exception [e] - (-> (exception-with-excerpt e) - format-ex - format-str - info)) - -(defn cljs-syntax-warning [warning] - (-> (figwheel.core/warning-info warning) - format-ex - format-str - info)) diff --git a/figwheel-main/src/figwheel/main/schema/cli.clj b/figwheel-main/src/figwheel/main/schema/cli.clj deleted file mode 100644 index 0351da68..00000000 --- a/figwheel-main/src/figwheel/main/schema/cli.clj +++ /dev/null @@ -1,738 +0,0 @@ -(ns figwheel.main.schema.cli - (:require - [cljs.build.api :as bapi] - [cljs.cli] - [cljs.util] - [clojure.java.io :as io] - [clojure.set :as set] - [clojure.spec.alpha :as s] - [clojure.string :as string] - [expound.alpha :as exp] - [expound.printer :as printer] - [figwheel.main.schema.core - :as schema - :refer [def-spec-meta - non-blank-string? - file-exists? - flag-arg? - not-flag? - directory-exists?]] - [figwheel.main.util :as fw-util] - [spell-spec.alpha :as spell] - [spell-spec.expound :as spell-exp])) - -(defn inline-edn-string? [s] - (or (string/starts-with? s "{") - (string/starts-with? s "^"))) - -(defn resource-exists? [f] - (when-let [rname (cond - (string/starts-with? f "@/") (subs f 2) - (string/starts-with? f "@") (subs f 1) - :else nil)] - (io/resource rname))) - -(defn file-or-resource-should-exist [f] - (if-let [rname (cond - (string/starts-with? f "@/") (subs f 2) - (string/starts-with? f "@") (subs f 1) - :else nil)] - (io/resource rname) - (file-exists? f))) - -(defn all-files-and-resources-should-exist [s] - (every? file-or-resource-should-exist (cljs.util/split-paths s))) - -(defn readable? [s] - (try - (read-string s) - true - (catch Throwable t - false))) - -(exp/def ::inline-edn-string inline-edn-string? - "should be an inline edn string that starts with {") - -(exp/def ::all-files-and-resources-should-exist all-files-and-resources-should-exist - "should be one of more existing files or resources separated by :\n -resource paths should start with @") - -(s/def ::edn-option - (s/or :inline-edn-string ::inline-edn-string - :list-of-existing-edn-resources ::all-files-and-resources-should-exist)) - -(s/def ::compile-opts (s/cat :opt-key #{"-co" "--compile-opts"} - :opt-val ::edn-option)) - -(s/def ::repl-opts (s/cat :opt-key #{"-ro" "--repl-opts"} - :opt-val ::edn-option)) - -(s/def ::figwheel-opts (s/cat :opt-key #{"-fwo" "--fw-opts"} - :opt-val ::edn-option)) - -(s/def ::output-dir (s/cat :opt-key #{"-d" "--output-dir"} - :opt-val not-flag?)) - -(s/def ::target (s/cat :opt-key #{"-t" "--target"} - :opt-val #{"node" "nodejs" "nashorn" "webworker" "none"})) - -(defn resource-path? [f] - (string/starts-with? f "@")) - -(exp/def ::resource-exists resource-exists? - "should be an existing resource that starts with @") - -(exp/def ::file-exists file-exists? - "should be an existing file") - -(s/def ::file-or-resource-should-exist - (s/or :resource ::resource-exists - :file (s/and (complement resource-path?) ::file-exists))) - -(s/def ::init (s/cat :opt-key #{"-i" "--init"} - :opt-val ::file-or-resource-should-exist)) - -(exp/def ::readable readable? "should be a readable Clojure expression") - -(s/def ::eval (s/cat :opt-key #{"-e" "--eval"} - :opt-val ::readable)) - -(s/def ::verbose (s/cat :opt-key #{"-v" "--verbose"} - :opt-val #{"true" "false"})) - -(s/def ::optimizations (s/cat :opt-key #{"-O" "--optimizations"} - :opt-val #{"none" "whitespace" "simple" "advanced"})) - -(defn build-exists? [b] - (file-exists? (str b ".cljs.edn"))) - -(exp/def ::not-end-with-cljs-edn #(not (string/ends-with? % ".cljs.edn")) - "should not end with .cljs.edn as this is already implied\n(this should be maria if you have a maria.cljs.edn file)") - -(exp/def ::build-exists build-exists? - "should indicate a build file in the current directory\n(this should be marko if you have a marko.cljs.edn file)") - -(exp/def ::directory-exists directory-exists? - "should be an existing directory relative to the current directory") - -(s/def ::build-name (s/and ::not-end-with-cljs-edn - ::build-exists)) - -(s/def ::background-build - (s/cat :opt-key #{"-bb" "--background-build"} - :opt-val ::build-name)) - -(s/def ::figwheel (s/cat :opt-key #{"-fw" "--figwheel"} - :opt-val #{"true" "false"})) - -(s/def ::output-to (s/cat :opt-key #{"-o" "--output-to"} - :opt-val not-flag?)) - -(s/def ::print-config #{"-pc" "--print-config"}) - -(s/def ::watch (s/cat :opt-key #{"-w" "--watch"} - :opt-val (s/and ::directory-exists - ::schema/has-cljs-source-files))) - -(s/def ::port (s/cat :opt-key #{"-p" "--port"} - :opt-val ::schema/port)) - -(s/def ::host (s/cat :opt-key #{"-H" "--host"} - :opt-val ::schema/host)) - -(defn can-require-and-resolve-var? [var-str] - (boolean (fw-util/require-resolve-var var-str))) - -(exp/def ::require-and-resolve-var can-require-and-resolve-var? - "should be an existing var in a namespace that can be required") - -(exp/def ::var-with-forward-slash #(re-matches #"[^\/]+\/[^\/]+" %) - "should represent a var with a namespace and var name separated by a /") - -(s/def ::ring-handler (s/cat :opt-key #{"-rh" "--ring-handler"} - :opt-val (s/and ::var-with-forward-slash - ::require-and-resolve-var))) - -(s/def ::init-opts - (s/alt - :compile-opts ::compile-opts - :output-dir ::output-dir - :repl-opts ::repl-opts - :figwheel-opts ::figwheel-opts - :target ::target - :init ::init - :eval ::eval - :verbose ::verbose - :optimizations ::optimizations - :background-build ::background-build - :figwheel ::figwheel - :output-to ::output-to - :print-config ::print-config - :watch ::watch - :port ::port - :host ::host - :ring-handler ::ring-handler)) - - -;; TODO - -(s/def ::script (s/cat :script-name ::file-exists - :args (s/* any?))) - -;; if there is extra input after the presense of a main option -;; these are extra args that are going to be ignored -#_(validate-cli ["-e" "(list)" "-" "-i"]) - -#_(s/conform ::cli-options ["-e" "(list)" "-s" "lproject.clj"]) - - -;; if there is extra input before a main option then it is an unknown flag -#_ (validate-cli ["-e" "(list)" "-asdf" "-r"]) - -(s/def ::stdin #{"-"}) - -(defn host-port? [s] (string/includes? s ":")) - -(exp/def ::host-port host-port? - "should specify a host and port separated by a \":\" (ie. localhost:3000)") - -(s/def ::repl (s/cat :flag #{"-r" "--repl"} - :args (s/* any?))) - -(s/def ::serve (s/cat :serve-opt #{"-s" "--serve"} - :serve-param (s/? ::host-port))) - -(s/def ::repl-or-serve (s/alt :repl ::repl - :serve ::serve)) - -(s/def ::build (s/cat :build-opt #{"-b" "--build"} - :build-val ::build-name)) - -(s/def ::build-once (s/cat :build-opt #{"-bo" "--build-once"} - :build-val ::build-name)) - -(defn cljs-namespace-available? [ns] - (fw-util/ns-available? ns)) - -(exp/def ::cljs-namespace-available cljs-namespace-available? - "should be a CLJS namespace available on the classpath") - -(s/def ::compile (s/cat :flag #{"-c" "--compile"} - :val (s/? not-flag?))) - -#_(s/explain-data ::cli-options ["-e" "(list)" "-c" "-figwheel" "-r"]) - -#_(validate-cli ["-e" "(list)" "asdf" "-c" "-asdf" "-r"]) - -#_(s/conform ::cli-options ["-e" "(list)" "-c" "-figwheel" "-r"]) - -(s/def ::main (s/cat :flag #{"-m" "--main"} - :val ::cljs-namespace-available - :args (s/* any?))) - -(s/def ::help #{"-h" "--help" "-?"}) - -(s/def ::main-opts (s/alt - :stdin ::stdin - :script ::script - :build (s/cat :opt ::build - :repl-serve (s/? ::repl-or-serve)) - :compile-ns (s/cat :flag #{"-c" "--compile"} - :ns ::cljs-namespace-available - :repl-serve (s/? ::repl-or-serve)) - :compile (s/cat :flag #{"-c" "--compile"} - :repl-serve (s/? ::repl-or-serve)) - :build-once ::build-once - :help ::help - :repl ::repl - :serve ::serve - :main ::main)) - -(s/def ::cli-options (s/cat :inits (s/* ::init-opts) - :mains (s/? ::main-opts))) - -;; ---------------------------------------------------------------------- -;; extra problem detection -;; ---------------------------------------------------------------------- - -(defn position-of-first-main-arg [args] - (let [main-args (:main-dispatch cljs.cli/default-commands)] - (when (some main-args args) - (count (take-while (complement main-args) args))))) - -(defn get-first-main-arg [args] - (when-let [pos (position-of-first-main-arg args)] - (nth args pos))) - -(defn extra-input? [{:keys [reason]}] (= reason "Extra input")) - -(defn error-pos [{:keys [in]}] (first in)) - -(defn error-before-main-flag? [{:keys [::s/value] :as expd} prob] - (when-let [pos (error-pos prob)] - (if-let [main-pos (position-of-first-main-arg value)] - (< pos main-pos) - true))) - -(defn error-after-main-flag? [{:keys [::s/value] :as expd} prob] - (when-let [pos (error-pos prob)] - (when-let [main-pos (position-of-first-main-arg value)] - (> pos main-pos)))) - -;; ---------------------------------------------------------------------- -;; extra input before a main option -;; ---------------------------------------------------------------------- - -(defn unknown-flag? [expd p] - (and (extra-input? p) - (error-before-main-flag? expd p) - (flag-arg? (-> expd ::s/problems first :val first)))) - -#_(let [expd (s/explain-data ::cli-options ["-e" "(list)" "-asdf"])] - (unknown-flag? expd (first (::s/problems expd)))) - -;; specific case when an extra arg is mistaken for a script -(defn unknown-script-input? [{:keys [::s/value ::s/problems] :as expd} p] - (and (extra-input? p) - (error-before-main-flag? expd p) - (when-let [arg (some-> p :val first)] - (and (not (flag-arg? arg)) - (not (file-exists? arg)))))) - -#_(let [expd (s/explain-data ::cli-options ["-e" "(list)" "ee" "-r"])] - (unknown-script-input? expd (first (::s/problems expd)))) - -;; ---------------------------------------------------------------------- -;; extra input before after main option -;; ---------------------------------------------------------------------- - -(defn ignored-args? [expd p] - (and (extra-input? p) - (error-after-main-flag? expd p))) - -#_(let [expd (s/explain-data ::cli-options ["-e" "(list)" "-c" "-s" "asdf:asdf" "-d"])] - (ignored-args? expd (first (::s/problems expd)))) - -(defn missing-build-file? [expd p] - (-> p :via last (= ::build-exists))) - -#_(let [expd (s/explain-data ::cli-options ["-b" "never-find-build"])] - (missing-build-file? expd (first (::s/problems expd)))) - -(defn problem-type [expd p] - (cond - (:expound.spec.problem/type p) - (:expound.spec.problem/type p) - (unknown-flag? expd p) - ::unknown-flag - (unknown-script-input? expd p) - ::unknown-script-input - (ignored-args? expd p) - ::ignored-args - (missing-build-file? expd p) - ::missing-build-file - :else nil)) - -(defn add-problem-type [expd p] - (if-let [t (problem-type expd p)] - (assoc p :expound.spec.problem/type t) - p)) - -(defn add-problem-types [expd] - (update expd ::s/problems #(mapv (partial add-problem-type expd) %))) - -(defn similar-flags [f] - (let [all-flags (filter some? - (concat (keys (:main-dispatch cljs.cli/default-commands)) - (keys (:init-dispatch cljs.cli/default-commands)))) - long-flags (into #{} - (filter #(string/starts-with? % "--")) - all-flags) - short-flags (set (filter #(re-matches #"-[^-].*" %) all-flags)) - similar-short-flags - (fn [flag] (binding [spell/*length->threshold* (fn [_] 1)] - ((spell/likely-misspelled (into #{} - (filter #(> (count %) 2)) - short-flags)) - flag))) - similar-long-flags #((spell/likely-misspelled long-flags) %)] - (when-let [result - (cond - ;; catch common mistake of providing a -- for - arg - (and (string/starts-with? f "--") - (<= (count f) 5)) - (let [flag' (subs f 1)] - (if-let [flag (short-flags flag')] - [flag] - (similar-short-flags flag'))) - - ;; catch common mistake of providing a - for -- arg - (and (re-matches #"-[^-].*" f) (> (count f) 4)) - (let [flag' (str "-" f)] - (if-let [flag (long-flags flag')] - [flag] - (similar-long-flags flag'))) - - ;; misspelled -- arg - (string/starts-with? f "--") - (similar-long-flags f) - - ;; misspelled - arg - :else - (similar-short-flags f))] - (not-empty result)))) - -#_(similar-flags "--cd") - - -(defmulti update-problem (fn [expd p] (:expound.spec.problem/type p))) - -(defmethod update-problem :default [expd p] p) - -(defmethod update-problem ::unknown-flag [{:keys [::s/value ::s/problems] :as expd} p] - (let [unknown-flag (-> problems first :val first)] - (if-let [similar (similar-flags unknown-flag)] - (assoc p - :expound.spec.problem/type ::misspelled-flag - ::similar-flags similar - ::misspelled-flag unknown-flag) - (assoc p ::unknown-flag unknown-flag)))) - -(defmethod update-problem ::unknown-script-input [{:keys [::s/value ::s/problems] :as expd} p] - (let [unknown-script (-> p :val first)] - (assoc p ::unknown-script unknown-script))) - -(defmethod update-problem ::missing-build-file [{:keys [::s/value ::s/problems] :as expd} p] - (let [build-id (:val p) - build-file (str build-id) - all-build-files (map second (keep #(when (.isFile %) - (re-matches #"(.+)\.cljs\.edn" (.getName %))) - (file-seq (io/file "."))))] - (cond-> (assoc p ::missing-file build-file) - (not-empty all-build-files) (assoc :pred (set all-build-files))))) - - -(defn update-problems [expd] - (update expd ::s/problems #(mapv (partial update-problem expd) %))) - -(defn doc-for-flag [val {:keys [in :expound.spec.problem/type ::similar-flags]}] - (when-let [flag (cond (not-empty similar-flags) - (first similar-flags) - (let [pos (first in)] - (and (integer? pos) (not (zero? pos)))) - (nth val (dec (first in))))] - (first (filter - (fn [[kys v]] - ((set kys) flag)) - (apply concat ((juxt :main :init) cljs.cli/default-commands)))))) - -(let [expected-str (deref #'exp/expected-str)] - (defn expected-str-with-doc [_type spec-name val path problems opts] - (str (expected-str _type spec-name val path problems opts) - (when-let [[flags {:keys [doc]}] (doc-for-flag val (first problems))] - (when doc - (str - "\n\n__ Doc for " (string/join " " flags) " _____\n\n" - (printer/indent (string/join "\n" (#'cljs.cli/auto-fill doc 65))))))))) - -#_(defn validate-cli [cli-options] - (when-let [data' (s/explain-data ::cli-options cli-options)] - (let [data (update-problems - (add-problem-types - data'))] - #_(clojure.pprint/pprint data) - (with-redefs [exp/expected-str expected-str-with-doc] - (with-out-str - ((exp/custom-printer {:print-specs? false - :show-valid-values? true}) - data)))))) - -;; ---------------------------------------------------------------------- -;; ensure the opts respect group -;; ---------------------------------------------------------------------- -;; we could just include this in one big spec -;; but the errors are less intuitive IMHO - -(s/def ::cli-options-no-repl-env - ;; include all opts except -i -e and -v - (s/cat :inits (s/* - (s/alt - :compile-opts ::compile-opts - :output-dir ::output-dir - :repl-opts ::repl-opts - :figwheel-opts ::figwheel-opts - :target ::target - ;:init ::init - ;:eval ::eval - ;:verbose ::verbose - :optimizations ::optimizations - :background-build ::background-build - :figwheel ::figwheel - :output-to ::output-to - :print-config ::print-config - :watch ::watch - :port ::port - :host ::host - :ring-handler ::ring-handler)) - :mains (s/? ::main-opts))) - -#_(let [mains [:compile {:flag "-c", :repl-serve [:repl {:flag "-r"}]}]] - (-> mains second :repl-serve first (= :repl))) - -(defn not-repl-env-opt [{:keys [inits mains] :as conformed} cli-options] - (when-not (or (#{:script :stdin :repl :main} (first mains)) - (and (#{:compile :compile-ns :build} (first mains)) - (-> mains second :repl-serve first (= :repl)))) - (when-let [error (s/explain-data ::cli-options-no-repl-env cli-options)] - (update error - ::s/problems - #(mapv - (fn [x] - (let [res (assoc x - :expound.spec.problem/type ::missing-main-opt - ::conformed-mains mains - ::should-have-main-opt - ["--repl" "--main" "-r" "-m" "-" "[cljs script]"])] - (cond - (empty? mains) res - (and (#{:compile :compile-ns :build} (first mains)) - (-> mains second :repl-serve nil? )) - (assoc res ::should-have-main-opt ["--repl" "-r"]) - :else - (assoc res - :expound.spec.problem/type - ::incompatible-flag-for-main-opt)))) - %))))) - -(s/def ::cli-options-no-compile - ;; include all opts except compile opts - (s/cat :inits (s/* - (s/alt - :compile-opts ::compile-opts - :output-dir ::output-dir - :repl-opts ::repl-opts - ;:figwheel-opts ::figwheel-opts - :target ::target - :init ::init - :eval ::eval - :verbose ::verbose - ;:optimizations ::optimizations - ;:background-build ::background-build - ;:figwheel ::figwheel - ;:output-to ::output-to - :print-config ::print-config - ;:watch ::watch - :port ::port - :host ::host - :ring-handler ::ring-handler)) - :mains (s/? ::main-opts))) - -(defn not-compile-opt [{:keys [inits mains] :as conformed} cli-options] - (when-not (#{:compile :compile-ns :build :build-once} (first mains)) - (when-let [error (s/explain-data ::cli-options-no-compile cli-options)] - (update error - ::s/problems - #(mapv - (fn [x] - (let [res (assoc x - :expound.spec.problem/type ::missing-main-opt - ::conformed-mains mains - ::should-have-main-opt - ["--compile" "--build" "--build-once" - "-c" "-b" "-bo"])] - (if (empty? mains) - res - (assoc res - :expound.spec.problem/type - ::incompatible-flag-for-main-opt)))) - %))))) - -(defn get-explain-data [cli-options] - (or (s/explain-data ::cli-options cli-options) - (let [conformed (s/conform ::cli-options cli-options)] - (or - (not-repl-env-opt conformed cli-options) - (not-compile-opt conformed cli-options))))) - -(defn validate-cli-extra [cli-options] - (if-let [data' (get-explain-data cli-options)] - (let [data (update-problems - (add-problem-types - data'))] - #_(clojure.pprint/pprint data) - (with-redefs [exp/expected-str expected-str-with-doc] - (with-out-str - ((exp/custom-printer {:print-specs? false - :show-valid-values? true}) - data)))))) - -#_ (validate-cli-extra ["-co" "dev.cljs.edn" "-O" "advanced"]) - - -(defn validate-cli! [cli-args context-msg] - (if-let [explained (validate-cli-extra cli-args)] - (throw (ex-info (str context-msg "\n" explained) - {::error explained})) - true)) - -#_(validate-cli! ["-b" "(list"] nil) - -(defmethod exp/problem-group-str ::unknown-flag [_type spec-name val path problems opts] - (spell-exp/exp-formated "Unknown CLI flag" _type spec-name val path problems opts)) - -(defmethod exp/expected-str ::unknown-flag [_type spec-name val path problems opts] - (let [{:keys [::unknown-flag]} (first problems)] - (str "should be a known CLI flag (use figwheel.main --help to see available options)"))) - -#_(validate-cli ["-e" "(list)" "-ii" "project" "-asdf"]) - -(defmethod exp/problem-group-str ::misspelled-flag [_type spec-name val path problems opts] - (spell-exp/exp-formated "Misspelled CLI flag" _type spec-name val path problems opts)) - -(defmethod exp/expected-str ::misspelled-flag [_type spec-name val path problems opts] - (let [{:keys [::similar-flags]} (first problems)] - (str "should probably be" (spell-exp/format-correction-list similar-flags)))) - -#_(validate-cli ["-e" "(list)" "-print-confi" "-asdf"]) - -(defmethod exp/problem-group-str ::unknown-script-input [_type spec-name val path problems opts] - (spell-exp/exp-formated "Script not found" _type spec-name val path problems opts)) - -(defmethod exp/expected-str ::unknown-script-input [_type spec-name val path problems opts] - (let [{:keys [::unknown-script]} (first problems)] - (str "is being interpreted as the name of a script to exec but " - unknown-script - " is not a file"))) - -#_ (validate-cli ["-e" "(list)" "ee" "-r"]) - -(defmethod exp/problem-group-str ::ignored-args [_type spec-name val path problems opts] - (spell-exp/exp-formated "Ignored Extra CLI arguments" _type spec-name val path problems opts)) - -(defmethod exp/expected-str ::ignored-args [_type spec-name val path problems opts] - (str "extra args are only allowed after the --repl, --main, - (stdin) or [script] options")) - -(defmethod exp/problem-group-str ::missing-main-opt [_type spec-name val path problems opts] - (spell-exp/exp-formated - "Missing main option" - _type spec-name val path problems opts)) - -(defmethod exp/expected-str ::missing-main-opt [_type spec-name val path problems opts] - (let [{:keys [::should-have-main-opt] :as prob} (first problems) - opt (first (:val prob))] - (str "must add a main option for the " opt " flag to take effect," - (spell-exp/format-correction-list should-have-main-opt)))) - -(defmethod exp/problem-group-str ::incompatible-flag-for-main-opt - [_type spec-name val path problems opts] - (let [{:keys [::conformed-mains]} (first problems) - mains (not-empty (flatten (s/unform ::cli-options {:mains conformed-mains})))] - (prn conformed-mains mains) - (spell-exp/exp-formated - (str "Incompatible flag for main option" - (when mains - (str "s: " (string/join " " mains))) - " ---") - _type spec-name val path problems opts))) - -(defmethod exp/expected-str ::incompatible-flag-for-main-opt - [_type spec-name val path problems opts] - (let [{:keys [::should-have-main-opt] :as prob} (first problems) - opt (first (:val prob))] - (str "should have the correct main option for the " opt " flag to take effect," - (spell-exp/format-correction-list should-have-main-opt)))) - -(defmethod exp/problem-group-str ::missing-build-file [_type spec-name val path problems opts] - (spell-exp/exp-formated - (str "Build file " (::missing-file (first problems)) ".cljs.edn not found" ) - _type spec-name val path problems opts)) - -(defmethod exp/expected-str ::missing-build-file - [_type spec-name val path problems opts] - (let [{:keys [val pred] :as prob} (first problems)] - (if (and (set? pred) (not-empty pred)) - ;; there are build files - (str "should refer to an existing build" (spell-exp/format-correction-list pred)) - (str "should refer to a build file but there are no build files in the current directory")))) - - -#_ (validate-cli ["-e" "(list)" "-c" "-s" "asdf:asdf" "-d"]) - -#_(exp/expound-str ::cli-options ["-i" "asdf" "-i" "asdf" "-e" "15"]) - -;; for reference -#_"init options: - -co, --compile-opts edn Options to configure the build, can be an EDN - string or system-dependent path-separated list of - EDN files / classpath resources. Options will be - merged left to right. Any meta data will be - merged with the figwheel-options. - -d, --output-dir path Set the output directory to use - -ro, --repl-opts edn Options to configure the repl-env, can be an EDN - string or system-dependent path-separated list of - EDN files / classpath resources. Options will be - merged left to right. - -t, --target name The JavaScript target. Configures environment - bootstrap and defaults to browser. Supported - values: node or nodejs, nashorn, webworker, none - -init options only for --main and --repl: - -e, --eval string Evaluate expressions in string; print non-nil - values - -i, --init path Load a file or resource - -v, --verbose bool If true, will enable ClojureScript verbose logging - -init options only for --compile: - -O, --optimizations level Set optimization level, only effective with -- - compile main option. Valid values are: none, - whitespace, simple, advanced - -bb, --background-build str The name of a build config to watch and build in - the background. - -fw, --figwheel bool Use Figwheel to auto reload and report compile - info. Only takes effect when watching is - happening and the optimizations level is :none or - nil.Defaults to true. - -fwo, --fw-opts edn Options to configure figwheel.main, can be an EDN - string or system-dependent path-separated list of - EDN files / classpath resources. Options will be - merged left to right. - -o, --output-to file Set the output compiled file - -pc, --print-config Instead of running the command print out the - configuration built up by the command. Useful for - debugging. - -w, --watch path Continuously build, only effective with the -- - compile and --build main options. This option can - be supplied multiple times. - -Figwheel REPL options: - -H, --host address Address to bind - -p, --port number Port to bind - -rh, --ring-handler string Ring Handler for default REPL server EX. \"example. - server/handler\" - -main options: - - Run a script from standard input - -b, --build string Run a compile. The supplied build name refers to - a compililation options edn file. IE. \"dev\" will - indicate that a \"dev.cljs.edn\" will be read for - compilation options. The --build option will make - an extra attempt to initialize a figwheel live - reloading workflow. If --repl follows, will - launch a REPL after the compile completes. If -- - server follows, will start a web server according - to current configuration after the compile - completes. - -bo, --build-once string Compile for the build name one time. Looks for a - build EDN file just like the --build command. - -c, --compile [ns] Run a compile. If optional namespace specified, - use as the main entry point. If --repl follows, - will launch a REPL after the compile completes. - If --server follows, will start a web server that - serves the current directory after the compile - completes. - -h, --help, -? Print this help message and exit - -m, --main ns Call the -main function from a namespace with args - -r, --repl Run a REPL - -s, --serve host:port Run a server based on the figwheel-main - configuration options. - path Run a script from a file or resource" diff --git a/figwheel-main/src/figwheel/main/schema/cljs_options.clj b/figwheel-main/src/figwheel/main/schema/cljs_options.clj deleted file mode 100644 index 2eaf6097..00000000 --- a/figwheel-main/src/figwheel/main/schema/cljs_options.clj +++ /dev/null @@ -1,1106 +0,0 @@ -(ns figwheel.main.schema.cljs-options - (:require - [spell-spec.alpha :as spell] - [clojure.spec.alpha :as s] - [figwheel.main.schema.core :refer [def-spec-meta non-blank-string? directory-exists?] - :as schema] - [clojure.string :as string])) - -;; * Specification for ClojureScript -;; ** Top level util specs - -(s/def ::string-or-symbol (s/or - :symbol ::schema/unquoted-symbol - :string non-blank-string?)) - -(s/def ::string-or-named (s/or - :symbol ::schema/unquoted-symbol - :string non-blank-string? - :keyword keyword?)) - -;; ** CLJS Compiler Options -;; *** Commonly used Compiler Options -;; **** TODO Look at the use of clojure.spec/+ - -;; The clojure.spec/+ is used in favor of clojure.spec/* below. The -;; assumption is that we want to look at the indivudiual use cases and -;; decide if an empty expression actually makes sense. - -;; This conflates the use case of options compliance and creating a -;; stricter set of options to inform users of possible missuse. - -;; I think it's better to have a tighter expression and force folks to -;; remove/comment out no-op configs, to bring awareness to them. -;; Commented out configs are more obvious than no-op ones. - -(s/def ::output-to non-blank-string?) - -(def-spec-meta ::output-to - :doc - "After your ClojureScript has been compiled to JavaScript, this -specifies the name of the JavaScript output file. The contents of -this file will differ based on the :optimizations setting. - -If :optimizations is set to :none then this file will merely contain -the code needed to load Google Closure the and rest of the compiled -namespaces (which are separate files). - -If :optimizations is set to :simple, :whitespace, or :advanced this -output file will contain all the compiled code. - - :output-to \"resources/public/js/main.js\"") - -(s/def ::output-dir non-blank-string?) - -(def-spec-meta ::output-dir - :doc - "Sets the output directory for output files generated during -compilation. - -Defaults to \"out\". - - :output-dir \"resources/public/js/out\"") - -(s/def ::optimizations #{:none :whitespace :simple :advanced}) - -(def-spec-meta ::optimizations - :doc - "The optimization level. May be :none, :whitespace, :simple, or -:advanced. Only :none and :simple are supported for bootstrapped -ClojureScript. - - :none is the recommended setting for development - - :advanced is the recommended setting for production, unless - something prevents it (incompatible external library, bug, - etc.). - -For a detailed explanation of the different optimization modes see -https://developers.google.com/closure/compiler/docs/compilation_levels - -When the :main option is not used, :none requires manual code loading -and hence a separate HTML from the other options. - -Defaults to :none. Note: lein cljsbuild 1.0.5 will supply :whitespace. - - :optimizations :none") - -;; TODO should exist!! -(s/def ::main ::string-or-symbol) -(def-spec-meta ::main - :doc - "Specifies an entry point namespace. When combined with optimization -level :none, :main will cause the compiler to emit a single JavaScript -file that will import goog/base.js, the JavaScript file for the -namespace, and emit the required goog.require statement. This permits -leaving HTML markup identical between dev and production. - -Also see :asset-path. - - :main \"example.core\"") - -(s/def ::asset-path string?) -(def-spec-meta ::asset-path - :doc - "When using :main it is often necessary to control where the entry -point script attempts to load scripts from due to the configuration of -the web server. :asset-path is a relative URL path not a file system -path. For example, if your output directory is :ouput-dir -\"resources/public/js/compiled/out\" but your webserver is serving files -from \"resources/public\" then you want the entry point script to load -scripts from \"js/compiled/out\". - - :asset-path \"js/compiled/out\"") - -(s/def ::source-map (some-fn boolean? non-blank-string?)) -(def-spec-meta ::source-map - :doc - "See https://github.com/clojure/clojurescript/wiki/Source-maps. Under -optimizations :none the valid values are true and false, with the -default being true. Under all other optimization settings must specify -a path to where the source map will be written. - -Under :simple, :whitespace, or :advanced - :source-map \"path/to/source/map.js.map\"") - -(s/def ::preloads (s/every ::schema/unquoted-symbol :min-count 1 :into [] :kind sequential?)) -(def-spec-meta ::preloads - :doc - "Developing ClojureScript commonly requires development time only -side effects such as enabling printing, logging, spec instrumentation, -and connecting REPLs. :preloads permits loading such side effect -boilerplate right after cljs.core. For example you can make a -development namespace for enabling printing in browsers: - - (ns foo.dev) - - (enable-console-print!) - -Now you can configure your development build to load this side effect -prior to your main namespace with the following compiler options: - - {:preloads [foo.dev] - :main \"foo.core\" - :output-dir \"out\"} - -The :preloads config value must be a sequence of symbols that map to -existing namespaces discoverable on the classpath.") - -(s/def ::verbose boolean?) -(def-spec-meta ::verbose - :doc - "Emit details and measurements from compiler activity. - - :verbose true") - -(s/def ::pretty-print boolean?) -(def-spec-meta ::pretty-print - :doc - "Determines whether the JavaScript output will be tabulated in a -human-readable manner. Defaults to true. - - :pretty-print false") - -(s/def ::target #{:nodejs :webworker}) -(def-spec-meta ::target - :doc - "If targeting nodejs add this line. Takes no other options at the -moment. The default (no :target specified) implies browsers are being -targeted. Have a look here for more information on how to run your -code in nodejs. - - :target :nodejs") - - -(s/def ::infer-externs boolean?) -(def-spec-meta ::infer-externs - :doc - "Experimental externs inference. - - :infer-externs true - -When you set :infer-externs true you will get a new file in -your :output-dir named inferred_externs.js. When you do an advanced -build, this externs file will be used. - -You must add type hints to your code as such: - - (set! *warn-on-infer* true) - (defn foo [^js/React.Component c] - (.render c)) - -Please see: -https://gist.github.com/swannodette/4fc9ccc13f62c66456daf19c47692799") - - - -(s/def ::foreign-libs (s/every - (spell/keys - :req-un [::file] - :opt-un [::file-min - ::provides - ::requires - ::module-type - ::preprocess - ::global-exports]) - :into [] - :kind sequential?)) -(def-spec-meta ::foreign-libs - :doc - "Adds dependencies on foreign libraries. Be sure that the url returns a -HTTP Code 200 - -Defaults to the empty vector [] - - :foreign-libs [{ :file \"http://example.com/remote.js\" - :provides [\"my.example\"]}] - -Each element in the :foreign-libs vector should be a map, where the -keys have these semantics: - - :file Indicates the URL to the library - - :file-min (Optional) Indicates the URL to the minified variant of - the library. - - :provides A synthetic namespace that is associated with the library. - This is typically a vector with a single string, but it - has the capability of specifying multiple namespaces - (typically used only by Google Closure libraries). - - :requires (Optional) A vector explicitly identifying dependencies - (:provides values from other foreign libs); used to form a - topological sort honoring dependencies. - - :module-type (Optional) indicates that the foreign lib uses a given - module system. Can be one of :commonjs, :amd, :es6. - Note that if supplied, :requires is not used (as it is - implicitly determined). - - :preprocess (Optional) Used to preprocess / transform code in other - dialects (JSX, etc.). A defmethod for - cljs.clojure/js-transforms must be provided that matches - the supplied value in order to effect the desired code - transformation. - - :global-exports (Optional) used to map provided namespaces to - globally exported values. If present the foreign - library can be used idiomatically when required, - i.e. support for :refer, :rename, :as, etc.") - - - -(s/def ::file non-blank-string?) -(s/def ::provides (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(s/def ::file-min non-blank-string?) -(s/def ::requires (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(s/def ::module-type #{:commonjs :amd :es6}) -(s/def ::preprocess ::string-or-named) -(s/def ::global-exports (s/map-of ::string-or-named ::string-or-named)) - -(s/def ::externs (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(def-spec-meta ::externs - :doc - "Configure externs files for external libraries. - -For this option, and those below, you can find a very good explanation at: -http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html - -Defaults to the empty vector []. - - :externs [\"jquery-externs.js\"]") - -(s/def ::modules (s/map-of - keyword? - (spell/keys - :req-un [:cljs.options-schema.modules/output-to] - :opt-un [::entries - ::depends-on]))) -(def-spec-meta ::modules - :doc - "A new option for emitting Google Closure Modules. Closure Modules -supports splitting up an optimized build into N different modules. If -:modules is supplied it replaces the single :output-to. A module needs -a name, an individual :output-to file path, :entries a set of -namespaces, and :depends-on a set of modules on which the module -depends. Modules are only supported with :simple and :advanced -optimizations. An example follows: - - {:optimizations :advanced - :source-map true - :output-dir \"resources/public/js\" - :modules { - :common - {:output-to \"resources/public/js/common.js\" - :entries #{\"com.foo.common\"}} - :landing - {:output-to \"resources/public/js/landing.js\" - :entries #{\"com.foo.landing\"} - :depends-on #{:common}} - :editor - {:output-to \"resources/public/js/editor.js\" - :entries #{\"com.foo.editor\"} - :depends-on #{:common}}}} - - -Any namespaces not in an :entries set will be moved into the default -module :cljs-base. However thanks to cross module code motion, Google -Closure can move functions and methods into the modules where they are -actually used. This process is somewhat conservative so if you know -that you want to keep some code together do this via :entries. - -The :cljs-base module defaults to being written out to :output-dir -with the name \"cljs_base.js\". This may be overridden by specifying a -:cljs-base module describing only :output-to. - -Take careful note that a namespace may only appear once across all -module :entries. - -:modules fully supports :foreign-libs. :foreign-libs are always put -into dependency order before any Google Closure compiled source. - -Source maps are fully supported, an individual one will be created for -each module. Just supply :source-map true (see example) as there is no -single source map to name.") - - -;; ** TODO name collision don't want docs to collide -;; this is the only name collision in this -(s/def :cljs.options-schema.modules/output-dir non-blank-string?) -(s/def ::entries (s/every ::string-or-symbol :min-count 1 :into [] :kind (some-fn sequential? set?))) -(s/def ::depends-on (s/every ::string-or-named :min-count 1 :into [] :kind (some-fn sequential? set?))) - -(s/def ::source-map-path string?) -(def-spec-meta ::source-map-path - :doc - "Set the path to source files references in source maps to avoid -further web server configuration. - - :source-map-path \"public/js\"") - -(s/def ::source-map-asset-path string?) -(def-spec-meta ::source-map-asset-path - :doc - "Provides fine grained control over the sourceMappingURL comment that -is appended to generated JavaScript files when source mapping is enabled. -further web server configuration. - - :source-map-asset-path \"http://foo.com/public/js/out\"") - -(s/def ::source-map-timestamp boolean?) -(def-spec-meta ::source-map-timestamp - :doc - "Add cache busting timestamps to source map urls. This is helpful for -keeping source maps up to date when live reloading code. - - :source-map-timestamp true") - -(s/def ::cache-analysis boolean?) -(def-spec-meta ::cache-analysis - :doc - "Experimental. Cache compiler analysis to disk. This enables faster -cold build and REPL start up times. - -For REPLs, defaults to true. Otherwise, defaults to true if and only -if :optimizations is :none. - - :cache-analysis true") - - -(s/def ::recompile-dependents boolean?) -(def-spec-meta ::recompile-dependents - :doc - "For correctness the ClojureScript compiler now always recompiles -dependent namespaces when a parent namespace changes. This prevents -corrupted builds and swallowed warnings. However this can impact -compile times depending on the structure of the application. This -option defaults to true. - - :recompile-dependents false") - -(s/def ::static-fns boolean?) -(def-spec-meta ::static-fns - :doc - "Employs static dispatch to specific function arities in emitted -JavaScript, as opposed to making use of the call construct. Defaults -to false except under advanced optimizations. Useful to have set to -false at REPL development to facilitate function redefinition, and -useful to set to true for release for performance. - -This setting does not apply to the standard library, which is always -compiled with :static-fns implicitly set to true. - - :static-fns true") - -(s/def ::load-tests boolean?) -(def-spec-meta ::load-tests - :doc - "This flag will cause deftest from cljs.test to be ignored if false. - -Useful for production if deftest has been used in the production classpath. - -Default is true. Has the same effect as binding cljs.analyzer/*load-tests*. - - :load-tests true") - -(s/def ::elide-asserts boolean?) -(def-spec-meta ::elide-asserts - :doc - "This flag will cause all (assert x) calls to be removed during -compilation, including implicit asserts associated with :pre and :post -conditions. Useful for production. Default is always false even in -advanced compilation. Does NOT specify goog.asserts.ENABLE_ASSERTS, -which is different and used by the Closure library. - -Note that it is currently not possible to dynamically set *assert* to -false at runtime; this compiler flag must explicitly be used to effect -the elision. - - :elide-asserts true") - -(s/def ::pseudo-names boolean?) -(def-spec-meta ::pseudo-names - :doc - "With :advanced mode optimizations, determines whether readable names -are emitted. This can be useful when debugging issues in the optimized -JavaScript and can aid in finding missing externs. Defaults to false. - - :pseudo-names true") - -(s/def ::print-input-delimiter boolean?) -(def-spec-meta ::print-input-delimiter - :doc - "Determines whether comments will be output in the JavaScript that can -be used to determine the original source of the compiled code. - -Defaults to false. - - :print-input-delimiter false") - -(s/def ::output-wrapper boolean?) -(def-spec-meta ::output-wrapper - :doc - "Wrap the JavaScript output in (function(){...};)() to avoid clobbering -globals. Defaults to false. - - :output-wrapper false") - - -(s/def ::libs (s/every string? :min-count 1 :into [] :kind sequential?)) -(def-spec-meta ::libs - :doc - "Adds dependencies on external js libraries, i.e. Google -Closure-compatible javascript files with correct goog.provides() and -goog.requires() calls. Note that files in these directories will be -watched and a rebuild will occur if they are modified. - -Paths or filenames can be given. Relative paths are relative to the -current working directory (usually project root). - -Defaults to the empty vector [] - - :libs [\"closure/library/third_party/closure\" - \"src/js\" - \"src/org/example/example.js\"]") - - -(s/def ::preamble (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(def-spec-meta ::preamble - :doc - "Prepends the contents of the given files to each output file. Only -valid with optimizations other than :none. - -Defaults to the empty vector [] - - :preamble [\"license.js\"]") - - -(s/def ::hashbang boolean?) -(def-spec-meta ::hashbang - :doc - "When using :target :nodejs the compiler will emit a shebang as the -first line of the compiled source, making it executable. When your -intention is to build a node.js module, instead of executable, use -this option to remove the shebang. - - :hashbang false") - -(s/def ::compiler-stats boolean?) -(def-spec-meta ::compiler-stats - :doc - "Report basic timing measurements on compiler activity. - -Defaults to false. - - :compiler-stats true") - -(s/def ::closure-language-in-out-opts - #{:ecmascript3 :ecmascript5 :ecmascript5-strict - :ecmascript6 :ecmascript6-typed :ecmascript6-strict - :no-transpile}) - -(s/def ::language-in ::closure-language-in-out-opts) -(def-spec-meta ::language-in - :doc - "Configure the input and output languages for the closure library. May -be :ecmascript3, ecmascript5, ecmascript5-strict, :ecmascript6-typed, -:ecmascript6-strict, :ecmascript6 or :no-transpile. - -Defaults to :ecmascript3 - - :language-in :ecmascript3") - -(s/def ::language-out ::closure-language-in-out-opts) -(def-spec-meta ::language-out - :doc - "Configure the input and output languages for the closure library. May -be :ecmascript3, ecmascript5, ecmascript5-strict, :ecmascript6-typed, -:ecmascript6-strict, :ecmascript6 or :no-transpile. - -Defaults to :ecmascript3 - - :language-out :ecmascript3") - -(s/def ::closure-defines (s/map-of - ::string-or-symbol - (some-fn number? - string? - boolean?))) -(def-spec-meta ::closure-defines - :doc - "Set the values of Closure libraries' variables annotated with @define -or with the cljs.core/goog-define helper macro. A common usage is -setting goog.DEBUG to false: - - :closure-defines {\"goog.DEBUG\" false} - -or - - :closure-defines {'goog.DEBUG false} - -Note when using Lein the quote is unnecessary due to implicit quoting. - -For :optimization :none, a :main option must be specified for defines -to work, and only goog-define defines are affected. :closure-defines -currently does not have any effect with :optimization :whitespace.") - -(s/def ::npm-deps (s/or :map (s/map-of ::string-or-named string?) - :false false?)) -(def-spec-meta ::npm-deps - :doc - "Declare NPM dependencies. A map of NPM package names to the desired -versions or the Boolean value false. If false then any existing -node_modules directory will not be indexed nor used. See also -:install-deps. - - :npm-deps {:left-pad \"1.1.3\" }") - -(s/def ::install-deps boolean?) -(def-spec-meta ::install-deps - :doc - "When set to true, the Clojurescript compiler will handle downloading -the Javascript dependencies defined in the :npm-deps section of the config. - - :install-deps true") - -(s/def ::closure-extra-annotations - (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(def-spec-meta ::closure-extra-annotations - :doc - "Define extra JSDoc annotations that a closure library might use so -that they don't trigger compiler warnings. - - :closure-extra-annotations #{\"api\"}") - -(s/def ::anon-fn-naming-policy #{:off :unmapped :mapped}) -(def-spec-meta ::anon-fn-naming-policy - :doc - "Strategies for how the Google Closure compiler does naming of -anonymous functions that occur as r-values in assignments and variable -declarations. Defaults to :off. - - :anon-fn-naming-policy :unmapped - -The following values are supported: - - :off Don't give anonymous functions names. - - :unmapped Generates names that are based on the left-hand side of - the assignment. Runs after variable and property renaming, - so that the generated names will be short and obfuscated. - - :mapped Generates short unique names and provides a mapping from - them back to a more meaningful name that's based on the - left-hand side of the assignment.") - - -(s/def ::optimize-constants boolean?) -(def-spec-meta ::optimize-constants - :doc - "When set to true, constants, such as keywords and symbols, will only -be created once and will be written to a separate file called -constants_table.js. The compiler will emit a reference to the constant -as defined in the constants table instead of creating a new object for -it. This option is mainly intended to be used for a release build -since it can increase performance due to decreased allocation. -Defaults to true under :advanced optimizations otherwise to false. - - :optimize-constants true") - -(s/def ::parallel-build boolean?) -(def-spec-meta ::parallel-build - :doc - "When set to true, compile source in parallel, utilizing multiple cores. - -:parallel-build true") - -;; XXX TODO -#_(s/def ::devcards boolean?) -#_(def-spec-meta :doc - ` "Whether to include devcard 'defcard' definitions in the output of the compile.") - -(s/def ::watch-fn fn?) -(def-spec-meta ::watch-fn - :doc - "Is a function that will be called after a successful build. - -Only available for cljs.build.api/watch - - :watch-fn (fn [] (println \"Updated build\"))") - -(s/def ::process-shim boolean?) -(def-spec-meta ::process-shim - :doc - "Defaults to true. Automatically provide a shim for Node.js process.env -containing a single Google Closure define, NODE_ENV with \"development\" -as the default value. In production NODE_ENV will be set to \"production\". -If set to false all of the stated behavior is disabled. - - :process-shim false") - -(s/def ::dump-core boolean?) -(s/def ::emit-constants boolean?) -(s/def ::warning-handlers ;; symbol, string, or fn? - (s/every ::s/any :min-count 1 :into [] :kind sequential?)) -(s/def ::source-map-inline boolean?) -(s/def ::ups-libs - (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(s/def ::ups-externs - (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)) -(s/def ::ups-foreign-libs - (s/every ::foreign-libs :min-count 1 :into [] :kind sequential?)) -(s/def ::closure-output-charset non-blank-string?) -(s/def ::external-config (s/map-of keyword? map?)) - -(s/def ::fn-invoke-direct boolean?) -(def-spec-meta ::fn-invoke-direct - :doc - "Requires :static-fns true. This option emits slightly different -code that can speed up your code around 10-30%. Higher order -function that don’t implement the IFn protocol are normally called -with f.call(null, arg0, arg1 …​). - -With this option enabled the compiler calls them with a faster -f(arg0, arg1 …​ instead.) - - :fn-invoke-direct true") - -(s/def ::rewrite-polyfills boolean?) -(def-spec-meta ::rewrite-polyfills - :doc - "If set to true, the google closure compiler will add polyfills (for example -when you use native javascript Promise). This requires :language-in to be set -to :es6 or higher or it will silently be ignored! - - :language-in :es6 - :rewrite-polyfills true") - -(s/def ::aot-cache boolean?) -(def-spec-meta ::aot-cache - :doc - "A boolean value to disable or enable global caching of compiled assets. - - :aot-cache false") - -(s/def ::checked-arrays (s/or :keyval #{:warn :error} - :false false? - :nil nil?)) -(def-spec-meta ::checked-arrays - :doc - "If set to :warn or :error, checks inferred types and runtime values passed -to aget and aset. Inferred type mismatches will result in the -:invalid-array-access warning being triggered. Logs when incorrect values -are passed if set to :warn, throws if set to :error. May be set to a -false-y value to disable this feature. - -This setting does not apply if :optimizations is set to :advanced. - - :checked-arrays :warn") - -;; ** ClojureScript Compiler Warnings - -(s/def ::warnings - (s/or - :bool boolean? - :warnings-map-options - (s/keys - :opt-un - [::dynamic - ::extending-base-js-type - ::extend-type-invalid-method-shape - ::fn-var - ::fn-arity - ::fn-deprecated - ::invalid-protocol-symbol - ::invoke-ctor - ::invalid-arithmetic - ::invalid-array-access - ::infer-warning - ::js-shadowed-by-local - ::multiple-variadic-overloads - ::munged-namespace - ::ns-var-clash - ::overload-arity - ::preamble-missing - ::protocol-deprecated - ::protocol-invalid-method - ::protocol-duped-method - ::protocol-multiple-impls - ::protocol-with-variadic-method - ::protocol-impl-with-variadic-method - ::protocol-impl-recur-with-target - ::redef - ::redef-in-file - ::single-segment-namespace - ::unprovided - ::undeclared-var - ::undeclared-ns - ::undeclared-ns-form - ::undeclared-protocol-symbol - ::unsupported-js-module-type - ::unsupported-preprocess-value - ::variadic-max-arity]))) - -(def-spec-meta ::warnings - :doc - "This flag will turn on/off compiler warnings for references to -undeclared vars, wrong function call arities, etc. Can be a boolean -for enabling/disabling common warnings, or a map of specific warning -keys with associated booleans. Defaults to true. - - :warnings true - -;; OR - - :warnings {:fn-deprecated false} ;; suppress this warning - -The following warnings are supported: - - :preamble-missing, missing preamble - :unprovided, required namespace not provided - :undeclared-var, undeclared var - :undeclared-ns, var references non-existent namespace - :undeclared-ns-form, namespace reference in ns form that does not exist - :redef, var redefinition - :dynamic, dynamic binding of non-dynamic var - :fn-var, var previously bound to fn changed to different type - :fn-arity, invalid invoke arity - :fn-deprecated, deprecated function usage - :protocol-deprecated, deprecated protocol usage - :undeclared-protocol-symbol, undeclared protocol referred - :invalid-protocol-symbol, invalid protocol symbol - :multiple-variadic-overloads, multiple variadic arities - :variadic-max-arity, arity greater than variadic arity - :overload-arity, duplicate arities - :extending-base-js-type, JavaScript base type extension - :invoke-ctor, type constructor invoked as function - :invalid-arithmetic, invalid arithmetic - :protocol-invalid-method, protocol method does not match declaration - :protocol-duped-method, duplicate protocol method implementation - :protocol-multiple-impls, protocol implemented multiple times - :protocol-with-variadic-method, protocol declares variadic signature - :protocol-impl-with-variadic-method, protocol impl employs variadic signature - :protocol-impl-recur-with-target, target passed in recur to protocol method head - :single-segment-namespace, single segment namespace - :munged-namespace, namespace name contains a reserved JavaScript keyword - :ns-var-clash, namespace clashes with var - :extend-type-invalid-method-shape, method arities must be grouped together - :unsupported-js-module-type, unsupported JavaScript module type - :unsupported-preprocess-value, unsupported foreign lib preprocess value - :js-shadowed-by-local, name shadowed by a local - :infer-warning, warnings related to externs inference") - -;; *** TODO differnet ns?? - -(s/def ::dynamic boolean?) -(s/def ::extending-base-js-type boolean?) -(s/def ::extend-type-invalid-method-shape boolean?) -(s/def ::fn-var boolean?) -(s/def ::fn-arity boolean?) -(s/def ::fn-deprecated boolean?) -(s/def ::invalid-protocol-symbol boolean?) -(s/def ::invoke-ctor boolean?) -(s/def ::invalid-arithmetic boolean?) -(s/def ::invalid-array-access boolean?) -(s/def ::infer-warning boolean?) -(s/def ::js-shadowed-by-local boolean?) -(s/def ::multiple-variadic-overloads boolean?) -(s/def ::munged-namespace boolean?) -(s/def ::ns-var-clash boolean?) -(s/def ::overload-arity boolean?) -(s/def ::preamble-missing boolean?) -(s/def ::protocol-deprecated boolean?) -(s/def ::protocol-invalid-method boolean?) -(s/def ::protocol-duped-method boolean?) -(s/def ::protocol-multiple-impls boolean?) -(s/def ::protocol-with-variadic-method boolean?) -(s/def ::protocol-impl-with-variadic-method boolean?) -(s/def ::protocol-impl-recur-with-target boolean?) -(s/def ::redef boolean?) -(s/def ::redef-in-file boolean?) -(s/def ::single-segment-namespace boolean?) -(s/def ::unprovided boolean?) -(s/def ::undeclared-var boolean?) -(s/def ::undeclared-ns boolean?) -(s/def ::undeclared-ns-form boolean?) -(s/def ::undeclared-protocol-symbol boolean?) -(s/def ::unsupported-js-module-type boolean?) -(s/def ::unsupported-preprocess-value boolean?) -(s/def ::variadic-max-arity boolean?) - -;; ** Closure Compiler Warnings - -(s/def ::closure-warnings - (s/keys - :opt-un - [::access-controls - ::ambiguous-function-decl - ::analyzer-checks - ::check-eventful-object-disposal - ::check-regexp - ::check-types - ::check-useless-code - ::check-variables - ::closure-dep-method-usage-checks - ::common-js-module-load - ::conformance-violations - ::const - ::constant-property - ::debugger-statement-present - ::deprecated - ::deprecated-annotations - ::duplicate-message - ::duplicate-vars - ::es3 - ::es5-strict - ::externs-validation - ::extra-require - ::fileoverview-jsdoc - ::function-params - ::global-this - ::inferred-const-checks - ::internet-explorer-checks - ::invalid-casts - ::j2cl-checks - ::late-provide - ::lint-checks - ::message-descriptions - ::misplaced-type-annotation - ::missing-getcssname - ::missing-override - ::missing-polyfill - ::missing-properties - ::missing-provide - ::missing-require - ::missing-return - ::non-standard-jsdoc - ::report-unknown-types - ::strict-missing-require - ::strict-module-dep-check - ::strict-requires - ::suspicious-code - ::tweaks - ::type-invalidation - ::undefined-names - ::undefined-variables - ::underscore - ::unknown-defines - ::unused-local-variable - ::unused-private-property - ::use-of-goog-base - ::violated-module-dep - ::visiblity]) - - ) -(def-spec-meta ::closure-warnings - :doc - "Configure warnings generated by the Closure compiler. A map from -Closure warning to configuration value, only :error, :warning and :off -are supported. - - :closure-warnings {:externs-validation :off} - -The following Closure warning options are exposed to ClojureScript: - - :access-controls - :ambiguous-function-decl - :analyzer-checks - :check-eventful-object-disposal - :check-regexp - :check-types - :check-useless-code - :check-variables - :closure-dep-method-usage-checks - :common-js-module-load - :conformance-violations - :const - :constant-property - :debugger-statement-present - :deprecated - :deprecated-annotations - :duplicate-message - :duplicate-vars - :es3 - :es5-strict - :externs-validation - :extra-require - :fileoverview-jsdoc - :function-params - :global-this - :inferred-const-checks - :internet-explorer-checks - :invalid-casts - :j2cl-checks - :late-provide - :lint-checks - :message-descriptions - :misplaced-type-annotation - :missing-getcssname - :missing-override - :missing-polyfill - :missing-properties - :missing-provide - :missing-require - :missing-return - :non-standard-jsdoc - :report-unknown-types - :strict-missing-require - :strict-module-dep-check - :strict-requires - :suspicious-code - :tweaks - :type-invalidation - :undefined-names - :undefined-variables - :underscore - :unknown-defines - :unused-local-variable - :unused-private-property - :use-of-goog-base - :violated-module-dep - :visiblity - -See the Closure Compiler Warning wiki for detailed descriptions.") - -(s/def ::warning-value #{:error :warning :off}) - -;; *** TODO differnet ns?? -(s/def ::access-controls ::warning-value) -(s/def ::ambiguous-function-decl ::warning-value) -(s/def ::analyzer-checks ::warning-value) -(s/def ::check-eventful-object-disposal ::warning-value) -(s/def ::check-regexp ::warning-value) -(s/def ::check-types ::warning-value) -(s/def ::check-useless-code ::warning-value) -(s/def ::check-variables ::warning-value) -(s/def ::closure-dep-method-usage-checks ::warning-value) -(s/def ::common-js-module-load ::warning-value) -(s/def ::conformance-violations ::warning-value) -(s/def ::const ::warning-value) -(s/def ::constant-property ::warning-value) -(s/def ::debugger-statement-present ::warning-value) -(s/def ::deprecated ::warning-value) -(s/def ::deprecated-annotations ::warning-value) -(s/def ::duplicate-message ::warning-value) -(s/def ::duplicate-vars ::warning-value) -(s/def ::es3 ::warning-value) -(s/def ::es5-strict ::warning-value) -(s/def ::externs-validation ::warning-value) -(s/def ::extra-require ::warning-value) -(s/def ::fileoverview-jsdoc ::warning-value) -(s/def ::function-params ::warning-value) -(s/def ::global-this ::warning-value) -(s/def ::inferred-const-checks ::warning-value) -(s/def ::internet-explorer-checks ::warning-value) -(s/def ::invalid-casts ::warning-value) -(s/def ::j2cl-checks ::warning-value) -(s/def ::late-provide ::warning-value) -(s/def ::lint-checks ::warning-value) -(s/def ::message-descriptions ::warning-value) -(s/def ::misplaced-type-annotation ::warning-value) -(s/def ::missing-getcssname ::warning-value) -(s/def ::missing-override ::warning-value) -(s/def ::missing-polyfill ::warning-value) -(s/def ::missing-properties ::warning-value) -(s/def ::missing-provide ::warning-value) -(s/def ::missing-require ::warning-value) -(s/def ::missing-return ::warning-value) -(s/def ::non-standard-jsdoc ::warning-value) -(s/def ::report-unknown-types ::warning-value) -(s/def ::strict-missing-require ::warning-value) -(s/def ::strict-module-dep-check ::warning-value) -(s/def ::strict-requires ::warning-value) -(s/def ::suspicious-code ::warning-value) -(s/def ::tweaks ::warning-value) -(s/def ::type-invalidation ::warning-value) -(s/def ::undefined-names ::warning-value) -(s/def ::undefined-variables ::warning-value) -(s/def ::underscore ::warning-value) -(s/def ::unknown-defines ::warning-value) -(s/def ::unused-local-variable ::warning-value) -(s/def ::unused-private-property ::warning-value) -(s/def ::use-of-goog-base ::warning-value) -(s/def ::violated-module-dep ::warning-value) -(s/def ::visiblity ::warning-value) - -;; ** The Top level Options Map for the cljs/build fn -(s/def ::cljs-options - (spell/keys - :opt-un - [::main - ::preloads - ::asset-path - ::output-to - ::output-dir - ::closure-warnings - ::optimizations - ::source-map - ::verbose - ::pretty-print - ::target - ::infer-externs - ::foreign-libs - ::externs - ::modules - ::source-map-path - ::source-map-asset-path - ::source-map-timestamp - ::cache-analysis - ::recompile-dependents - ::static-fns - ::load-tests - ::elide-asserts - ::pseudo-names - ::print-input-delimiter - ::output-wrapper - ::libs - ::preamble - ::hashbang - ::compiler-stats - ::language-in - ::language-out - ::npm-deps - ::install-deps - ::closure-defines - ::closure-extra-annotations - ::anon-fn-naming-policy - ::optimize-constants - ::parallel-build - ::devcards - ::dump-core - ::emit-constants - ::warning-handlers - ::source-map-inline - ::ups-libs - ::ups-externs - ::ups-foreign-libs - ::closure-output-charset - ::external-config - ::watch-fn - ::process-shim - ::warnings - ::fn-invoke-direct - ::rewrite-polyfills - ::checked-arrays - ::aot-cache - - ;; these need to be specified - ::closure-variable-map-out - ::closure-generate-exports - ::closure-module-roots - ::rename-prefix - ::closure-property-map-in - ::ignore-js-module-exts - ::closure-property-map-out - ::stable-names - ::watch-error-fn - ::browser-repl - ::opts-cache - ::watch - ::cache-analysis-format - ::rename-prefix-namespace - ::closure-variable-map-in - ::use-only-custom-externs - - ] - )) diff --git a/figwheel-main/src/figwheel/main/schema/config.clj b/figwheel-main/src/figwheel/main/schema/config.clj deleted file mode 100644 index 66b734ac..00000000 --- a/figwheel-main/src/figwheel/main/schema/config.clj +++ /dev/null @@ -1,538 +0,0 @@ -(ns figwheel.main.schema.config - (:require - [clojure.java.io :as io] - [clojure.string :as string] - [clojure.spec.alpha :as s] - [clojure.set] - [figwheel.main.util :as util] - [figwheel.main.schema.core - :as schema - :refer [def-spec-meta non-blank-string? directory-exists? - ensure-all-registered-keys-included]] - [expound.alpha :as exp] - [spell-spec.alpha :as spell] - [spell-spec.expound])) - -(s/def ::watch-dirs - (s/coll-of - (s/and non-blank-string? - directory-exists? - ::schema/has-cljs-source-files))) - -#_(exp/expound ::watch-dirs ["/Users/bhauman/workspace/temp/figtest/ouchy"]) - -(def-spec-meta ::watch-dirs - :doc - "A list of ClojureScript source directories to be watched and compiled on change. - - :watch-dirs [\"cljs-src\"]" - :group :common) - -(s/def ::css-dirs (s/coll-of (s/and non-blank-string? - directory-exists?))) -(def-spec-meta ::css-dirs - :doc - "A list of CSS source directories to be watched and reloaded into the browser. - - :css-dirs [\"resource/public/css\"]" - :group :common) - -(s/def ::ring-handler (s/or :non-blank-string non-blank-string? - :symbol ::schema/unquoted-symbol)) -(def-spec-meta ::ring-handler - :doc - "A symbol or string indicating a ring-handler to embed in the -figwheel.repl server. This aids in quickly getting a dev server up and -running. If the figwheel server doesn't meet your needs you can simply -start your own server, the figwheel.client will still be able to -connect to its websocket endpoint. -Default: none - - :ring-handler my-project.server/handler" - :group :common) - -(s/def ::ring-server-options (s/keys :opt-un - [::schema/integer-port - ::schema/host])) - -(def-spec-meta ::ring-server-options - :doc - "All the options to forward to the `ring-jetty-adapter/run-jetty` function -which figwheel.main uses to run its ring server. - -All the available options are documented here: -https://github.com/ring-clojure/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj#L127 - -This will normally be used to set the `:port` and `:host` of the server. - -Most uses of these options are considered advanced if you find -yourself using many of these options you problably need to run your -own server outside of figwheel.main." - :group :common) - -(s/def ::rebel-readline boolean?) -(def-spec-meta ::rebel-readline - :doc - "By default Figwheel engauges a Rebel readline editor when it starts -the ClojureScript Repl in the terminal that it is launched in. - -This will only work if you have `com.bhauman/rebel-readline-cljs` in -your dependencies. - -More about Rebel readline: -https://github.com/bhauman/rebel-readline - -Default: true - - :rebel-readline false" - :group :common) - -(s/def ::pprint-config boolean?) -(def-spec-meta ::pprint-config - :doc - "When `:pprint-config` is set to true. The `figwheel.main` will print the -computed config information and will terminate the process. Useful for -understanding what figwheel.main adds to your configuration before it -compiles your build. - -Default: false - - :pprint-config true" - :group :common) - -(s/def ::open-file-command non-blank-string?) -(def-spec-meta ::open-file-command - :doc - "A path to an executable shell script that will be passed a file and -line information for a particular compilation error or warning. - -A script like this would work -ie. in ~/bin/myfile-opener - - #! /bin/sh - emacsclient -n +$2:$3 $1 - -The add this script in your config: - - :open-file-command \"myfile-opener\" - -But thats not the best example because Figwheel handles `emacsclient` -as a special case so as long as `emacsclient` is on the shell path you can -simply do: - - :open-file-command \"emacsclient\" - -and Figwheel will call emacsclient with the correct args." - :group :common) - -(s/def ::figwheel-core boolean?) -(def-spec-meta ::figwheel-core - :doc - "Wether to include the figwheel.core library in the build. This - enables hot reloading and client notification of compile time errors. - Default: true - - :figwheel-core false" - :group :common) - -(s/def ::hot-reload-cljs boolean?) -(def-spec-meta ::hot-reload-cljs - :doc - "Whether or not figwheel.core should hot reload compiled -ClojureScript. Only has meaning when :figwheel is true. -Default: true - - :hot-reload-cljs false" - :group :common) - -(s/def ::reload-dependents boolean?) -(def-spec-meta ::reload-dependents - :doc - "Whether or not figwheel.core should reload reload the namespaces -that `depend` on the changed namespaces in addition to the changed -namespaces themselves. Only has meaning when :figwheel is true. -Default:true - - :reload-dependents false" - :group :common) - -(s/def ::connect-url non-blank-string?) -(def-spec-meta ::connect-url - :doc - "The url that the figwheel repl client will use to connect back to -the server. - -This url is actually a template that will be filled in. For example -the default `:connect-url` is: - - \"ws://[[config-hostname]]:[[server-port]]/figwheel-connect\" - -The available template variables are: - -For the server side: - - [[config-hostname]] the host supplied in :ring-server-options > :host or \"localhost\" - [[server-hostname]] the java.InetAddress localhost name - \"Bruces-MacBook-Pro.local\" on my machine - [[server-ip]] the java.InetAddress localhost ip interface - normally 192.168.x.x - [[server-port]] the port supplied in :ring-server-options > :port or the default port 9500 - -On the client side: - - [[client-hostname]] the js/location.hostname on the client - [[client-port]] the js/location.port on the client - -If the url starts with a Websocket scheme \"ws://\" a websocket -connection will be established. If the url starts with an http scheme -\"http\" an http long polling connection will be established." - :group :common) - -(s/def ::open-url (s/or :non-blank-string non-blank-string? - :false false?)) -(def-spec-meta ::open-url - :doc - "Either a boolean value `false` or a string that indicates the url -that the figwheel repl will open in the browser after the source code -has been compiled. A `false` value will disable this behavior. - -The string value is actually a template that can provide optional -template variables. For example the default `:open-url` is: - - \"http://[[server-hostname]]:[[server-port]]\" - -The available template variables are: - -For the server side: - - [[server-hostname]] the host supplied in :ring-server-options > :host or \"localhost\" - [[server-port]] the port supplied in :ring-server-options > :port or the default port 9500" - :group :common) - -(s/def ::reload-clj-files (s/or :bool boolean? - :extension-coll (s/coll-of #{:clj :cljc}))) -(def-spec-meta ::reload-clj-files - :doc - "Figwheel naively reloads `clj` and `cljc` files on the `:source-paths`. -It doesn't reload clj dependent files like tools.namspace. - -Figwheel does note if there is a macro in the changed `clj` or `cljc` file -and then marks any cljs namespaces that depend on the `clj` file for -recompilation and then notifies the figwheel client that these -namespaces have changed. - -If you want to disable this behavior: - - :reload-clj-files false - -Or you can specify which suffixes will cause the reloading - - :reload-clj-files #{:clj :cljc}" - :group :common) - -(s/def ::log-file non-blank-string?) -(def-spec-meta ::log-file - :doc - "The name of a file to redirect the figwheel.main logging to. This -will only take effect when a REPL has been started. - - :log-file \"figwheel-main.log\"" - :group :common) - -(s/def ::log-level #{:error :info :debug :trace :all :off}) -(def-spec-meta ::log-level - :doc - "The level to set figwheel.main java.util.logger to. -Can be one of: `:error` `:info` `:debug` `:trace` `:all` `:off` - - :log-level :error" - :group :common) - -(s/def ::client-log-level #{:severe :warning :info :config :fine :finer :finest}) -(def-spec-meta ::client-log-level - :doc - "The log level to set the client side goog.log.Logger to for -figwheel.repl and figwheel.core. Can be one of: -`:severe` `:warning` `:info` `:config` `:fine` `:finer` `:finest` - - :client-log-level :warning" - :group :common) - -(s/def ::log-syntax-error-style #{:verbose :concise}) -(def-spec-meta ::log-syntax-error-style - :doc - "figwheel.main logging prints out compile time syntax errors which -includes displaying the erroneous code. -Setting `:log-syntax-error-style` to `:concise` will cause the logging to -not display the erroneous code. -Available options: `:verbose`, `:concise` -Default: `:verbose` - - :log-syntax-error-style :concise" - :group :common) - -(s/def ::load-warninged-code boolean?) -(def-spec-meta ::load-warninged-code - :doc - "If there are warnings in your code emitted from the compiler, figwheel -does not refresh. If you would like Figwheel to load code even if -there are warnings generated set this to true. -Default: false - - :load-warninged-code true" - :group :common) - -(s/def ::ansi-color-output boolean?) -(def-spec-meta ::ansi-color-output - :doc - "Figwheel makes an effort to provide colorful text output. If you need -to prevent ANSI color codes in figwheel output set `:ansi-color-output` -to false. Default: true - - :ansi-color-output false" - :group :common) - -(s/def ::validate-config boolean?) -(def-spec-meta ::validate-config - :doc - "Whether to validate the figwheel-main.edn and build config (i.e.\".cljs.edn\") files. -Default: true - - :validate-config false" - :group :common) - -(s/def ::validate-cli boolean?) -(def-spec-meta ::validate-cli - :doc - "Whether to validate the figwheel-main command line options -Default: true - - :validate-cli false" - :group :common) - -(s/def ::target-dir non-blank-string?) -(def-spec-meta ::target-dir - :doc - "A String that specifies the target directory component of the path -where figwheel.main outputs compiled ClojureScript - -The default `:output-dir` is composed of: - - [[:target-dir]]/public/cljs-out/[[build-id]] - -The default `:output-to` is composed of: - - [[:target-dir]]/public/cljs-out/[[build-id]]-main.js - -If you are using the default figwheel.repl server to serve compiled -assets, it is very important that the :target-dir be on the classpath. - -The default value of `:target-dir` is \"target\" - - :target-dir \"cljs-target\"" - :group :common) - -(s/def ::launch-node boolean?) -(def-spec-meta ::launch-node - :doc - "A boolean that indicates wether you want figwheel to automatically -launch Node. Defaults to true." - :group :common) - -(s/def ::inspect-node boolean?) -(def-spec-meta ::inspect-node - :doc - "A boolean that indicates wether you want figwheel to enable remote -inspection by adding \"--inspect\" when it launches Node. -Defaults to true." - :group :common) - -(s/def ::node-command non-blank-string?) -(def-spec-meta ::node-command - :doc - "A String indicating the Node.js executable to launch Node with. -Defaults to \"node\"" - :group :common) - -(s/def ::cljs-devtools boolean?) - -(def-spec-meta ::cljs-devtools - :doc - "A boolean that indicates wether to include binaryage/devtools into -the your clojurescript build. Defaults to true when the target is a -browser and the :optimizations level is :none, otherwise it is false. - - :cljs-devtools false" - :group :common) - -;; -------------------------------XXXXXXXXXXXX - -(s/def ::client-print-to (s/coll-of #{:console :repl})) -(def-spec-meta ::client-print-to - :doc - "The `figwheel.repl` client can direct printed (via pr) output to the -repl and or the console. `:client-print-to` is a list of where you -want print output directed. The output choices are `:console` and `:repl` -Default: [:console :repl] - - :client-print-to [:console]" - :group :un-common) - -(s/def ::ring-stack (s/or :non-blank-string non-blank-string? - :symbol ::schema/unquoted-symbol)) - -(def-spec-meta ::ring-stack - :doc - "The fighweel server has a notion of a `:ring-stack`. The -`:ring-stack` is a composition of basic ring-middleware (think -sessions) to wrap around a supplied `:ring-handler`. - -The default `:ring-stack` is a slightly modified -`ring.middleware.defaults/wrap-defaults`" - :group :un-common) - -(s/def ::ring-stack-options map?) -(def-spec-meta ::ring-stack-options - :doc - (str "The fighweel.repl server has a notion of a `:ring-stack`. The -`:ring-stack` is a composition of basic ring-middleware to wrap around -a supplied `:ring-handler`. - -The default `:ring-stack` is a slightly modified -ring.middleware.defaults/wrap-defaults. - -`:ring-stack-options` are the options that figwheel.repl supplies to -`ring.middleware.defaults/wrap-defaults`. - -The default options are slightly modified from `ring.middleware.defaults/site-defaults`: - -``` -" (when-let [opt (resolve 'figwheel.server.ring/default-options)] - (with-out-str (clojure.pprint/pprint (deref opt)))) -"``` - -You can override these options by suppling your own to `:ring-stack-options` - -If these options are changed significantly don't be suprised if the -figwheel stops behaving correctly :)") - :group :un-common) - -(s/def ::wait-time-ms integer?) -(def-spec-meta ::wait-time-ms - :doc - "The number of milliseconds to wait before issuing reloads. Set this -higher to wait longer for changes. This is the interval from when the first -file change occurs until we finally issue a reload event. - -Default: 50 - - :wait-time-ms 50" - :group :un-common) - -(s/def ::mode #{:build-once :repl :serve}) -(def-spec-meta ::mode - :doc - "The `:mode` indicates the behavior that occurs after a compile. -Options: `:repl` `:serve` or `:build-once` - -* `:repl` indicates that repl sill be started -* `:serve` indicates that a server will be started -* `:build-once` indicates that a compile will not be follwed by any action - -This is mainly intended for use when you are launching figwheel.main from a script. - -Normally defaults to `:repl`" -:group :un-common) - -(s/def ::broadcast-reload boolean?) -(def-spec-meta ::broadcast-reload - :doc - "Figwheel broadcasts hot reloads to all clients that have connected -since the figwheel process has started. Set `:broadcast-reload` to -`false` if you want to only send hot-reloads to the client where the -REPL eval occurs. -Default: true - - :broadast-reload false" - - :group :un-common) - -(s/def ::broadcast boolean?) -(def-spec-meta ::broadcast - :doc - "In the past figwheel would broadcast REPL evaluations to all -connected clients and then print the first result received in the -REPL. Setting `:broadcast` to `true` will give you back this legacy -behavior. Default: false - - :broadcast true" - :group :un-common) - -(s/def ::repl-eval-timeout integer?) -(def-spec-meta ::repl-eval-timeout - :doc - "The time (in milliseconds) it takes for the repl to timeout. -Evaluating any given expression in cljs can take some time. -The repl is configured to throw a timeout exception as to not hang forever. - -This config option will determine how long the repl waits for the result of an eval -before throwing. - -Default: 8000 - - :repl-eval-timeout 10000 ;;waits for 10 seconds instead of 8" - :group :un-common) - -(s/def ::hawk-options (s/map-of #{:watcher} #{:barbary :java :polling})) - -(def-spec-meta ::hawk-options - :doc - "If you need to watch files with polling instead of FS events. This can -be useful for certain docker environments. - - :hawk-options {:watcher :polling}" - :group :un-common) - - -(s/def ::edn - (ensure-all-registered-keys-included - #{::edn} - (spell/strict-keys - :opt-un - [::watch-dirs - ::css-dirs - ::ring-handler - ::ring-server-options - ::rebel-readline - ::pprint-config - ::open-file-command - ::figwheel-core - ::hot-reload-cljs - ::reload-dependents - ::connect-url - ::open-url - ::reload-clj-files - ::log-file - ::log-level - ::client-log-level - ::log-syntax-error-style - ::load-warninged-code - ::ansi-color-output - ::validate-config - ::validate-cli - ::target-dir - - ::launch-node - ::inspect-node - ::node-command - ::cljs-devtools - - ::client-print-to - ::ring-stack - ::ring-stack-options - ::wait-time-ms - ::mode - ::ring-server - ::broadcast - ::broadcast-reload - ::repl-eval-timeout - ::hawk-options - ]))) diff --git a/figwheel-main/src/figwheel/main/schema/core.clj b/figwheel-main/src/figwheel/main/schema/core.clj deleted file mode 100644 index adc9bd8e..00000000 --- a/figwheel-main/src/figwheel/main/schema/core.clj +++ /dev/null @@ -1,163 +0,0 @@ -(ns figwheel.main.schema.core - (:require - [clojure.java.io :as io] - [clojure.string :as string] - [clojure.spec.alpha :as s] - [clojure.set] - [figwheel.main.util :as util] - [expound.printer :as printer] - [expound.alpha :as exp])) - -(def ^:dynamic *spec-meta* (atom {})) - -(defn def-spec-meta [k & args] - (assert (even? (count args))) - (swap! *spec-meta* assoc k (assoc (into {} (map vec (partition 2 args))) - :position (count (keys @*spec-meta*)) - :key k))) - -(defn spec-doc [k doc] (swap! *spec-meta* assoc-in [k :doc] doc)) - -(defn file-exists? [s] (and s (.isFile (io/file s)))) -(defn directory-exists? [s] (and s (.isDirectory (io/file s)))) -(defn non-blank-string? [x] (and (string? x) (not (string/blank? x)))) - -(defn integer-like? [x] - (and (string? x) - (re-matches #"\d+" x))) - -(defn flag-arg? [s] - (and (non-blank-string? s) - (.startsWith s "-"))) - -(defn not-flag? [x] - (and (string? x) - (not (flag-arg? x)))) - -(defn unquoted-symbol? [a] - (and (symbol? a) - (not (string/starts-with? (str a) "'")))) - -;; ------------------------------------------------------------ -;; Shared specs -;; ------------------------------------------------------------ - -(exp/def ::host not-flag? - "should be an existing host interface (i.e. \"localhost\" \"127.0.0.1\" \"0.0.0.0\" \"192.168.0.1\")") - -(exp/def ::port integer-like? - "should be an integer port i.e 9500") - -(exp/def ::integer-port integer? - "should be an integer port i.e 9500") - -(defn has-cljs-source-files? [dir] - (not-empty (clojure.set/intersection - #{"cljs" "cljc"} - (util/source-file-types-in-dir dir)))) - -(exp/def ::unquoted-symbol unquoted-symbol? - "should be a symbol WITHOUT an initial quote. Quoted symbols are not needed in EDN") - -(exp/def ::has-cljs-source-files has-cljs-source-files? - "directory should contain cljs or cljc source files") - - -;; ------------------------------------------------------------ -;; Validate -;; ------------------------------------------------------------ - -(defn key-meta-for-problem [{:keys [via :spell-spec.alpha/likely-misspelling-of] :as prob}] - (or - (when-let [n (first likely-misspelling-of)] - (when-let [ns (namespace (first via))] - (get @*spec-meta* (keyword ns (name n))))) - (some->> (reverse via) - (filter @*spec-meta*) - ;; don't show the root docs - (filter (complement - #{:figwheel.main.schema.config/edn - :figwheel.main.schema.cljs-options/cljs-options})) - first - (get @*spec-meta*)))) - -(let [expected-str (deref #'exp/expected-str)] - (defn expected-str-with-doc [_type spec-name val path problems opts] - (str (expected-str _type spec-name val path problems opts) - (when-let [{:keys [key doc]} (key-meta-for-problem (first problems))] - (when doc - (str - "\n\n-- Doc for " (pr-str (keyword (name key))) " -----\n\n" - (printer/indent doc))))))) - -(defn expound-string [spec form] - (when-let [explain-data (s/explain-data spec form)] - (with-redefs [exp/expected-str expected-str-with-doc] - (with-out-str - ((exp/custom-printer - {:print-specs? false}) - explain-data))))) - -(defn validate-config! [spec config-data context-msg] - (if-let [explained (expound-string spec config-data)] - (throw (ex-info (str context-msg "\n" explained) - {::error explained})) - true)) - -#_(expound-string - :figwheel.main.schema.config/edn - (read-string (slurp "figwheel-main.edn"))) - -;; ------------------------------------------------------------ -;; Spec validation -;; ------------------------------------------------------------ - -(defmacro ensure-all-registered-keys-included [ignore-reg-keys key-spec] - (let [spec-keys (set (concat ignore-reg-keys - (mapcat second (partition 2 (rest key-spec))))) - reg-keys (set (filter #(= (str *ns*) (namespace %)) - (keys (s/registry)))) - missing-keys (clojure.set/difference reg-keys spec-keys)] - (assert (empty? missing-keys) (str "missing keys " (pr-str missing-keys)))) - key-spec) - -;; ------------------------------------------------------------ -;; Generate docs -;; ------------------------------------------------------------ - -(defn markdown-option-docs [key-datas] - (string/join - "\n\n" - (mapv (fn [{:keys [key doc]}] - (let [k (keyword (name key))] - (format "## %s\n\n%s" (pr-str k) doc))) - key-datas))) - -(defn markdown-docs [] - (let [{:keys [common un-common]} (->> (vals @*spec-meta*) - (filter #(-> % - :key - namespace - (= "figwheel.main.schema.config"))) - (sort-by :position) - (group-by :group))] - (str "# Figwheel Main Configuration Options\n\n" - "The following options can be supplied to `figwheel.main` via the `figwheel-main.edn` file.\n\n" - "# Commonly used options (in order of importance)\n\n" - (markdown-option-docs common) - "\n\n" - "# Rarely used options\n\n" - (markdown-option-docs un-common)))) - -(defn output-docs [output-to] - (require 'figwheel.main.schema.config) - (require 'figwheel.server.ring) - (.mkdirs (.getParentFile (io/file output-to))) - (spit output-to (markdown-docs))) - - -#_(validate-config! :figwheel.main.schema.config/edn (read-string (slurp "figwheel-main.edn")) "") - -#_(output-docs "doc/figwheel-main-options.md") - -#_(markdown-docs) diff --git a/figwheel-main/src/figwheel/main/util.clj b/figwheel-main/src/figwheel/main/util.clj deleted file mode 100644 index fd85b583..00000000 --- a/figwheel-main/src/figwheel/main/util.clj +++ /dev/null @@ -1,174 +0,0 @@ -(ns figwheel.main.util - (:require - [clojure.string :as string] - [clojure.java.io :as io] - [cljs.util] - [cljs.build.api :as bapi]) - (:import - [java.nio.file.Paths])) - -(defn ->path [s & args] - (java.nio.file.Paths/get ^String s (into-array String args))) - -(defn path-parts [& args] - (mapv str (apply ->path args))) - -(defn relativized-path-parts [path] - (let [local-dir-parts (path-parts (System/getProperty "user.dir")) - parts (path-parts (.getCanonicalPath (io/file path)))] - [local-dir-parts parts] - (when (= local-dir-parts (take (count local-dir-parts) parts)) - (drop (count local-dir-parts) parts)))) - -#_(relativized-path-parts (.getCanonicalPath (io/file "src/figwheel/main.clj"))) - -(defn require? [symbol] - (try - (require symbol) - true - (catch Exception e - #_(println (.getMessage e)) - #_(.printStackTrace e) - false))) - -(defn require-resolve-var [handler] - (when handler - (if (fn? handler) - handler - (let [h (symbol handler)] - (or (try (resolve h) (catch Throwable t nil)) - (when-let [ns (namespace h)] - (when (require? (symbol ns)) - (when-let [handler-var (resolve h)] - handler-var)))))))) - -(defn rebel-readline? [] - (require-resolve-var 'rebel-readline.core/read-line)) - -(defn static-classpath [] - (mapv - #(.getCanonicalPath (io/file %)) - (string/split (System/getProperty "java.class.path") - (java.util.regex.Pattern/compile (System/getProperty "path.separator"))))) - -(defn dynamic-classpath [] - (mapv - #(.getCanonicalPath (io/file (.getFile %))) - (mapcat - #(try (.getURLs %) - (catch Throwable t - nil)) - (take-while some? (iterate #(.getParent %) (.getContextClassLoader (Thread/currentThread))))))) - -#_((set (dynamic-classpath)) (.getCanonicalPath (io/file "src"))) -#_(add-classpath! (.toURL (io/file "src"))) - -(defn dir-on-classpath? [dir] - ((set (static-classpath)) (.getCanonicalPath (io/file dir)))) - -(defn dir-on-current-classpath? [dir] - ((into #{} - (concat - (static-classpath) - (dynamic-classpath))) (.getCanonicalPath (io/file dir)))) - -(defn root-dynclass-loader [] - (last - (take-while - #(instance? clojure.lang.DynamicClassLoader %) - (iterate #(.getParent ^java.lang.ClassLoader %) (.getContextClassLoader (Thread/currentThread)))))) - -(defn ensure-dynclass-loader! [] - (let [cl (.getContextClassLoader (Thread/currentThread))] - (when-not (instance? clojure.lang.DynamicClassLoader cl) - (.setContextClassLoader (Thread/currentThread) (clojure.lang.DynamicClassLoader. cl))))) - -(defn add-classpath! [url] - (assert (instance? java.net.URL url)) - (ensure-dynclass-loader!) - (let [root-loader (root-dynclass-loader)] - (.addURL ^clojure.lang.DynamicClassLoader root-loader url))) - -;; this is a best guess for situations where the user doesn't -;; add the source directory to the classpath -(defn valid-source-path? [source-path] - ;; TODO shouldn't contain preconfigured target directory - (let [compiled-js (string/replace source-path #"\.clj[sc]$" ".js")] - (and (not (.isFile (io/file compiled-js))) - (not (string/starts-with? source-path "./out")) - (not (string/starts-with? source-path "./target")) - (not (string/starts-with? source-path "./resources")) - (not (string/starts-with? source-path "./dev-resources")) - (let [parts (path-parts source-path) - fpart (second parts)] - (and (not (#{"out" "resources" "target" "dev-resources"} fpart)) - (empty? (filter #{"public"} parts))))))) - -(defn find-ns-source-in-local-dir [ns] - (let [cljs-path (cljs.util/ns->relpath ns :cljs) - cljc-path (cljs.util/ns->relpath ns :cljc) - sep (System/getProperty "file.separator")] - (->> (file-seq (io/file ".")) - (map str) - (filter - #(or (string/ends-with? % (str sep cljs-path)) - (string/ends-with? % (str sep cljc-path)))) - (filter valid-source-path?) - (sort-by count) - first))) - -;; only called when ns isn't on classpath -(defn find-source-dir-for-cljs-ns [ns] - (let [cljs-path (cljs.util/ns->relpath ns :cljs) - cljc-path (cljs.util/ns->relpath ns :cljc)] - (when-let [candidate (find-ns-source-in-local-dir ns)] - (let [rel-source-path (if (string/ends-with? candidate "s") - cljs-path - cljc-path) - candidate' - (when candidate - (let [path (string/replace candidate rel-source-path "")] - (-> path - (subs 0 (dec (count path))) - (subs 2))))] - (when (.isFile (io/file candidate' rel-source-path)) - candidate'))))) - -#_(find-source-dir-for-cljs-ns 'expro) - -#_(find-source-dir-for-cljs-ns 'exproj.core) - -(defn ns->location [ns] - (try (bapi/ns->location ns) - (catch java.lang.IllegalArgumentException e - (throw (ex-info - (str "ClojureScript Namespace " ns " was not found on the classpath.") - {:figwheel.main/error true}))))) - -(defn safe-ns->location [ns] - (try (bapi/ns->location ns) - (catch java.lang.IllegalArgumentException e - nil))) - -#_(ns->location 'asdf.asdf) -#_(safe-ns->location 'asdf.asdf) - -#_(ns->location 'figwheel.main) -#_(safe-ns->location 'figwheel.main) - -(defn ns-available? [ns] - (or (safe-ns->location ns) - (find-ns-source-in-local-dir ns))) - -#_(ns-available? "exproj.core") - -(defn source-file-types-in-dir [dir] - (into - #{} - (map - #(last (string/split % #"\.")) - (keep - #(last (path-parts (str %))) - (filter - #(.isFile %) - (file-seq (io/file dir))))))) diff --git a/figwheel-main/src/figwheel/main/watching.clj b/figwheel-main/src/figwheel/main/watching.clj deleted file mode 100644 index 5133e585..00000000 --- a/figwheel-main/src/figwheel/main/watching.clj +++ /dev/null @@ -1,70 +0,0 @@ -(ns figwheel.main.watching - (:require - [clojure.java.io :as io] - [clojure.string :as string] - [hawk.core :as hawk])) - -(def ^:dynamic *watcher* (atom {:watcher nil :watches {}})) - -(def ^:dynamic *hawk-options* nil) - -(defn alter-watches [{:keys [watcher watches]} f] - (when watcher (hawk/stop! watcher)) - (let [watches (f watches) - watcher (when (not-empty watches) - (if *hawk-options* - (apply hawk/watch! *hawk-options* (map vector (vals watches))) - (apply hawk/watch! (map vector (vals watches)))))] - {:watcher watcher - :watches watches})) - -(defn add-watch! [watch-key watch] - (swap! *watcher* alter-watches #(assoc % watch-key watch))) - -(defn remove-watch! [watch-key] - (swap! *watcher* alter-watches #(dissoc % watch-key))) - -(defn reset-watch! [] - (let [{:keys [watcher]} @*watcher*] - (when watcher (hawk/stop! watcher)) - (reset! *watcher* {}))) - -(defn running? [] - (some-> *watcher* deref :watcher :thread .isAlive)) - -(defn join [] - (some-> *watcher* deref :watcher :thread .join)) - -(defn stop! [] - (some-> *watcher* deref :watcher hawk/stop!)) - -(defn throttle [millis f] - (fn [{:keys [collector] :as ctx} e] - (let [collector (or collector (atom {})) - {:keys [collecting? events]} (deref collector)] - (if collecting? - (swap! collector update :events (fnil conj []) e) - (do - (swap! collector assoc :collecting? true) - (future (Thread/sleep millis) - (let [events (volatile! nil)] - (swap! collector - #(-> % - (assoc :collecting? false) - (update :events (fn [evts] (vreset! events evts) nil)))) - (f (cons e @events)))))) - (assoc ctx :collector collector)))) - -(defn file-suffix [file] - (last (string/split (.getName (io/file file)) #"\."))) - -(defn real-file? [file] - (and file - (.isFile file) - (not (.isHidden file)) - (not (#{\. \#} (first (.getName file)))))) - -(defn suffix-filter [suffixes] - (fn [_ {:keys [file]}] - (and (real-file? file) - (suffixes (file-suffix file))))) diff --git a/figwheel-main/test/figwheel/main/schema/cli_test.clj b/figwheel-main/test/figwheel/main/schema/cli_test.clj deleted file mode 100644 index 1d9a830d..00000000 --- a/figwheel-main/test/figwheel/main/schema/cli_test.clj +++ /dev/null @@ -1,126 +0,0 @@ -(ns figwheel.main.schema.cli-test - (:require - [figwheel.main.schema.cli :refer [validate-cli-extra]] - [figwheel.main.test.utils :refer [with-edn-files]] - [clojure.string :as string] - [clojure.test :refer [deftest testing is]])) - -(defmacro incl [expr & ss] - `(let [exp# ~expr] - (doseq [s# ~(vec ss)] - (is (string/includes? exp# s#))))) - -(deftest misspelling-args-test - (testing "similar short flags" - (incl (validate-cli-extra ["-cc"]) - "Misspelled CLI flag" - "should probably be: \"-co\"")) - (testing "single dash for double dash" - (incl (validate-cli-extra ["-print-confi"]) - "Misspelled CLI flag" - "should probably be: \"--print-config\"")) - (testing "double dash for single dash" - (incl (validate-cli-extra ["--pc"]) - "Misspelled CLI flag" - "should probably be: \"-pc")) - (testing "similar long args" - (incl (validate-cli-extra ["--ouput-dir"]) - "Misspelled CLI flag" - "should probably be: \"--output-dir\"" - "Doc for -d --output-dir" - "Set the output directory"))) - -(deftest unknown-flag-test - (incl (validate-cli-extra ["-vxxxxxx"]) - "Unknown CLI flag" - "-vxxxxxx" - "^^^^^^^^^^" - "should be a known CLI flag")) - -(deftest unknown-script-test - (incl (validate-cli-extra ["-O" "advanced" "dev" "-r"]) - "^^^^^" - "is being interpreted") - (incl (validate-cli-extra ["dev" "-r"]) - "^^^^^" - "is being interpreted") - (incl (validate-cli-extra ["-O" "advanced" "dev"]) - "^^^^^" - "is being interpreted") - (incl (validate-cli-extra ["dev"]) - "^^^^^" - "is being interpreted")) - - -(deftest ignored-args - (incl (validate-cli-extra ["-c" "figwheel.main" "-s" "asdf:asdf" "asd"]) - "Ignored Extra CLI arguments" - "extra args are only allowed") - (incl (validate-cli-extra ["-h" "figwheel.main"]) - "Ignored Extra CLI arguments" - "extra args are only allowed")) - -(deftest missing-main-opt - (incl (validate-cli-extra ["-e" "(list)"]) - "Missing main option" - "must add a main option for the -e") - - (with-edn-files - {:ex-script.cljs "(list)"} - (incl (validate-cli-extra ["-i" "ex-script.cljs"]) - "Missing main option" - "must add a main option for the -i")) - - (incl (validate-cli-extra ["-e" "(list)" "-c" "figwheel.main"]) - "Missing main option" - "must add a main option for the -e" - ;; narrows the suggestion - "\"--repl\", \"-r\"\n") - - (incl (validate-cli-extra ["-O" "advanced"]) - "Missing main option" - "must add a main option for the -O" - "--compile")) - -(deftest imcompatible-flag-for-main-opt - (incl (validate-cli-extra ["-e" "(list)" "-s" "asdf:hasdf"]) - "Incompatible flag for main options: -s" - "--repl") - - - (incl (validate-cli-extra ["-O" "advanced" "-r"]) - "Incompatible flag for main options: -r" - "should have the correct main option for the -O" - "--compile")) - -(deftest missing-build-file - (with-edn-files {:downtown.cljs.edn '{:main downtown.core} - :clowntown.cljs.edn '{:main clowntown.core}} - (incl (validate-cli-extra ["-b" "decent"]) - "Build file decent.cljs.edn not found" - "should refer to an existing build" - "\"downtown\"" "\"clowntown\"") - ) - - (with-edn-files {:downtown.cljs.edn '{:main downtown.core} - :clowntown.cljs.edn '{:main clowntown.core}} - (incl (validate-cli-extra ["-bo" "decent" ]) - "Build file decent.cljs.edn not found" - "should refer to an existing build" - "\"downtown\"" "\"clowntown\"") - ) - - (with-edn-files {:downtown.cljs.edn '{:main downtown.core} - :clowntown.cljs.edn '{:main clowntown.core}} - (incl (validate-cli-extra ["-bb" "decent" ]) - "Build file decent.cljs.edn not found" - "should refer to an existing build" - "\"downtown\"" "\"clowntown\"") - ) - - (with-edn-files {:devver.cljs.edn :delete - :helper.cljs.edn :delete - :dev.cljs.edn :delete} - (incl (validate-cli-extra ["-bb" "decent" ]) - "Build file decent.cljs.edn not found" - "there are no build files in the current directory"))) diff --git a/figwheel-main/test/figwheel/main/test/utils.clj b/figwheel-main/test/figwheel/main/test/utils.clj deleted file mode 100644 index 3d5e3b41..00000000 --- a/figwheel-main/test/figwheel/main/test/utils.clj +++ /dev/null @@ -1,78 +0,0 @@ -(ns figwheel.main.test.utils - (:require - [clojure.java.io :as io] - [figwheel.main.logging :as log])) - -(defn rename-file [filename new-filename] - (let [f (io/file filename)] - (when (.isFile f) - (.renameTo f (io/file new-filename)) - (.delete f)))) - -(defn backup-file [filename] - (rename-file filename (str filename "._backup"))) - -(defn restore-file [filename] - (if (.isFile (io/file (str filename "._backup"))) - (rename-file (str filename "._backup") filename) - (when (.isFile (io/file filename)) - (.delete (io/file filename))))) - -(defn place-files [files-map] - (doseq [[filename content] files-map] - (backup-file filename) - (when-not (= ":delete" (clojure.string/trim content)) - (spit (io/file filename) content)))) - -(defn restore-files [files-map] - (doseq [[filename content] files-map] - (restore-file filename))) - -(defn with-files* [files-map thunk] - (place-files files-map) - (try - (thunk) - (finally - (restore-files files-map)))) - -(defn with-edn-files* [files-map thunk] - (with-files* (into {} (map (fn [[k v]] [(name k) - (with-out-str (clojure.pprint/pprint v))]) - files-map)) - thunk)) - -(defmacro with-edn-files - "Make a temporary set of files that can shadow existing files - - specifying :delete as the content of a file will back it up only and - then restore it after completion. - -Example: - (with-edn-files - {:hithere {:some-edn 1} - :figwheel-main.edn :delete} - (slurp \"hithere\")) - => \"{:some-edn 1}\n\"" - [files-map & body] - `(with-edn-files* - ~files-map - (fn [] ~@body))) - -#_(with-edn-files - {"hithere" {:hi :there}} - (slurp "hithere")) - -(defmacro with-err-str - "Evaluates exprs in a context in which *err* is bound to a fresh - StringWriter. Returns the string created by any nested printing - calls." - {:added "1.0"} - [& body] - `(let [s# (new java.io.StringWriter)] - (binding [*err* s#] - ~@body - (str s#)))) - -(defn logging-fixture [f] - (with-redefs [log/*logger* (log/default-logger "figmain.test.logger" (log/writer-handler))] - (f))) diff --git a/figwheel-main/test/figwheel/main_test.clj b/figwheel-main/test/figwheel/main_test.clj deleted file mode 100644 index 32bf80d7..00000000 --- a/figwheel-main/test/figwheel/main_test.clj +++ /dev/null @@ -1,118 +0,0 @@ -(ns figwheel.main-test - (:require - [figwheel.main :as fm] - [figwheel.main.test.utils :refer [with-edn-files with-err-str logging-fixture]] - [clojure.java.io :as io] - [clojure.string :as string] - [clojure.test :refer [deftest testing is use-fixtures]])) - -(use-fixtures :once logging-fixture) - -(defn main->config [& args] - (with-redefs [clojure.core/shutdown-agents (fn []) - figwheel.main/print-conf - (fn [cnf] - (throw (ex-info "stealing config" {::escape-cnf cnf})))] - (try - (apply fm/-main (cons "-pc" args)) - (catch clojure.lang.ExceptionInfo e - (or (::escape-cnf (ex-data e)) - (throw e)))))) - -(deftest works-when-figwheel-main-is-absent - ;; basic sanity test - ;; mainly checking for exceptions being thrown - (with-edn-files - {:figwheel-main.edn :delete} - (is (:options (main->config))) - (is (:options (main->config "-r"))) - (is (:options (main->config "-m" "figwheel.main"))))) - -(defn temp-dir? [s] - ;; works on a mac - (string/starts-with? s "/var")) - -(defn uses-temp-dir? [{:keys [output-to output-dir]}] - (is (temp-dir? output-to)) - (is (temp-dir? output-dir))) - -(deftest noargs-uses-temp-dir-when-not-present-target-dir - (with-edn-files - {:figwheel-main.edn {:target-dir "never-gonna-find-me"} - :scripty-test.cljs "(println (+ 1 2 3))"} - (uses-temp-dir? (:options (main->config))) - (uses-temp-dir? (:options (main->config "-r"))) - (uses-temp-dir? (:options (main->config "-m" "figwheel.main"))) - (uses-temp-dir? (:options (main->config "scripty-test.cljs"))) - (uses-temp-dir? (:options (main->config "-"))))) - -;; FIX logging output capture -(deftest auto-adds-target-classpath-for-compile - (with-edn-files - {:figwheel-main.edn {:target-dir "never-gonna-find-me-now"}} - (is (string/includes? (with-out-str (main->config "-b" "dev")) - "Attempting to dynamically add \"never-gonna-find-me-now\"")) - (is (string/includes? (with-out-str (main->config "-bo" "dev")) - "Attempting to dynamically add \"never-gonna-find-me-now\"")) - (is (string/includes? (with-out-str (main->config "-c" "figwheel.main")) - "Attempting to dynamically add \"never-gonna-find-me-now\"")))) - -(deftest validates-command-line - (testing "without figwheel-main.edn" - (with-edn-files - {:figwheel-main.edn {:target-dir "never-gonna-find-me"}} - (string/includes? (with-err-str (main->config "-O" "dev")) "should be one of"))) - (testing "with figwheel-main.edn" - (with-edn-files - {:figwheel-main.edn :delete} - (string/includes? (with-err-str (main->config "-O" "dev")) "should be one of")))) - -(defn asset-path-relative? [{:keys [options]}] - (let [{:keys [output-dir asset-path]} options] - (and output-dir - asset-path - (string/ends-with? output-dir asset-path)))) - -(deftest asset-path-is-relative-to-output-dir - (with-edn-files - {:figwheel-main.edn {:target-dir "never-gonna-find-me"}} - (is (asset-path-relative? (main->config "-co" "dev.cljs.edn" "-r"))) - (is (asset-path-relative? (main->config "-m" "figwheel.main"))) - (is (asset-path-relative? (main->config "-c" "figwheel.main" "-r"))) - (is (asset-path-relative? (main->config "-b" "dev" "-r"))) - (is (asset-path-relative? (main->config "-bo" "dev")))) - (with-edn-files - {:figwheel-main.edn :delete} - (is (asset-path-relative? (main->config "-co" "dev.cljs.edn" "-r"))) - (is (asset-path-relative? (main->config "-m" "figwheel.main"))) - (is (asset-path-relative? (main->config "-c" "figwheel.main" "-r"))) - (is (asset-path-relative? (main->config "-b" "dev" "-r"))) - (is (asset-path-relative? (main->config "-bo" "dev")))) - - - ) - -(deftest dont-infer-watch-directory-for-compile-without-repl-or-serve - (with-edn-files - {:dev.cljs.edn '{:main exproj.core}} - (is (empty? (-> (main->config "-co" "dev.cljs.edn" "-c") - :figwheel.main/config :watch-dirs))) - (is (empty? (-> (main->config "-c" "exproj.core") - :figwheel.main/config :watch-dirs))) - - (is (not-empty (-> (main->config "-co" "dev.cljs.edn" "-c" "-r") - :figwheel.main/config :watch-dirs))) - - (is (not-empty (-> (main->config "-co" "dev.cljs.edn" "-c" "-s") - :figwheel.main/config :watch-dirs))) - - - - ) - - ) - - - - -#_(main-to-print-config "-pc" "-r" )