Compare commits
81 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcdff7577a | ||
|
|
984979b347 | ||
|
|
2f4d1a3581 | ||
|
|
2bca9089b8 | ||
|
|
656af38802 | ||
|
|
bfd7adf98f | ||
|
|
08173bc6a1 | ||
|
|
3fc6c58cd6 | ||
|
|
ccaf99910c | ||
|
|
9c588f68c2 | ||
|
|
f16d7004ee | ||
|
|
3caea10121 | ||
|
|
fb09fef496 | ||
|
|
b89b930ec2 | ||
|
|
4065f5df36 | ||
|
|
632977ff41 | ||
|
|
5275023b38 | ||
|
|
ad6ca6fb5e | ||
|
|
eff4c04f21 | ||
|
|
5df6c941f7 | ||
|
|
098b56d14f | ||
|
|
58e2ded430 | ||
|
|
8a3fc385a2 | ||
|
|
2d050e9055 | ||
|
|
b77f504cfd | ||
|
|
5ac52b725b | ||
|
|
c85da6149c | ||
|
|
6cf5390a44 | ||
|
|
bc3924aedf | ||
|
|
5d992042e4 | ||
|
|
83542e56a7 | ||
|
|
232df7a8a3 | ||
|
|
10dbbaa40b | ||
|
|
5b26fb6092 | ||
|
|
e9f9dfca14 | ||
|
|
348297ee11 | ||
|
|
52831f6b3e | ||
|
|
9666d3f372 | ||
|
|
5564e367e7 | ||
|
|
f65ed6a266 | ||
|
|
6dafae195d | ||
|
|
5fab543501 | ||
|
|
2ba3c60995 | ||
|
|
fb52f79396 | ||
|
|
c5f3e4cdf8 | ||
|
|
76e9a71a13 | ||
|
|
8de6b09989 | ||
|
|
884a2b2d87 | ||
|
|
c2687d1b9f | ||
|
|
17112646f1 | ||
|
|
d9c4f621cd | ||
|
|
ed1c9944f6 | ||
|
|
e07d7d6aad | ||
|
|
686b79e03f | ||
|
|
2ff032c8b3 | ||
|
|
244d834c46 | ||
|
|
0ff5fe106c | ||
|
|
bb23747273 | ||
|
|
2d5566ae86 | ||
|
|
1acd4feb4c | ||
|
|
c210cc486c | ||
|
|
4f8384763b | ||
|
|
6e848d1ee4 | ||
|
|
db38d8cacd | ||
|
|
594cc58b71 | ||
|
|
e956dd4de5 | ||
|
|
0a208bd275 | ||
|
|
5e0a4c5bfc | ||
|
|
562340f4dc | ||
|
|
b3f3f49d64 | ||
|
|
a4552fc6ed | ||
|
|
697775ef45 | ||
|
|
75d05e3158 | ||
|
|
dc59f3ec98 | ||
|
|
1ccff026de | ||
|
|
be6e9be246 | ||
|
|
52e360f3ab | ||
|
|
fdb85e0fe2 | ||
|
|
e247636be6 | ||
|
|
e032a6ef54 | ||
|
|
dc7dbdd51e |
50 changed files with 607 additions and 210 deletions
1
.clj-kondo/config.edn
Normal file
1
.clj-kondo/config.edn
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{:config-paths ["../resources/clj-kondo.exports/mount/mount/"]}
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,7 +1,10 @@
|
||||||
/target
|
/target
|
||||||
/classes
|
/classes
|
||||||
/checkouts
|
/checkouts
|
||||||
pom.xml
|
.cpcache/
|
||||||
|
.rebel_readline_history
|
||||||
|
cljs-test-runner-out
|
||||||
|
node_modules
|
||||||
pom.xml.asc
|
pom.xml.asc
|
||||||
.repl*
|
.repl*
|
||||||
dev/resources/public/js/*
|
dev/resources/public/js/*
|
||||||
|
|
@ -18,3 +21,4 @@ doo-index.html
|
||||||
/.nrepl-history
|
/.nrepl-history
|
||||||
.cljs_rhino_repl/
|
.cljs_rhino_repl/
|
||||||
out/
|
out/
|
||||||
|
.clj-kondo/.cache
|
||||||
|
|
|
||||||
26
.travis.yml
Normal file
26
.travis.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
sudo: false
|
||||||
|
language: java
|
||||||
|
script:
|
||||||
|
- boot test
|
||||||
|
- boot test-cljs
|
||||||
|
- boot test-cljs-advanced
|
||||||
|
install:
|
||||||
|
- mkdir -p ~/bin
|
||||||
|
- export PATH=~/bin:$PATH
|
||||||
|
|
||||||
|
- curl -L https://github.com/boot-clj/boot-bin/releases/download/latest/boot.sh -o ~/bin/boot
|
||||||
|
- chmod +x ~/bin/boot
|
||||||
|
jdk: openjdk8
|
||||||
|
env:
|
||||||
|
matrix:
|
||||||
|
- BOOT_CLOJURE_VERSION=1.8.0
|
||||||
|
global:
|
||||||
|
- JAVA_OPTS="-Xms512m -Xmx2048m"
|
||||||
|
jdk:
|
||||||
|
- openjdk8
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.m2
|
||||||
|
- $HOME/.boot/cache/bin
|
||||||
|
- $HOME/.boot/cache/lib
|
||||||
|
- $HOME/bin
|
||||||
37
CHANGELOG.md
37
CHANGELOG.md
|
|
@ -1,3 +1,38 @@
|
||||||
|
## 0.1.19
|
||||||
|
###### Wed Aug 21 22:43:40 2024 -0400
|
||||||
|
|
||||||
|
* add `clojure-kondo`
|
||||||
|
|
||||||
|
## 0.1.17
|
||||||
|
###### Mon Dec 19 15:17:21 2022 -0500
|
||||||
|
|
||||||
|
* 2d050e9 fix: swap-states non string rollback (thanks to [egg-juxt](https://github.com/egg-juxt))
|
||||||
|
|
||||||
|
## 0.1.16
|
||||||
|
###### Mon Jan 28 10:34:26 2019 -0500
|
||||||
|
|
||||||
|
* fb52f79 prevent reloading of mount.core ns ([106](https://github.com/tolitius/mount/issues/106))
|
||||||
|
* c5f3e4c current-state should return Derefable on :cljc ([104](https://github.com/tolitius/mount/issues/104))
|
||||||
|
* c2687d1 silent `*logger*` warning in latest ClojureScript([101](https://github.com/tolitius/mount/issues/101))
|
||||||
|
* bb23747 switch form circle to travis
|
||||||
|
|
||||||
|
## 0.1.14
|
||||||
|
###### Thu Oct 25 18:34:22 2018 -0400
|
||||||
|
|
||||||
|
* cljs: throw js/Error not just a string ([#100](https://github.com/tolitius/mount/issues/100))
|
||||||
|
* add ^{:on-lazy-start :throw} ([#95](https://github.com/tolitius/mount/issues/95) and [#99](https://github.com/tolitius/mount/issues/99))
|
||||||
|
* self hosted ClojureScript support ([#85](https://github.com/tolitius/mount/issues/85) and [#97](https://github.com/tolitius/mount/issues/97))
|
||||||
|
|
||||||
|
## 0.1.12
|
||||||
|
###### Sat Feb 10 14:53:04 2018 -0500
|
||||||
|
|
||||||
|
* remove ref to old state alias in `swap-states` ([#89](https://github.com/tolitius/mount/issues/89))
|
||||||
|
* `:on-reload :noop` should not leave stale references
|
||||||
|
* `stop-except` & `start-without` to take all states ([#81](https://github.com/tolitius/mount/issues/81))
|
||||||
|
* goog.log/error for logging cljs errors ([#63](https://github.com/tolitius/mount/issues/63))
|
||||||
|
* on failure (down) reports and cleans up vs. just "throw" ([#63](https://github.com/tolitius/mount/issues/63))
|
||||||
|
* do not start a `DerefableState` as a side-effect of printing ([#76](https://github.com/tolitius/mount/issues/76))
|
||||||
|
|
||||||
## 0.1.11
|
## 0.1.11
|
||||||
###### Fri Dec 2 18:09:51 2016 -0600
|
###### Fri Dec 2 18:09:51 2016 -0600
|
||||||
|
|
||||||
|
|
@ -19,7 +54,7 @@
|
||||||
## 0.1.9
|
## 0.1.9
|
||||||
###### Sun Jan 31 15:47:19 2016 -0500
|
###### Sun Jan 31 15:47:19 2016 -0500
|
||||||
|
|
||||||
* `:on-reload` #{:noop :stop :restart} ([#36](https://github.com/tolitius/mount/issues/36))
|
* `:on-reload` #{:noop :stop :restart} ([#36](https://github.com/tolitius/mount/issues/36))
|
||||||
* swapping states with values ([#45](https://github.com/tolitius/mount/issues/45))
|
* swapping states with values ([#45](https://github.com/tolitius/mount/issues/45))
|
||||||
* `(mount.core/system)` experiment is refactored to [Yurt](https://github.com/tolitius/yurt)
|
* `(mount.core/system)` experiment is refactored to [Yurt](https://github.com/tolitius/yurt)
|
||||||
* cleaning up deleted states ([#42](https://github.com/tolitius/mount/issues/42))
|
* cleaning up deleted states ([#42](https://github.com/tolitius/mount/issues/42))
|
||||||
|
|
|
||||||
31
Makefile
Normal file
31
Makefile
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
.PHONY: clean test jar tag outdated install deploy tree repl
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf target
|
||||||
|
rm -rf classes
|
||||||
|
|
||||||
|
jar: clean test tag
|
||||||
|
clojure -A:jar
|
||||||
|
|
||||||
|
test: clean
|
||||||
|
clojure -X:test :patterns '[".*"]' # clojure tests
|
||||||
|
# clojure -Atest-cljs -r ".*test.self.host.*" # clojure script tests
|
||||||
|
# run "j8; boot test-cljs" until running cljs tests via deps.edn is fixed
|
||||||
|
|
||||||
|
outdated:
|
||||||
|
clojure -M:outdated
|
||||||
|
|
||||||
|
tag:
|
||||||
|
clojure -A:tag
|
||||||
|
|
||||||
|
install: jar
|
||||||
|
clojure -A:install
|
||||||
|
|
||||||
|
deploy: jar
|
||||||
|
clojure -A:deploy
|
||||||
|
|
||||||
|
tree:
|
||||||
|
mvn dependency:tree
|
||||||
|
|
||||||
|
repl:
|
||||||
|
clojure -A:dev -A:repl
|
||||||
95
README.md
95
README.md
|
|
@ -1,19 +1,13 @@
|
||||||
> I think that it's _extraordinarily important_ that we in computer science keep fun in computing
|
> I think that it's _extraordinarily important_ that we in computer science keep fun in computing
|
||||||
|
|
||||||
_**Alan J. Perlis** from [Structure and Interpretation of Computer Programs](https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-3.html)_
|
_**Alan J. Perlis** from [Structure and Interpretation of Computer Programs](https://web.mit.edu/6.001/6.037/sicp.pdf)_
|
||||||
|
|
||||||
# mount <img src="doc/img/mount-logo.png" width="70px">
|
# mount <img src="doc/img/mount-logo.png" width="70px">
|
||||||
|
[](https://github.com/tolitius/mount/releases)
|
||||||
|
[](https://clojars.org/mount)
|
||||||
|
|
||||||
module | branch | status
|
###### _any_ questions or feedback: [`#mount`](https://clojurians.slack.com/messages/mount/) clojurians slack channel <img src="doc/img/slack-icon.png" width="15px"> (or just [open an issue](https://github.com/tolitius/mount/issues))
|
||||||
----------|----------|----------
|
|
||||||
mount | `master` | [](https://circleci.com/gh/tolitius/mount/tree/master)
|
|
||||||
|
|
||||||
[](http://clojars.org/mount)
|
|
||||||
|
|
||||||
> <img src="doc/img/slack-icon.png" width="30px"> _any_ questions or feedback: [`#mount`](https://clojurians.slack.com/messages/mount/) clojurians slack channel (or just [open an issue](https://github.com/tolitius/mount/issues))
|
|
||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
||||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||||
|
|
||||||
- [Why?](#why)
|
- [Why?](#why)
|
||||||
|
|
@ -34,6 +28,8 @@ _**Alan J. Perlis** from [Structure and Interpretation of Computer Programs](htt
|
||||||
- [Swapping States with States](#swapping-states-with-states)
|
- [Swapping States with States](#swapping-states-with-states)
|
||||||
- [Stop an Application Except Certain States](#stop-an-application-except-certain-states)
|
- [Stop an Application Except Certain States](#stop-an-application-except-certain-states)
|
||||||
- [ClojureScript is Clojure](doc/clojurescript.md#managing-state-in-clojurescript)
|
- [ClojureScript is Clojure](doc/clojurescript.md#managing-state-in-clojurescript)
|
||||||
|
- [cljc mode](#cljc-mode)
|
||||||
|
- [Disable Lazy Start](#disable-lazy-start)
|
||||||
- [Packaging](#packaging)
|
- [Packaging](#packaging)
|
||||||
- [Affected States](#affected-states)
|
- [Affected States](#affected-states)
|
||||||
- [Recompiling Namespaces with Running States](#recompiling-namespaces-with-running-states)
|
- [Recompiling Namespaces with Running States](#recompiling-namespaces-with-running-states)
|
||||||
|
|
@ -94,7 +90,7 @@ Creating state is easy:
|
||||||
(defstate conn :start (create-conn))
|
(defstate conn :start (create-conn))
|
||||||
```
|
```
|
||||||
|
|
||||||
where the `create-conn` function is defined elsewhere, can be right above it.
|
where the `create-conn` function creates a connection (for example to a database) and is defined elsewhere, can be right above it.
|
||||||
|
|
||||||
In case this state needs to be cleaned / destroyed between reloads, there is also `:stop`
|
In case this state needs to be cleaned / destroyed between reloads, there is also `:stop`
|
||||||
|
|
||||||
|
|
@ -107,7 +103,7 @@ That is pretty much it. But wait, there is more.. this state is _a top level bei
|
||||||
`required` by other namespaces or in REPL:
|
`required` by other namespaces or in REPL:
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
dev=> (require '[app.nyse :refer [conn]])
|
dev=> (require '[app.db :refer [conn]])
|
||||||
nil
|
nil
|
||||||
dev=> conn
|
dev=> conn
|
||||||
#object[datomic.peer.LocalConnection 0x1661a4eb "datomic.peer.LocalConnection@1661a4eb"]
|
#object[datomic.peer.LocalConnection 0x1661a4eb "datomic.peer.LocalConnection@1661a4eb"]
|
||||||
|
|
@ -124,6 +120,22 @@ For example let's say an `app` needs a connection above. No problem:
|
||||||
|
|
||||||
where `above` is an arbitrary namespace that defines the above state / connection.
|
where `above` is an arbitrary namespace that defines the above state / connection.
|
||||||
|
|
||||||
|
### Documentation String
|
||||||
|
|
||||||
|
As in any definition (i.e. `def`, `defn`) a documentation string can be added to better describe a state:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
(defstate answer
|
||||||
|
"answer to the ultimate question of life universe and everything"
|
||||||
|
:start (+ 1 41))
|
||||||
|
```
|
||||||
|
```clojure
|
||||||
|
(doc answer)
|
||||||
|
-------------------------
|
||||||
|
dev/answer
|
||||||
|
answer to the ultimate question of life universe and everything
|
||||||
|
```
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
If the whole app is one big application context (or `system`), cross dependencies with a solid dependency graph
|
If the whole app is one big application context (or `system`), cross dependencies with a solid dependency graph
|
||||||
|
|
@ -160,8 +172,9 @@ this `config`, being top level, can be used in other namespaces, including the o
|
||||||
(defstate conn :start (create-connection config))
|
(defstate conn :start (create-connection config))
|
||||||
```
|
```
|
||||||
|
|
||||||
[here](dev/clj/app/www.clj#L32)
|
[here](dev/clj/app/www.clj#L32) is an example of a web server that "depends" on a similar `config`.
|
||||||
is an example of a web server that "depends" on a similar `config`.
|
|
||||||
|
###### _(the example `load-config` function above comes from [cprop](https://github.com/tolitius/cprop), but could of course be a custom function that loads configuration from a file)_
|
||||||
|
|
||||||
## Value of values
|
## Value of values
|
||||||
|
|
||||||
|
|
@ -392,7 +405,7 @@ The `start-with-states` function takes values in a form of `{:start fn :stop fn}
|
||||||
```
|
```
|
||||||
|
|
||||||
`start-with-states` takes a map of states with their substitutes. For example `#'app.nyse/db` here is the real deal (remote) DB that is being
|
`start-with-states` takes a map of states with their substitutes. For example `#'app.nyse/db` here is the real deal (remote) DB that is being
|
||||||
substituted with `#(connect test-config)` function, which could endup being anything, a map, an in memory DB, etc.
|
substituted with `#(connect test-config)` function, which could end up being anything, a map, an in memory DB, etc.
|
||||||
|
|
||||||
The `:stop` functions of substitutes can be anything, and could refer to the original state references. As in the example above: `db` and `publisher`
|
The `:stop` functions of substitutes can be anything, and could refer to the original state references. As in the example above: `db` and `publisher`
|
||||||
are real references. They would need to be accessible from the namespace of course, so you might need to `(:require [app.neo :refer [db]])`
|
are real references. They would need to be accessible from the namespace of course, so you might need to `(:require [app.neo :refer [db]])`
|
||||||
|
|
@ -535,6 +548,56 @@ Mount detected that `#'dev/won't-be-here-long` was deleted, hence:
|
||||||
<< stopping.. #'dev/won't-be-here-long (it was deleted)
|
<< stopping.. #'dev/won't-be-here-long (it was deleted)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `cljc` mode
|
||||||
|
|
||||||
|
By default mount states are kept under var references. While it works for Clojure, it falls short in the land of ClojureScript since, especially during an `:advanced` compilation, var names get compressed + ClojureScript does not support reified vars.
|
||||||
|
|
||||||
|
To support both Clojure and ClojureScript mount has a `cljc` mode which is well documented in [here](doc/clojurescript.md#managing-state-in-clojurescript), and can be enabled by `(mount/in-cljc-mode)`.
|
||||||
|
|
||||||
|
### Disable Lazy Start
|
||||||
|
|
||||||
|
When in `cljc` mode, mount states that are not started by `(mount/start a b c)`, or that are not transitive states: i.e. not `:require`d at the time `(mount/start)` is called, will start lazily whenever they are dereferenced:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
=> (mount/in-cljc-mode)
|
||||||
|
:cljc
|
||||||
|
|
||||||
|
=> (defstate db-connection :start (println "connecting")
|
||||||
|
:stop (println "disconnecting..."))
|
||||||
|
|
||||||
|
=> db-connection
|
||||||
|
#object[mount.core.DerefableState 0x546b9d51 {:status :pending, :val nil}]
|
||||||
|
|
||||||
|
dev=> (mount/running-states)
|
||||||
|
#{}
|
||||||
|
|
||||||
|
dev=> @db-connection ;; db-connection will start here when deref'ed even though it was not started explicitly
|
||||||
|
connecting
|
||||||
|
|
||||||
|
dev=> (mount/running-states)
|
||||||
|
#{"#'dev/db-connection"}
|
||||||
|
```
|
||||||
|
|
||||||
|
This can be quite handy as it allows certain app states to start lazily.
|
||||||
|
|
||||||
|
However there are cases when it is best to fail in case a certain state is deref'ed while it was not yet started. This is possible by marking such states with `^{:on-lazy-start :throw}` metadata:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
=> (defstate ^{:on-lazy-start :throw} db-connection :start (do (println "connecting") 42)
|
||||||
|
:stop (println "disconnecting..."))
|
||||||
|
|
||||||
|
=> @db-connection ;; this will throw since db connection is deref'ed before it was started
|
||||||
|
|
||||||
|
java.lang.RuntimeException: :on-lazy-start is set to :throw i.e. (defstate {:on-lazy-start :throw} #'dev/db-connection...) and #'dev/db-connection state was not explicitly started before it was deref'ed (i.e. @#'dev/db-connection)
|
||||||
|
|
||||||
|
=> (mount/start #'dev/db-connection)
|
||||||
|
connecting
|
||||||
|
{:started ["#'dev/db-connection"]}
|
||||||
|
|
||||||
|
=> @db-connection
|
||||||
|
42
|
||||||
|
```
|
||||||
|
|
||||||
## Packaging
|
## Packaging
|
||||||
|
|
||||||
Since `mount` relies on the Clojure/Script Compiler to learn about all the application states, before `mount/start` is called all the namespaces that have `defstate`s need to be compiled.
|
Since `mount` relies on the Clojure/Script Compiler to learn about all the application states, before `mount/start` is called all the namespaces that have `defstate`s need to be compiled.
|
||||||
|
|
@ -798,7 +861,7 @@ The documentation is [here](doc/runtime-arguments.md#passing-runtime-arguments).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright © 2017 tolitius
|
Copyright © 2020 tolitius
|
||||||
|
|
||||||
Distributed under the Eclipse Public License either version 1.0 or (at
|
Distributed under the Eclipse Public License either version 1.0 or (at
|
||||||
your option) any later version.
|
your option) any later version.
|
||||||
|
|
|
||||||
2
boot.properties
Normal file
2
boot.properties
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
BOOT_VERSION=2.7.1
|
||||||
|
BOOT_CLOJURE_VERSION=1.10.1
|
||||||
25
build.boot
25
build.boot
|
|
@ -1,8 +1,18 @@
|
||||||
(def +version+ "0.1.12")
|
(def +version+ "0.1.18")
|
||||||
|
|
||||||
|
;; -- since boot is no more, this file will go away
|
||||||
|
;; -- once deps.edn "learns" how to run all cljs tests
|
||||||
|
|
||||||
|
;; j8; boot test
|
||||||
|
;; j8; boot test-cljs
|
||||||
|
;; j8; boot test-cljs-advanced
|
||||||
|
;; j8; boot -v build-jar push-snapshot
|
||||||
|
;; j8; boot -v build-jar push-release
|
||||||
|
|
||||||
(set-env!
|
(set-env!
|
||||||
:source-paths #{"src"}
|
:source-paths #{"src"}
|
||||||
:dependencies '[;; mount brings _no dependencies_, everything here is for
|
:resource-paths #{"resources"}
|
||||||
|
:dependencies '[;; mount brings _NO DEPENDENCIES_, everything here is for
|
||||||
;; mount dev, examples apps and tests
|
;; mount dev, examples apps and tests
|
||||||
|
|
||||||
[org.clojure/clojure "1.8.0" :scope "provided"]
|
[org.clojure/clojure "1.8.0" :scope "provided"]
|
||||||
|
|
@ -13,6 +23,7 @@
|
||||||
[cheshire "5.5.0" :scope "provided"]
|
[cheshire "5.5.0" :scope "provided"]
|
||||||
[hiccups "0.3.0" :scope "provided" :exclusions [org.clojure/clojurescript]]
|
[hiccups "0.3.0" :scope "provided" :exclusions [org.clojure/clojurescript]]
|
||||||
[com.andrewmcveigh/cljs-time "0.3.14" :scope "provided"]
|
[com.andrewmcveigh/cljs-time "0.3.14" :scope "provided"]
|
||||||
|
[tolitius/yang "0.1.9" :scope "provided"]
|
||||||
[ch.qos.logback/logback-classic "1.1.3" :scope "provided"]
|
[ch.qos.logback/logback-classic "1.1.3" :scope "provided"]
|
||||||
[org.clojure/tools.logging "0.3.1" :scope "provided"]
|
[org.clojure/tools.logging "0.3.1" :scope "provided"]
|
||||||
[robert/hooke "1.3.0" :scope "provided"]
|
[robert/hooke "1.3.0" :scope "provided"]
|
||||||
|
|
@ -33,11 +44,12 @@
|
||||||
|
|
||||||
;; boot cljs
|
;; boot cljs
|
||||||
[adzerk/boot-cljs "1.7.228-1" :scope "test"]
|
[adzerk/boot-cljs "1.7.228-1" :scope "test"]
|
||||||
[adzerk/boot-cljs-repl "0.3.0" :scope "test"]
|
[adzerk/boot-cljs-repl "0.4.0" :scope "test"]
|
||||||
|
[cider/piggieback "0.3.9" :scope "test" :exclusions [org.clojure/clojurescript]]
|
||||||
|
[weasel "0.7.0" :scope "test" :exclusions [org.clojure/clojurescript]]
|
||||||
|
[nrepl "0.4.5" :scope "test"]
|
||||||
[pandeiro/boot-http "0.7.1-SNAPSHOT" :scope "test"]
|
[pandeiro/boot-http "0.7.1-SNAPSHOT" :scope "test"]
|
||||||
[tolitius/boot-stripper "0.1.0-SNAPSHOT" :scope "test"]
|
[tolitius/boot-stripper "0.1.0-SNAPSHOT" :scope "test"]
|
||||||
[com.cemerick/piggieback "0.2.1" :scope "test" :exclusions [org.clojure/clojurescript]]
|
|
||||||
[weasel "0.7.0" :scope "test" :exclusions [org.clojure/clojurescript]]
|
|
||||||
[adzerk/boot-reload "0.4.8" :scope "test"]
|
[adzerk/boot-reload "0.4.8" :scope "test"]
|
||||||
[crisptrutski/boot-cljs-test "0.2.1-SNAPSHOT" :scope "test"]])
|
[crisptrutski/boot-cljs-test "0.2.1-SNAPSHOT" :scope "test"]])
|
||||||
|
|
||||||
|
|
@ -132,7 +144,8 @@
|
||||||
|
|
||||||
(task-options!
|
(task-options!
|
||||||
tcs/test-cljs {:js-env :phantom}
|
tcs/test-cljs {:js-env :phantom}
|
||||||
push {:ensure-branch nil}
|
push {; :ensure-clean nil
|
||||||
|
:ensure-branch nil}
|
||||||
pom {:project 'mount
|
pom {:project 'mount
|
||||||
:version +version+
|
:version +version+
|
||||||
:description "managing Clojure and ClojureScript app state since (reset)"
|
:description "managing Clojure and ClojureScript app state since (reset)"
|
||||||
|
|
|
||||||
17
circle.yml
17
circle.yml
|
|
@ -1,17 +0,0 @@
|
||||||
machine:
|
|
||||||
java:
|
|
||||||
version: oraclejdk8
|
|
||||||
environment:
|
|
||||||
_JAVA_OPTIONS: "-Xms512m -Xmx2048m"
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
pre:
|
|
||||||
- wget https://github.com/boot-clj/boot-bin/releases/download/latest/boot.sh
|
|
||||||
- mv boot.sh boot && chmod a+x boot && sudo mv boot /usr/local/bin
|
|
||||||
|
|
||||||
test:
|
|
||||||
override:
|
|
||||||
- boot test
|
|
||||||
- boot test-cljs
|
|
||||||
- boot test-cljs-advanced
|
|
||||||
- lein do clean, test2junit
|
|
||||||
52
deps.edn
Normal file
52
deps.edn
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
{:paths ["src" "resources"]
|
||||||
|
|
||||||
|
:deps {} ;; deps no deps
|
||||||
|
|
||||||
|
:aliases {:dev {:extra-deps {metosin/jsonista {:mvn/version "0.3.8"}
|
||||||
|
com.datomic/datomic-free {:mvn/version "0.9.5359"
|
||||||
|
:exclusions [joda-time/joda-time]}
|
||||||
|
org.clojure/tools.nrepl {:mvn/version "0.2.12"}
|
||||||
|
org.clojure/tools.namespace {:mvn/version "0.2.11"}
|
||||||
|
cheshire/cheshire {:mvn/version "5.5.0"}
|
||||||
|
compojure/compojure {:mvn/version "1.5.0"}
|
||||||
|
ring/ring-jetty-adapter {:mvn/version "1.1.0"}
|
||||||
|
robert/hooke {:mvn/version "1.3.0"}
|
||||||
|
proto-repl/proto-repl {:mvn/version "0.3.1"}
|
||||||
|
proto-repl-charts/proto-repl-charts {:mvn/version "0.3.2"}
|
||||||
|
nrepl/nrepl {:mvn/version "0.7.0"}}}
|
||||||
|
:test {:extra-paths ["test/core" "test/clj" "test/cljs" "test/resources"]
|
||||||
|
:extra-deps {com.datomic/datomic-free {:mvn/version "0.9.5359"
|
||||||
|
:exclusions [joda-time/joda-time]}
|
||||||
|
org.clojure/tools.nrepl {:mvn/version "0.2.12"}
|
||||||
|
robert/hooke {:mvn/version "1.3.0"}
|
||||||
|
org.clojure/tools.logging {:mvn/version "1.3.0"}
|
||||||
|
io.github.cognitect-labs/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
|
||||||
|
:sha "e7660458ce25bc4acb4ccc3e2415aae0a4907198"}}
|
||||||
|
:main-opts ["-m" "cognitect.test-runner"]
|
||||||
|
:exec-fn cognitect.test-runner.api/test}
|
||||||
|
:test-cljs {:extra-paths ["test/core" "test/cljs" "test/resources"]
|
||||||
|
:extra-deps {org.clojure/clojure {:mvn/version "1.8.0"}
|
||||||
|
org.clojure/clojurescript {:mvn/version "1.7.228"}
|
||||||
|
com.andrewmcveigh/cljs-time {:mvn/version "0.3.14"}
|
||||||
|
hiccups/hiccups {:mvn/version "0.3.0"}
|
||||||
|
datascript/datascript {:mvn/version "0.15.0"}
|
||||||
|
olical/cljs-test-runner {:mvn/version "3.8.1"}}
|
||||||
|
:main-opts ["-m" "cljs-test-runner.main"]}
|
||||||
|
:repl {:extra-paths ["dev/clj"]
|
||||||
|
:extra-deps {cider/cider-nrepl {:mvn/version "0.22.4"}
|
||||||
|
org.clojure/tools.logging {:mvn/version "1.2.4"}
|
||||||
|
com.bhauman/rebel-readline {:mvn/version "0.1.4"}}
|
||||||
|
:main-opts ["-e" "(require 'dev)(in-ns 'dev)"
|
||||||
|
"-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"
|
||||||
|
"-i" "-f" "rebel-readline.main/-main"]}
|
||||||
|
:outdated {:extra-deps {olical/depot {:mvn/version "2.0.1"}}
|
||||||
|
:main-opts ["-m" "depot.outdated.main" "-a" "outdated"]}
|
||||||
|
:tag {:extra-deps {tolitius/tag {:mvn/version "0.1.7"}}
|
||||||
|
:main-opts ["-m" "tag.core" "tolitius/mount" "managing Clojure and ClojureScript app state since (reset)"]}
|
||||||
|
:jar {:extra-deps {seancorfield/depstar {:mvn/version "1.1.128"}}
|
||||||
|
:extra-paths ["target/about"]
|
||||||
|
:main-opts ["-m" "hf.depstar.jar" "target/mount.jar" "--exclude" "clojure/core/specs/alpha.*"]}
|
||||||
|
:deploy {:extra-deps {deps-deploy/deps-deploy {:mvn/version "RELEASE"}}
|
||||||
|
:main-opts ["-m" "deps-deploy.deps-deploy" "deploy" "target/mount.jar"]}
|
||||||
|
:install {:extra-deps {deps-deploy/deps-deploy {:mvn/version "RELEASE"}}
|
||||||
|
:main-opts ["-m" "deps-deploy.deps-deploy" "install" "target/mount.jar"]}}}
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
(defn load-config [path]
|
(defn load-config [path]
|
||||||
(info "loading config from" path)
|
(info "loading config from" path)
|
||||||
(-> path
|
(-> path
|
||||||
slurp
|
slurp
|
||||||
edn/read-string))
|
edn/read-string))
|
||||||
|
|
||||||
(defstate config
|
(defstate config
|
||||||
:start (load-config "dev/resources/config.edn"))
|
:start (load-config "dev/resources/config.edn"))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(ns app.db
|
(ns app.db
|
||||||
(:require [mount.core :refer [defstate]]
|
(:require [mount.core :refer [defstate]]
|
||||||
[datomic.api :as d]
|
[datomic.api :as d]
|
||||||
[clojure.tools.logging :refer [info]]
|
[clojure.tools.logging :refer [info]]
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
:db/valueType :db.type/bigdec
|
:db/valueType :db.type/bigdec
|
||||||
:db/cardinality :db.cardinality/one
|
:db/cardinality :db.cardinality/one
|
||||||
:db.install/_attribute :db.part/db}
|
:db.install/_attribute :db.part/db}
|
||||||
|
|
||||||
{:db/id #db/id [:db.part/db]
|
{:db/id #db/id [:db.part/db]
|
||||||
:db/ident :order/qty
|
:db/ident :order/qty
|
||||||
:db/valueType :db.type/long
|
:db/valueType :db.type/long
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@
|
||||||
|
|
||||||
(defn find-orders [conn ticker]
|
(defn find-orders [conn ticker]
|
||||||
(let [orders (d/q '[:find ?e :in $ ?ticker
|
(let [orders (d/q '[:find ?e :in $ ?ticker
|
||||||
:where [?e :order/symbol ?ticker]]
|
:where [?e :order/symbol ?ticker]]
|
||||||
(d/db conn) ticker)]
|
(d/db conn) ticker)]
|
||||||
(touch conn orders)))
|
(touch conn orders)))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(ns app.utils.logging ;; << change to your namespace/path
|
(ns app.utils.logging ;; << change to your namespace/path
|
||||||
(:require [mount.core]
|
(:require [mount.core]
|
||||||
[robert.hooke :refer [add-hook clear-hooks]]
|
[robert.hooke :refer [add-hook clear-hooks]]
|
||||||
[clojure.string :refer [split]]
|
[clojure.string :refer [split]]
|
||||||
|
|
@ -21,9 +21,9 @@
|
||||||
:down "<< stopping"
|
:down "<< stopping"
|
||||||
false))
|
false))
|
||||||
|
|
||||||
(defn log-status [f & args]
|
(defn log-status [f & args]
|
||||||
(let [[state-name state] args
|
(let [[state-name state] args
|
||||||
action (f-to-action f state)]
|
action (f-to-action f state)]
|
||||||
(when-let [taking-over-the-world (whatcha-doing? action)]
|
(when-let [taking-over-the-world (whatcha-doing? action)]
|
||||||
(info (str taking-over-the-world ".. " state-name)))
|
(info (str taking-over-the-world ".. " state-name)))
|
||||||
(apply f args)))
|
(apply f args)))
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
(GET "/nyse/orders/:ticker" [ticker]
|
(GET "/nyse/orders/:ticker" [ticker]
|
||||||
(generate-string (find-orders conn ticker)))
|
(generate-string (find-orders conn ticker)))
|
||||||
|
|
||||||
(POST "/nyse/orders" [ticker qty bid offer]
|
(POST "/nyse/orders" [ticker qty bid offer]
|
||||||
(let [order {:ticker ticker
|
(let [order {:ticker ticker
|
||||||
:bid (bigdec bid)
|
:bid (bigdec bid)
|
||||||
:offer (bigdec offer)
|
:offer (bigdec offer)
|
||||||
:qty (Integer/parseInt qty)}]
|
:qty (Integer/parseInt qty)}]
|
||||||
(add-order conn order)
|
(add-order conn order)
|
||||||
(generate-string {:added order}))))
|
(generate-string {:added order}))))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
(ns dev
|
(ns dev
|
||||||
(:require [clojure.pprint :refer [pprint]]
|
(:require [clojure.pprint :refer [pprint]]
|
||||||
[clojure.tools.namespace.repl :as tn]
|
[clojure.tools.namespace.repl :as tn]
|
||||||
[boot.core :refer [load-data-readers!]]
|
|
||||||
[mount.core :as mount :refer [defstate]]
|
[mount.core :as mount :refer [defstate]]
|
||||||
[mount.tools.graph :refer [states-with-deps]]
|
[mount.tools.graph :refer [states-with-deps]]
|
||||||
[app.utils.logging :refer [with-logging-status]]
|
[app.utils.logging :refer [with-logging-status]]
|
||||||
|
|
@ -41,4 +40,11 @@
|
||||||
(tn/refresh :after 'dev/go))
|
(tn/refresh :after 'dev/go))
|
||||||
|
|
||||||
(mount/in-clj-mode)
|
(mount/in-clj-mode)
|
||||||
|
|
||||||
|
(defn load-data-readers!
|
||||||
|
"Refresh *data-readers* with readers from newly acquired dependencies."
|
||||||
|
[]
|
||||||
|
(#'clojure.core/load-data-readers)
|
||||||
|
(set! *data-readers* (.getRawRoot #'*data-readers*)))
|
||||||
|
|
||||||
(load-data-readers!)
|
(load-data-readers!)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
(ns proto-play
|
(ns proto-play
|
||||||
(:require [mount.tools.graph :as mount]
|
(:require [mount.tools.graph :as mg]
|
||||||
[proto-repl-charts.graph :as proto]))
|
[proto-repl-charts.graph :as proto]))
|
||||||
|
|
||||||
(defn mount->proto [graph]
|
(defn mount->proto [graph]
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
{}
|
{}
|
||||||
graph))
|
graph))
|
||||||
|
|
||||||
(->> (mount/states-with-deps)
|
(->> (mg/states-with-deps)
|
||||||
mount->proto
|
mount->proto
|
||||||
(proto/graph "a proto graph of mount states"))
|
(proto/graph "a proto graph of mount states"))
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@
|
||||||
|
|
||||||
(defn find-source-logs [db source]
|
(defn find-source-logs [db source]
|
||||||
(d/q '{:find [?t ?msg]
|
(d/q '{:find [?t ?msg]
|
||||||
:in [$ ?s]
|
:in [$ ?s]
|
||||||
:where [[?e :source ?s]
|
:where [[?e :source ?s]
|
||||||
[?e :timestamp ?t]
|
[?e :timestamp ?t]
|
||||||
[?e :msg ?msg]]}
|
[?e :msg ?msg]]}
|
||||||
@@db source))
|
@@db source))
|
||||||
|
|
||||||
(defn find-all-logs [db]
|
(defn find-all-logs [db]
|
||||||
(->> (map :e (d/datoms @@db :aevt :timestamp))
|
(->> (map :e (d/datoms @@db :aevt :timestamp))
|
||||||
dedupe
|
dedupe
|
||||||
(d/pull-many @@db '[:timestamp :source :msg])))
|
(d/pull-many @@db '[:timestamp :source :msg])))
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
" → [" (name source) "]: " msg))
|
" → [" (name source) "]: " msg))
|
||||||
|
|
||||||
(defn show-log []
|
(defn show-log []
|
||||||
(.write js/document
|
(.write js/document
|
||||||
(html [:ul (doall (for [e (find-all-logs log)]
|
(html [:ul (doall (for [e (find-all-logs log)]
|
||||||
[:li (format-log-event e)]))])))
|
[:li (format-log-event e)]))])))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{:datomic
|
{:datomic
|
||||||
{:uri "datomic:mem://mount"}
|
{:uri "datomic:mem://mount"}
|
||||||
|
|
||||||
:www {:port 4242}
|
:www {:port 4242}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
- [Using States](#using-states)
|
- [Using States](#using-states)
|
||||||
- [Thanks](#thanks)
|
- [Thanks](#thanks)
|
||||||
|
|
||||||
In case you need to manage state in ClojureScript using mount, _all_ the mount Clojure features are supported in ClojureScript.
|
In case you need to manage state in ClojureScript using mount, _all_ the mount Clojure features are supported in ClojureScript.
|
||||||
Which means all the mount Clojure [documentation](../README.md) is the mount ClojureScript documentation.
|
Which means all the mount Clojure [documentation](../README.md) is the mount ClojureScript documentation.
|
||||||
|
|
||||||
With a slight change in [_mode_](clojurescript.md#mount-modes) ( no change in _mood_ though, just the _mode_ :)).
|
With a slight change in [_mode_](clojurescript.md#mount-modes) ( no change in _mood_ though, just the _mode_ :)).
|
||||||
|
|
@ -16,19 +16,19 @@ With a slight change in [_mode_](clojurescript.md#mount-modes) ( no change in _m
|
||||||
### The "Why"
|
### The "Why"
|
||||||
|
|
||||||
Since [reader conditionals](http://clojure.org/reader#The%20Reader--Reader%20Conditionals) were added in Clojure 1.7,
|
Since [reader conditionals](http://clojure.org/reader#The%20Reader--Reader%20Conditionals) were added in Clojure 1.7,
|
||||||
it became a lot easier to target both platforms with lots of code reuse. You might have noticed
|
it became a lot easier to target both platforms with lots of code reuse. You might have noticed
|
||||||
that most of mount code lives in `.cljc` files.
|
that most of mount code lives in `.cljc` files.
|
||||||
|
|
||||||
The way mount is designed it "mounts" itself to a solid Clojure [namespace API](http://clojure.org/namespaces),
|
The way mount is designed it "mounts" itself to a solid Clojure [namespace API](http://clojure.org/namespaces),
|
||||||
and while `.cljc` helps a lot with targeting Clojure and ClojureScript, JavaScript VM is vastly different from JVM.
|
and while `.cljc` helps a lot with targeting Clojure and ClojureScript, JavaScript VM is vastly different from JVM.
|
||||||
Since JavaScript mostly tagrets browsers, mobile devices and IoT,
|
Since JavaScript mostly tagrets browsers, mobile devices and IoT,
|
||||||
it is quite important to [compress](https://github.com/clojure/clojurescript/wiki/Advanced-Compilation) the final result.
|
it is quite important to [compress](https://github.com/clojure/clojurescript/wiki/Advanced-Compilation) the final result.
|
||||||
|
|
||||||
Which means that Clojure namespaces API are not that well supported in ClojureScript, since they get renamed and optimized
|
Which means that Clojure namespaces API are not that well supported in ClojureScript, since they get renamed and optimized
|
||||||
during compilation + of course no native namespace support on the JavaScript side
|
during compilation + of course no native namespace support on the JavaScript side
|
||||||
(but that is somewhat solved with [Google Closure](https://closure-library.googlecode.com/git-history/docs/local_closure_goog_base.js.source.html#line428)).
|
(but that is somewhat solved with [Google Closure](https://closure-library.googlecode.com/git-history/docs/local_closure_goog_base.js.source.html#line428)).
|
||||||
|
|
||||||
But. When developing an application in Clojure and ClojureScript, it would only make sense if the API for any library
|
But. When developing an application in Clojure and ClojureScript, it would only make sense if the API for any library
|
||||||
would be _identical_ for both platforms. It should be transparent for developers whether they use a library in Clojure or ClojureScript.
|
would be _identical_ for both platforms. It should be transparent for developers whether they use a library in Clojure or ClojureScript.
|
||||||
It is not possible for all libraries (i.e. concurrency, reified Vars, etc.), but we should try to make it possible for most.
|
It is not possible for all libraries (i.e. concurrency, reified Vars, etc.), but we should try to make it possible for most.
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ To switch Mount into this mode do:
|
||||||
|
|
||||||
anywhere before a call to `(mount/start)`, usually at the entry point of an app: in the `-main`, web handler, etc.
|
anywhere before a call to `(mount/start)`, usually at the entry point of an app: in the `-main`, web handler, etc.
|
||||||
|
|
||||||
This sets mount into the `cljc` mode. In this mode mount supports _both_: Clojure and ClojureScript with one difference
|
This sets mount into the `cljc` mode. In this mode mount supports _both_: Clojure and ClojureScript with one difference
|
||||||
from the default `clj` mode:
|
from the default `clj` mode:
|
||||||
|
|
||||||
> all states are "_derefable_"
|
> all states are "_derefable_"
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ the same with or without Mount: there are no extra mental steps.
|
||||||
### Objects vs. Namespaces
|
### Objects vs. Namespaces
|
||||||
|
|
||||||
One thing that feels a bit "unClojure" about Component is "Objects". Objects everywhere, and Objects for everything.
|
One thing that feels a bit "unClojure" about Component is "Objects". Objects everywhere, and Objects for everything.
|
||||||
This is how Component "separates explicit dependencies" and "clears the bounaries".
|
This is how Component "separates explicit dependencies" and "clears the boundaries".
|
||||||
|
|
||||||
This is also how an Object Oriented language does it, which does not leave a lot of room for functions:
|
This is also how an Object Oriented language does it, which does not leave a lot of room for functions:
|
||||||
with Component most of the functions are _methods_ which is an important distinction.
|
with Component most of the functions are _methods_ which is an important distinction.
|
||||||
|
|
@ -146,9 +146,13 @@ no "ceremony".
|
||||||
|
|
||||||
Mount uses namespaces and vars where Component uses records and protocols.
|
Mount uses namespaces and vars where Component uses records and protocols.
|
||||||
|
|
||||||
Component manages protocols and records, and in order to do that it requires a whole app buyin, which makes it a _framework_.
|
Component manages records and protocols,
|
||||||
|
and in order to do that it requires a whole app buy-in,
|
||||||
|
which makes it a _framework_.
|
||||||
|
|
||||||
Mount does not need to manage namespaces and vars, since it is very well managed by the Clojure Compiler, which makes it a _library_.
|
Mount does not need to manage namespaces and vars,
|
||||||
|
since it is very well managed by the Clojure Compiler,
|
||||||
|
which makes it a _library_.
|
||||||
|
|
||||||
## What Component does better
|
## What Component does better
|
||||||
|
|
||||||
|
|
@ -156,9 +160,9 @@ Mount does not need to manage namespaces and vars, since it is very well managed
|
||||||
|
|
||||||
With Component multiple separate systems can be started _in the same Clojure runtime_ with different settings. Which _might_ be useful for testing, i.e. if you need to have `dev db` and `test db` started in the _same_ REPL, to _run tests within the same REPL you develop in_.
|
With Component multiple separate systems can be started _in the same Clojure runtime_ with different settings. Which _might_ be useful for testing, i.e. if you need to have `dev db` and `test db` started in the _same_ REPL, to _run tests within the same REPL you develop in_.
|
||||||
|
|
||||||
Development workflows vary and tend to be a subjective / preference based more than a true recipe, but I believe it is much cleaner to run tests in the _separate_ REPL / process. Moreover run them continuesly: i.e. `boot watch speak test`: this way you don't event need to look at that other REPL / terminal, Boot will _tell_ you whether the tests pass or fail after any file is changed.
|
Development workflows vary and tend to be a subjective / preference based more than a true recipe, but I believe it is much cleaner to run tests in the _separate_ REPL / process. Moreover run them continuously: i.e. `boot watch speak test`: this way you don't event need to look at that other REPL / terminal, Boot will _tell_ you whether the tests pass or fail after any file is changed.
|
||||||
|
|
||||||
Mount keeps states in namespaces, hence the app becomes "[The One](https://en.wikipedia.org/wiki/Neo_(The_Matrix))", and there can't be "multiples The Ones". In practice, if we are talking about stateful external resources, there is trully only _one_ of them with a given configuration. Different configuration => different state. It's is that simple.
|
Mount keeps states in namespaces, hence the app becomes "[The One](https://en.wikipedia.org/wiki/Neo_(The_Matrix))", and there can't be "multiples The Ones". In practice, if we are talking about stateful external resources, there is trully only _one_ of them with a given configuration. Different configuration => different state. It's that simple.
|
||||||
|
|
||||||
Testing is not alien to Mount and it knows how to do a thing or two:
|
Testing is not alien to Mount and it knows how to do a thing or two:
|
||||||
|
|
||||||
|
|
|
||||||
23
package.json
Normal file
23
package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"name": "@tolitius/mount",
|
||||||
|
"version": "0.1.16",
|
||||||
|
"license": "EPL-1.0",
|
||||||
|
"homepage": "https://github.com/tolitius/mount",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/tolitius/mount"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "tolitius",
|
||||||
|
"url": "http://www.dotkam.com"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/*"
|
||||||
|
],
|
||||||
|
"directories": {
|
||||||
|
"lib": "src"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ws": "^8.16.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
45
pom.xml
Normal file
45
pom.xml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<groupId>mount</groupId>
|
||||||
|
<artifactId>mount</artifactId>
|
||||||
|
<version>0.1.23</version>
|
||||||
|
<name>mount</name>
|
||||||
|
<description>managing Clojure and ClojureScript app state since (reset)</description>
|
||||||
|
<url>https://github.com/tolitius/mount</url>
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>Eclipse Public License</name>
|
||||||
|
<url>http://www.eclipse.org/legal/epl-v10.html</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>tolitius</name>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<url>https://github.com/tolitius/mount</url>
|
||||||
|
<connection>scm:git:git://github.com/tolitius/mount.git</connection>
|
||||||
|
<developerConnection>scm:git:ssh://git@github.com/tolitius/mount.git</developerConnection>
|
||||||
|
<tag>HEAD</tag>
|
||||||
|
</scm>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.clojure</groupId>
|
||||||
|
<artifactId>clojure</artifactId>
|
||||||
|
<version>1.11.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
</build>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>clojars</id>
|
||||||
|
<url>https://repo.clojars.org/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
</project>
|
||||||
14
project.clj
14
project.clj
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject mount "0.1.12-SNAPSHOT"
|
(defproject mount "0.1.17"
|
||||||
:description "managing Clojure and ClojureScript app state since (reset)"
|
:description "managing Clojure and ClojureScript app state since (reset)"
|
||||||
:url "https://github.com/tolitius/mount"
|
:url "https://github.com/tolitius/mount"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
@ -7,10 +7,13 @@
|
||||||
:source-paths ["src"]
|
:source-paths ["src"]
|
||||||
|
|
||||||
:dependencies [] ;; for visual clarity
|
:dependencies [] ;; for visual clarity
|
||||||
|
|
||||||
|
:tach {:test-runner-ns 'mount.test-self-host
|
||||||
|
:source-paths ["test/core"]}
|
||||||
|
|
||||||
:profiles {:dev {:source-paths ["dev" "dev/clj" "test/clj"]
|
:profiles {:dev {:source-paths ["dev" "dev/clj" "test/clj"]
|
||||||
:dependencies [[org.clojure/clojure "1.7.0"]
|
:dependencies [[org.clojure/clojure "1.8.0"]
|
||||||
[org.clojure/clojurescript "1.7.170"]; :classifier "aot"]
|
[org.clojure/clojurescript "1.9.946"]; :classifier "aot"]
|
||||||
[datascript "0.13.3"]
|
[datascript "0.13.3"]
|
||||||
[compojure "1.4.0"]
|
[compojure "1.4.0"]
|
||||||
[ring/ring-jetty-adapter "1.1.0"]
|
[ring/ring-jetty-adapter "1.1.0"]
|
||||||
|
|
@ -27,7 +30,8 @@
|
||||||
:plugins [[lein-cljsbuild "1.1.1"]
|
:plugins [[lein-cljsbuild "1.1.1"]
|
||||||
[lein-doo "0.1.6"]
|
[lein-doo "0.1.6"]
|
||||||
[lein-figwheel "0.5.0-2"]
|
[lein-figwheel "0.5.0-2"]
|
||||||
[test2junit "1.1.3"]]
|
[test2junit "1.1.3"]
|
||||||
|
[lein-tach "1.0.0"]]
|
||||||
|
|
||||||
:test2junit-output-dir ~(or (System/getenv "CIRCLE_TEST_REPORTS") "target/test2junit")
|
:test2junit-output-dir ~(or (System/getenv "CIRCLE_TEST_REPORTS") "target/test2junit")
|
||||||
|
|
||||||
|
|
|
||||||
3
resources/clj-kondo.exports/mount/mount/config.edn
Normal file
3
resources/clj-kondo.exports/mount/mount/config.edn
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{:linters {:mount/defstate {:level :warning}}
|
||||||
|
:hooks {:analyze-call {mount.core/defstate hooks.defstate/defstate
|
||||||
|
mount.core/defstate! hooks.defstate/defstate}}}
|
||||||
39
resources/clj-kondo.exports/mount/mount/hooks/defstate.clj
Normal file
39
resources/clj-kondo.exports/mount/mount/hooks/defstate.clj
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
(ns hooks.defstate
|
||||||
|
(:require [clj-kondo.hooks-api :as api]))
|
||||||
|
|
||||||
|
(defn defstate [{:keys [node]}]
|
||||||
|
(let [[n & args] (next (:children node))
|
||||||
|
[docs args] (if (string? (api/sexpr (first args)))
|
||||||
|
[(first args) (next args)]
|
||||||
|
[nil args])
|
||||||
|
m (when-let [m (first (:meta n))]
|
||||||
|
(api/sexpr m))
|
||||||
|
m (if (map? m) m {})
|
||||||
|
ks (cond-> (take 1 args)
|
||||||
|
(> (count args) 2) (conj (nth args 2)))
|
||||||
|
invalid-key (first (remove (comp (partial contains? #{:start :stop}) api/sexpr) ks))]
|
||||||
|
(cond
|
||||||
|
invalid-key
|
||||||
|
(api/reg-finding!
|
||||||
|
{:message (str "lifecycle functions can only contain `:start` and `:stop`. illegal function found: " (api/sexpr invalid-key))
|
||||||
|
:type :mount/defstate
|
||||||
|
:row (:row (meta invalid-key))
|
||||||
|
:col (:col (meta invalid-key))})
|
||||||
|
(not (contains? (set (map api/sexpr ks)) :start))
|
||||||
|
(throw (ex-info "lifecycle functions must include `:start`" {}))
|
||||||
|
((complement contains?) #{2 4} (count args))
|
||||||
|
(throw (ex-info "lifecycle functions must consist of no more than 2 pair forms: `:start` and `:stop`" {}))
|
||||||
|
(and (contains? m :on-reload) (not (contains? #{:noop :stop} (:on-reload m))))
|
||||||
|
(api/reg-finding!
|
||||||
|
{:message "metadata `:on-reload` key can only have value of `noop` or `stop`"
|
||||||
|
:type :mount/defstate
|
||||||
|
:row (:row (meta n))
|
||||||
|
:col (:col (meta n))})
|
||||||
|
:else
|
||||||
|
{:node (api/list-node
|
||||||
|
(cond-> [(api/token-node 'def) n]
|
||||||
|
docs (conj docs)
|
||||||
|
true (conj (api/list-node
|
||||||
|
(list*
|
||||||
|
(api/token-node 'do)
|
||||||
|
args)))))})))
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
(ns mount.core
|
(ns mount.core
|
||||||
|
#?(:clj {:clojure.tools.namespace.repl/load false}) ; prevent reloading of this ns
|
||||||
#?(:clj (:require [mount.tools.macro :refer [on-error throw-runtime] :as macro]
|
#?(:clj (:require [mount.tools.macro :refer [on-error throw-runtime] :as macro]
|
||||||
|
[mount.tools.macrovich :refer [deftime]]
|
||||||
[mount.tools.logger :refer [log]]
|
[mount.tools.logger :refer [log]]
|
||||||
[clojure.set :refer [intersection]]
|
[clojure.set :refer [intersection]]
|
||||||
[clojure.string :as s])
|
[clojure.string :as s])
|
||||||
:cljs (:require [mount.tools.macro :as macro]
|
:cljs (:require [mount.tools.macro]
|
||||||
[clojure.set :refer [intersection]]
|
[clojure.set :refer [intersection]]
|
||||||
[mount.tools.logger :refer [log]]))
|
[mount.tools.logger :refer [log]]))
|
||||||
#?(:cljs (:require-macros [mount.core]
|
#?(:cljs (:require-macros [mount.core]
|
||||||
[mount.tools.macro :refer [if-clj on-error throw-runtime]])))
|
[mount.tools.macro :refer [on-error throw-runtime]]
|
||||||
|
[mount.tools.macrovich :refer [deftime]])))
|
||||||
|
|
||||||
(defonce ^:private -args (atom {})) ;; mostly for command line args and external files
|
(defonce ^:private -args (atom {})) ;; mostly for command line args and external files
|
||||||
(defonce ^:private state-seq (atom 0))
|
(defonce ^:private state-seq (atom 0))
|
||||||
|
|
@ -15,10 +18,6 @@
|
||||||
(defonce ^:private meta-state (atom {}))
|
(defonce ^:private meta-state (atom {}))
|
||||||
(defonce ^:private running (atom {})) ;; to clean dirty states on redefs
|
(defonce ^:private running (atom {})) ;; to clean dirty states on redefs
|
||||||
|
|
||||||
;; supporting tools.namespace: (disable-reload!)
|
|
||||||
#?(:clj
|
|
||||||
(alter-meta! *ns* assoc ::load false)) ;; to exclude the dependency
|
|
||||||
|
|
||||||
(defn- make-state-seq [state]
|
(defn- make-state-seq [state]
|
||||||
(or (:order (@meta-state state))
|
(or (:order (@meta-state state))
|
||||||
(swap! state-seq inc)))
|
(swap! state-seq inc)))
|
||||||
|
|
@ -58,17 +57,6 @@
|
||||||
(stop))
|
(stop))
|
||||||
(swap! running dissoc state)))
|
(swap! running dissoc state)))
|
||||||
|
|
||||||
#?(:clj
|
|
||||||
(defn current-state [state]
|
|
||||||
(let [{:keys [inst var]} (@meta-state state)]
|
|
||||||
(if (= @mode :cljc)
|
|
||||||
@inst
|
|
||||||
(var-get var))))
|
|
||||||
|
|
||||||
:cljs
|
|
||||||
(defn current-state [state]
|
|
||||||
(-> (@meta-state state) :inst deref)))
|
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(defn alter-state! [{:keys [var inst]} value]
|
(defn alter-state! [{:keys [var inst]} value]
|
||||||
(if (= @mode :cljc)
|
(if (= @mode :cljc)
|
||||||
|
|
@ -110,8 +98,8 @@
|
||||||
:fail? false)
|
:fail? false)
|
||||||
:f-failed)]
|
:f-failed)]
|
||||||
(log cause :error) ;; this would mostly be useful in REPL / browser console
|
(log cause :error) ;; this would mostly be useful in REPL / browser console
|
||||||
(alter-state! current (NotStartedState. state)))
|
(alter-state! current (->NotStartedState state)))
|
||||||
(alter-state! current (NotStartedState. state))) ;; (!) if a state does not have :stop when _should_ this might leak
|
(alter-state! current (->NotStartedState state))) ;; (!) if a state does not have :stop when _should_ this might leak
|
||||||
(swap! running dissoc state)
|
(swap! running dissoc state)
|
||||||
(update-meta! [state :status] #{:stopped})))
|
(update-meta! [state :status] #{:stopped})))
|
||||||
|
|
||||||
|
|
@ -124,9 +112,12 @@
|
||||||
(#?(:clj deref
|
(#?(:clj deref
|
||||||
:cljs -deref)
|
:cljs -deref)
|
||||||
[_]
|
[_]
|
||||||
(let [{:keys [status inst] :as state} (@meta-state name)]
|
(let [{:keys [status var inst] :as state} (@meta-state name)]
|
||||||
(when-not (:started status)
|
(when-not (:started status)
|
||||||
(up name state (atom #{})))
|
(if (= :throw (-> var meta :on-lazy-start))
|
||||||
|
(throw-runtime (str ":on-lazy-start is set to :throw i.e. (defstate {:on-lazy-start :throw} " name "...) "
|
||||||
|
"and " name " state was not explicitly started before it was deref'ed (i.e. @" name ")"))
|
||||||
|
(up name state (atom #{}))))
|
||||||
@inst))
|
@inst))
|
||||||
#?(:clj clojure.lang.IPending
|
#?(:clj clojure.lang.IPending
|
||||||
:cljs IPending)
|
:cljs IPending)
|
||||||
|
|
@ -135,6 +126,17 @@
|
||||||
[_]
|
[_]
|
||||||
(boolean ((running-states) name))))
|
(boolean ((running-states) name))))
|
||||||
|
|
||||||
|
#?(:clj
|
||||||
|
(defn current-state [state]
|
||||||
|
(let [{:keys [var]} (@meta-state state)]
|
||||||
|
(if (= @mode :cljc)
|
||||||
|
(->DerefableState state)
|
||||||
|
(var-get var))))
|
||||||
|
|
||||||
|
:cljs
|
||||||
|
(defn current-state [state]
|
||||||
|
(-> (@meta-state state) :inst deref)))
|
||||||
|
|
||||||
(defn on-reload-meta [s-var]
|
(defn on-reload-meta [s-var]
|
||||||
(or (-> s-var meta :on-reload)
|
(or (-> s-var meta :on-reload)
|
||||||
:restart)) ;; restart by default on ns reload
|
:restart)) ;; restart by default on ns reload
|
||||||
|
|
@ -146,10 +148,10 @@
|
||||||
(and (status :started)
|
(and (status :started)
|
||||||
(= :noop on-reload)))))
|
(= :noop on-reload)))))
|
||||||
|
|
||||||
;;TODO: make private after figuring out the inconsistency betwen cljs compile stages
|
;;TODO: make private after figuring out the inconsistency betwen cljs compile stages
|
||||||
;; (i.e. _sometimes_ this, if private, is not seen by expanded "defmacro" on cljs side)
|
;; (i.e. _sometimes_ this, if private, is not seen by expanded "defmacro" on cljs side)
|
||||||
(defn mount-it [s-var s-name s-meta]
|
(defn mount-it [s-var s-name s-meta]
|
||||||
(let [with-inst (assoc s-meta :inst (atom (NotStartedState. s-name))
|
(let [with-inst (assoc s-meta :inst (atom (->NotStartedState s-name))
|
||||||
:var s-var)
|
:var s-var)
|
||||||
on-reload (on-reload-meta s-var)
|
on-reload (on-reload-meta s-var)
|
||||||
existing? (when-not (= :noop on-reload)
|
existing? (when-not (= :noop on-reload)
|
||||||
|
|
@ -159,39 +161,42 @@
|
||||||
(log (str ">> starting.. " s-name " (namespace was recompiled)"))
|
(log (str ">> starting.. " s-name " (namespace was recompiled)"))
|
||||||
(up s-name with-inst (atom #{})))))
|
(up s-name with-inst (atom #{})))))
|
||||||
|
|
||||||
#?(:clj
|
(deftime
|
||||||
(defmacro defstate
|
|
||||||
"Defines a state. Restarts on recompilation.
|
|
||||||
Pass ^{:on-reload :noop} to prevent auto-restart
|
|
||||||
on ns recompilation, or :stop to stop on recompilation."
|
|
||||||
[state & body]
|
|
||||||
(let [[state params] (macro/name-with-attributes state body)
|
|
||||||
{:keys [start stop] :as lifecycle} (apply hash-map params)
|
|
||||||
state-name (with-ns *ns* state)
|
|
||||||
order (make-state-seq state-name)]
|
|
||||||
(validate lifecycle)
|
|
||||||
(let [s-meta (cond-> {:order order
|
|
||||||
:start `(fn [] ~start)
|
|
||||||
:status #{:stopped}}
|
|
||||||
stop (assoc :stop `(fn [] ~stop)))]
|
|
||||||
`(do
|
|
||||||
;; (log (str "|| mounting... " ~state-name))
|
|
||||||
;; only create/redefine a new state iff this is not a running ^{:on-reload :noop}
|
|
||||||
(if-not (running-noop? ~state-name)
|
|
||||||
(do
|
|
||||||
(~'defonce ~state (DerefableState. ~state-name))
|
|
||||||
(mount-it (~'var ~state) ~state-name ~s-meta))
|
|
||||||
(~'defonce ~state (current-state ~state-name)))
|
|
||||||
(~'var ~state))))))
|
|
||||||
|
|
||||||
#?(:clj
|
(defmacro defstate
|
||||||
(defmacro defstate! [state & {:keys [start! stop!]}]
|
"defines a state (a.k.a. a stateful component).
|
||||||
(let [state-name (with-ns *ns* state)]
|
restarts on recompilation.
|
||||||
`(defstate ~state
|
pass ^{:on-reload :noop} to prevent auto-restart on ns recompilation,
|
||||||
:start (~'let [~state (mount/current-state ~state-name)]
|
or ^{:on-reload :stop} to stop on recompilation."
|
||||||
~start!)
|
[state & body]
|
||||||
:stop (~'let [~state (mount/current-state ~state-name)]
|
(let [[state params] (mount.tools.macro/name-with-attributes state body)
|
||||||
~stop!)))))
|
{:keys [start stop] :as lifecycle} (apply hash-map params)
|
||||||
|
state-name (with-ns *ns* state)
|
||||||
|
order (make-state-seq state-name)]
|
||||||
|
(validate lifecycle)
|
||||||
|
(let [s-meta (cond-> {:order order
|
||||||
|
:start `(fn [] ~start)
|
||||||
|
:status #{:stopped}}
|
||||||
|
stop (assoc :stop `(fn [] ~stop)))]
|
||||||
|
`(do
|
||||||
|
;; (log (str "|| mounting... " ~state-name))
|
||||||
|
;; only create/redefine a new state iff this is not a running ^{:on-reload :noop}
|
||||||
|
(if-not (running-noop? ~state-name)
|
||||||
|
(do
|
||||||
|
(~'defonce ~state (->DerefableState ~state-name))
|
||||||
|
(mount-it (~'var ~state) ~state-name ~s-meta))
|
||||||
|
(~'defonce ~state (current-state ~state-name)))
|
||||||
|
(~'var ~state)))))
|
||||||
|
|
||||||
|
(defmacro defstate! [state & {:keys [start! stop!]}]
|
||||||
|
(let [state-name (with-ns *ns* state)]
|
||||||
|
`(defstate ~state
|
||||||
|
:start (~'let [~state (mount.core/current-state ~state-name)]
|
||||||
|
~start!)
|
||||||
|
:stop (~'let [~state (mount.core/current-state ~state-name)]
|
||||||
|
~stop!))))
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
(defn in-cljc-mode []
|
(defn in-cljc-mode []
|
||||||
(reset! mode :cljc))
|
(reset! mode :cljc))
|
||||||
|
|
@ -279,7 +284,7 @@
|
||||||
(if-not (empty? fs) ;; (mount/start) vs. (mount/start #{}) vs. (mount/start #{1 2 3})
|
(if-not (empty? fs) ;; (mount/start) vs. (mount/start #{}) vs. (mount/start #{1 2 3})
|
||||||
(apply start fs)
|
(apply start fs)
|
||||||
{:started #{}})
|
{:started #{}})
|
||||||
(let [states (or (seq states)
|
(let [states (or (->> states (map var-to-str) seq)
|
||||||
(all-without-subs))]
|
(all-without-subs))]
|
||||||
{:started (bring states up <)}))))
|
{:started (bring states up <)}))))
|
||||||
|
|
||||||
|
|
@ -289,7 +294,7 @@
|
||||||
(if-not (empty? fs) ;; (mount/stop) vs. (mount/stop #{}) vs. (mount/stop #{1 2 3})
|
(if-not (empty? fs) ;; (mount/stop) vs. (mount/stop #{}) vs. (mount/stop #{1 2 3})
|
||||||
(apply stop fs)
|
(apply stop fs)
|
||||||
{:stopped #{}})
|
{:stopped #{}})
|
||||||
(let [states (or (seq states)
|
(let [states (or (->> states (map var-to-str) seq)
|
||||||
(find-all-states))
|
(find-all-states))
|
||||||
_ (dorun (map unsub states)) ;; unmark substitutions marked by "start-with" / "swap-states"
|
_ (dorun (map unsub states)) ;; unmark substitutions marked by "start-with" / "swap-states"
|
||||||
stopped (bring states down >)]
|
stopped (bring states down >)]
|
||||||
|
|
@ -303,22 +308,22 @@
|
||||||
set))
|
set))
|
||||||
|
|
||||||
(defn only
|
(defn only
|
||||||
([states]
|
([these]
|
||||||
(only (find-all-states) states))
|
(only (find-all-states) these))
|
||||||
([states these]
|
([states these]
|
||||||
(intersection (mapset var-to-str these)
|
(intersection (mapset var-to-str these)
|
||||||
(mapset var-to-str states))))
|
(mapset var-to-str states))))
|
||||||
|
|
||||||
(defn with-args
|
(defn with-args
|
||||||
([args]
|
([args]
|
||||||
(with-args (find-all-states) args))
|
(with-args (find-all-states) args))
|
||||||
([states args]
|
([states args]
|
||||||
(reset! -args args) ;; TODO localize
|
(reset! -args args) ;; TODO localize
|
||||||
states))
|
states))
|
||||||
|
|
||||||
(defn except
|
(defn except
|
||||||
([states]
|
([these]
|
||||||
(except (find-all-states) states))
|
(except (find-all-states) these))
|
||||||
([states these]
|
([states these]
|
||||||
(remove (mapset var-to-str these)
|
(remove (mapset var-to-str these)
|
||||||
(mapset var-to-str states))))
|
(mapset var-to-str states))))
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
(:import [goog.debug Console])]))
|
(:import [goog.debug Console])]))
|
||||||
|
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(defonce *logger*
|
(defonce ^:dynamic *logger*
|
||||||
(do
|
(do
|
||||||
(.setCapturing (Console.) true)
|
(.setCapturing (Console.) true)
|
||||||
(glog/getLogger "mount"))))
|
(glog/getLogger "mount" nil))))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(defn log [msg & _]
|
(defn log [msg & _]
|
||||||
|
|
@ -15,6 +15,6 @@
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(defn log [msg & level]
|
(defn log [msg & level]
|
||||||
(case (first level)
|
(case (first level)
|
||||||
:error (glog/error *logger* msg)
|
:error (glog/error *logger* msg nil)
|
||||||
(glog/info *logger* msg))))
|
(glog/info *logger* msg nil))))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,28 @@
|
||||||
(ns mount.tools.macro
|
(ns mount.tools.macro
|
||||||
#?(:cljs (:require-macros [mount.tools.macro])))
|
(:refer-clojure :exclude [case])
|
||||||
|
#?(:cljs (:require-macros [mount.tools.macrovich :refer [deftime]])
|
||||||
|
:clj (:require [mount.tools.macrovich :refer [deftime]])))
|
||||||
|
|
||||||
#?(:clj
|
(deftime
|
||||||
(defmacro if-clj [then else]
|
|
||||||
(if (-> &env :ns not)
|
|
||||||
then
|
|
||||||
else)))
|
|
||||||
|
|
||||||
#?(:clj
|
(defmacro on-error [msg f & {:keys [fail?]
|
||||||
(defmacro on-error [msg f & {:keys [fail?]
|
:or {fail? true}}]
|
||||||
:or {fail? true}}]
|
`(mount.tools.macrovich/case
|
||||||
`(if-clj
|
:clj (try ~f
|
||||||
(try ~f
|
(catch Throwable t#
|
||||||
(catch Throwable t#
|
(if ~fail?
|
||||||
(if ~fail?
|
(throw (RuntimeException. ~msg t#))
|
||||||
(throw (RuntimeException. ~msg t#))
|
{:f-failed (ex-info ~msg {} t#)})))
|
||||||
{:f-failed (ex-info ~msg {} t#)})))
|
:cljs (try ~f
|
||||||
(try ~f
|
(catch :default t#
|
||||||
(catch :default t#
|
(if ~fail?
|
||||||
(if ~fail?
|
(throw (js/Error (~'str ~msg " " t#)))
|
||||||
(throw (~'str ~msg " " t#))
|
{:f-failed (ex-info ~msg {} t#)})))))
|
||||||
{:f-failed (ex-info ~msg {} t#)}))))))
|
|
||||||
|
|
||||||
#?(:clj
|
(defmacro throw-runtime [msg]
|
||||||
(defmacro throw-runtime [msg]
|
`(throw (mount.tools.macrovich/case :clj (RuntimeException. ~msg) :cljs (~'str ~msg))))
|
||||||
`(throw (if-clj (RuntimeException. ~msg)
|
|
||||||
(~'str ~msg)))))
|
)
|
||||||
|
|
||||||
;; this is a one to one copy from https://github.com/clojure/tools.macro
|
;; this is a one to one copy from https://github.com/clojure/tools.macro
|
||||||
;; to avoid a lib dependency for a single function
|
;; to avoid a lib dependency for a single function
|
||||||
|
|
|
||||||
21
src/mount/tools/macrovich.cljc
Normal file
21
src/mount/tools/macrovich.cljc
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
(ns ^{:doc "From https://github.com/cgrand/macrovich. Licensed under EPL v1.
|
||||||
|
Copyright Cristophe Grand." }
|
||||||
|
mount.tools.macrovich
|
||||||
|
(:refer-clojure :exclude [case]))
|
||||||
|
|
||||||
|
(defmacro deftime
|
||||||
|
"This block will only be evaluated at the correct time for macro definition, at other times its content
|
||||||
|
are removed.
|
||||||
|
For Clojure it always behaves like a `do` block.
|
||||||
|
For Clojurescript/JVM the block is only visible to Clojure.
|
||||||
|
For self-hosted Clojurescript the block is only visible when defining macros in the pseudo-namespace."
|
||||||
|
[& body]
|
||||||
|
(when #?(:clj (not (:ns &env)) :cljs (re-matches #".*\$macros" (name (ns-name *ns*))))
|
||||||
|
`(do ~@body)))
|
||||||
|
|
||||||
|
(defmacro case [& {:keys [cljs clj]}]
|
||||||
|
(if (contains? &env '&env)
|
||||||
|
`(if (:ns ~'&env) ~cljs ~clj)
|
||||||
|
(if #?(:clj (:ns &env) :cljs true)
|
||||||
|
cljs
|
||||||
|
clj)))
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
(defn load-config [path]
|
(defn load-config [path]
|
||||||
(info "loading config from" path)
|
(info "loading config from" path)
|
||||||
(-> path
|
(-> path
|
||||||
slurp
|
slurp
|
||||||
edn/read-string))
|
edn/read-string))
|
||||||
|
|
||||||
(defstate config
|
(defstate config
|
||||||
:start (load-config "dev/resources/config.edn"))
|
:start (load-config "dev/resources/config.edn"))
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
:db/valueType :db.type/bigdec
|
:db/valueType :db.type/bigdec
|
||||||
:db/cardinality :db.cardinality/one
|
:db/cardinality :db.cardinality/one
|
||||||
:db.install/_attribute :db.part/db}
|
:db.install/_attribute :db.part/db}
|
||||||
|
|
||||||
{:db/id #db/id [:db.part/db]
|
{:db/id #db/id [:db.part/db]
|
||||||
:db/ident :order/qty
|
:db/ident :order/qty
|
||||||
:db/valueType :db.type/long
|
:db/valueType :db.type/long
|
||||||
|
|
@ -51,11 +51,11 @@
|
||||||
:order/bid bid
|
:order/bid bid
|
||||||
:order/offer offer
|
:order/offer offer
|
||||||
:order/qty qty}]))
|
:order/qty qty}]))
|
||||||
|
|
||||||
|
|
||||||
(defn find-orders [ticker] ;; can take connection as param
|
(defn find-orders [ticker] ;; can take connection as param
|
||||||
(let [orders (d/q '[:find ?e :in $ ?ticker
|
(let [orders (d/q '[:find ?e :in $ ?ticker
|
||||||
:where [?e :order/symbol ?ticker]]
|
:where [?e :order/symbol ?ticker]]
|
||||||
(d/db @nyse/conn) ticker)]
|
(d/db @nyse/conn) ticker)]
|
||||||
(touch @nyse/conn orders)))
|
(touch @nyse/conn orders)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@
|
||||||
(defn entity [conn id]
|
(defn entity [conn id]
|
||||||
(d/entity (d/db conn) id))
|
(d/entity (d/db conn) id))
|
||||||
|
|
||||||
(defn touch [conn results]
|
(defn touch
|
||||||
"takes 'entity ids' results from a query
|
"takes 'entity ids' results from a query
|
||||||
e.g. '#{[272678883689461] [272678883689462] [272678883689459] [272678883689457]}'"
|
e.g. '#{[272678883689461] [272678883689462] [272678883689459] [272678883689457]}'"
|
||||||
|
[conn results]
|
||||||
(let [e (partial entity conn)]
|
(let [e (partial entity conn)]
|
||||||
(map #(-> % first e d/touch) results)))
|
(map #(-> % first e d/touch) results)))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(ns tapp.utils.logging ;; << change to your namespace/path
|
(ns tapp.utils.logging ;; << change to your namespace/path
|
||||||
(:require [mount.core]
|
(:require [mount.core]
|
||||||
[robert.hooke :refer [add-hook clear-hooks]]
|
[robert.hooke :refer [add-hook clear-hooks]]
|
||||||
[clojure.string :refer [split]]
|
[clojure.string :refer [split]]
|
||||||
|
|
@ -21,9 +21,9 @@
|
||||||
:down "<< stopping"
|
:down "<< stopping"
|
||||||
false))
|
false))
|
||||||
|
|
||||||
(defn log-status [f & args]
|
(defn log-status [f & args]
|
||||||
(let [[state-name state] args
|
(let [[state-name state] args
|
||||||
action (f-to-action f state)]
|
action (f-to-action f state)]
|
||||||
(when-let [taking-over-the-world (whatcha-doing? action)]
|
(when-let [taking-over-the-world (whatcha-doing? action)]
|
||||||
(info (str taking-over-the-world ".. " state-name)))
|
(info (str taking-over-the-world ".. " state-name)))
|
||||||
(apply f args)))
|
(apply f args)))
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@
|
||||||
|
|
||||||
(defn find-source-logs [db source]
|
(defn find-source-logs [db source]
|
||||||
(d/q '{:find [?t ?msg]
|
(d/q '{:find [?t ?msg]
|
||||||
:in [$ ?s]
|
:in [$ ?s]
|
||||||
:where [[?e :source ?s]
|
:where [[?e :source ?s]
|
||||||
[?e :timestamp ?t]
|
[?e :timestamp ?t]
|
||||||
[?e :msg ?msg]]}
|
[?e :msg ?msg]]}
|
||||||
@@db source))
|
@@db source))
|
||||||
|
|
||||||
(defn find-all-logs [db]
|
(defn find-all-logs [db]
|
||||||
(->> (map :e (d/datoms @@db :aevt :timestamp))
|
(->> (map :e (d/datoms @@db :aevt :timestamp))
|
||||||
dedupe
|
dedupe
|
||||||
(d/pull-many @@db '[:timestamp :source :msg])))
|
(d/pull-many @@db '[:timestamp :source :msg])))
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
" → [" (name source) "]: " msg))
|
" → [" (name source) "]: " msg))
|
||||||
|
|
||||||
(defn show-log []
|
(defn show-log []
|
||||||
(.write js/document
|
(.write js/document
|
||||||
(html [:ul (doall (for [e (find-all-logs log)]
|
(html [:ul (doall (for [e (find-all-logs log)]
|
||||||
[:li (format-log-event e)]))])))
|
[:li (format-log-event e)]))])))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
[mount.test.helper :refer [dval helper forty-two]]))
|
[mount.test.helper :refer [dval helper forty-two]]))
|
||||||
|
|
||||||
(def status (atom :a-not-started))
|
(def status (atom :a-not-started))
|
||||||
(defstate a :start (reset! status :a-started)
|
(defstate a :start (reset! status :a-started)
|
||||||
:stop (reset! status :a-stopped))
|
:stop (reset! status :a-stopped))
|
||||||
|
|
||||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||||
|
|
@ -30,11 +30,11 @@
|
||||||
(testing "should cleanup/stop a state after it was deleted from ns"
|
(testing "should cleanup/stop a state after it was deleted from ns"
|
||||||
(is (empty? (:started (mount/start)))) ;; on any mount op (not necessarily on "stop")
|
(is (empty? (:started (mount/start)))) ;; on any mount op (not necessarily on "stop")
|
||||||
(is (= :a-stopped @status))
|
(is (= :a-stopped @status))
|
||||||
(is (not (some #{"#'mount.test.cleanup-deleted-states/a"}
|
(is (not (some #{"#'mount.test.cleanup-deleted-states/a"}
|
||||||
(keys @@#'mount.core/meta-state)))))
|
(keys @@#'mount.core/meta-state)))))
|
||||||
|
|
||||||
(testing "should not stop it again on stop (should not be there by this point)")
|
(testing "should not stop it again on stop (should not be there by this point)")
|
||||||
(is (not (some #{"#'mount.test.cleanup-deleted-states/a"}
|
(is (not (some #{"#'mount.test.cleanup-deleted-states/a"}
|
||||||
(-> (mount/stop) :stopped set))))))
|
(-> (mount/stop) :stopped set))))))
|
||||||
|
|
||||||
;; (t/run-tests)
|
;; (t/run-tests)
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
(.require js/goog "mount.test.helper") ;; should have run :stop of `helper`
|
(.require js/goog "mount.test.helper") ;; should have run :stop of `helper`
|
||||||
;; (is (= :cleaned @forty-two)) ;; TODO: figure out how to reload a namespace properly
|
;; (is (= :cleaned @forty-two)) ;; TODO: figure out how to reload a namespace properly
|
||||||
;; (is (instance? mount.core.NotStartedState (dval helper)))
|
;; (is (instance? mount.core.NotStartedState (dval helper)))
|
||||||
(mount/start #'mount.test.helper/helper)
|
(mount/start #'mount.test.helper/helper)
|
||||||
(is (= :started (dval helper)))
|
(is (= :started (dval helper)))
|
||||||
(mount/stop)
|
(mount/stop)
|
||||||
(is (instance? mount.core.NotStartedState (dval helper))))))
|
(is (instance? mount.core.NotStartedState (dval helper))))))
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(deftest only-states
|
(deftest only-states
|
||||||
|
|
||||||
(testing "only should only return given states.
|
(testing "only should only return given states.
|
||||||
if source set of states is not provided, it should use all the states to select from"
|
if source set of states is not provided, it should use all the states to select from"
|
||||||
(is (= #{"#'mount.test.composable-fns/test-conn" "#'tapp.example/nrepl" "#'tapp.nyse/conn"}
|
(is (= #{"#'mount.test.composable-fns/test-conn" "#'tapp.example/nrepl" "#'tapp.nyse/conn"}
|
||||||
(only #{"#'is.not/here" #'mount.test.composable-fns/test-conn #'tapp.example/nrepl #'tapp.nyse/conn}))))
|
(only #{"#'is.not/here" #'mount.test.composable-fns/test-conn #'tapp.example/nrepl #'tapp.nyse/conn}))))
|
||||||
|
|
||||||
(testing "only should only return given states"
|
(testing "only should only return given states"
|
||||||
(is (= #{"#'mount.test.composable-fns/test-conn" "#'tapp.example/nrepl"}
|
(is (= #{"#'mount.test.composable-fns/test-conn" "#'tapp.example/nrepl"}
|
||||||
(only [#'mount.test.composable-fns/test-conn #'tapp.example/nrepl #'tapp.nyse/conn]
|
(only [#'mount.test.composable-fns/test-conn #'tapp.example/nrepl #'tapp.nyse/conn]
|
||||||
#{"#'is.not/here" #'mount.test.composable-fns/test-conn #'tapp.example/nrepl}))))))
|
#{"#'is.not/here" #'mount.test.composable-fns/test-conn #'tapp.example/nrepl}))))))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
|
|
@ -109,6 +109,16 @@
|
||||||
(is (= 42 (dval conn)))
|
(is (= 42 (dval conn)))
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
|
(testing "swap-states should swap states on start and rollback on stop"
|
||||||
|
(let [states (swap-states {#'tapp.nyse/conn swap-conn})]
|
||||||
|
(is (= states (#'mount.core/find-all-states)))
|
||||||
|
(mount/start #'tapp.nyse/conn)
|
||||||
|
(is (= 42 (dval conn)))
|
||||||
|
(mount/stop #'tapp.nyse/conn)
|
||||||
|
(mount/start #'tapp.nyse/conn)
|
||||||
|
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
||||||
|
(mount/stop)))
|
||||||
|
|
||||||
(testing "swap-states should swap states with states and return only states that it is given"
|
(testing "swap-states should swap states with states and return only states that it is given"
|
||||||
(let [t-states #{"#'is.not/here" #'mount.test.composable-fns/test-conn #'tapp.nyse/conn}
|
(let [t-states #{"#'is.not/here" #'mount.test.composable-fns/test-conn #'tapp.nyse/conn}
|
||||||
states (swap-states t-states {#'tapp.nyse/conn swap-conn
|
states (swap-states t-states {#'tapp.nyse/conn swap-conn
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
#'mount.test.fun-with-values/private-f
|
#'mount.test.fun-with-values/private-f
|
||||||
#'mount.test.fun-with-values/f-value))
|
#'mount.test.fun-with-values/f-value))
|
||||||
|
|
||||||
(use-fixtures :once
|
(use-fixtures :once
|
||||||
#?(:cljs {:before start-states
|
#?(:cljs {:before start-states
|
||||||
:after mount/stop}
|
:after mount/stop}
|
||||||
:clj #((start-states) (%) (mount/stop))))
|
:clj #((start-states) (%) (mount/stop))))
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||||
|
|
||||||
(defn dval
|
(defn dval
|
||||||
"returns a value of DerefableState without deref'ing it"
|
"returns a value of DerefableState without deref'ing it"
|
||||||
[d]
|
[d]
|
||||||
(-> (@@(var mount.core/meta-state)
|
(-> (@@(var mount.core/meta-state)
|
||||||
#?(:clj (.name d)
|
#?(:clj (.name d)
|
||||||
:cljs (.-name d)))
|
:cljs (.-name d)))
|
||||||
:inst
|
:inst
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
[tapp.audit-log :refer [log]]]
|
[tapp.audit-log :refer [log]]]
|
||||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||||
[mount.core :as mount :refer [defstate]]
|
[mount.core :as mount :refer [defstate]]
|
||||||
[tapp.example]])
|
[tapp.example]])
|
||||||
[mount.test.helper :refer [dval helper forty-two counter inc-counter]]
|
[mount.test.helper :refer [dval helper forty-two counter inc-counter]]
|
||||||
[mount.test.on-reload-helper :refer [a b c]]))
|
[mount.test.on-reload-helper :refer [a b c]]))
|
||||||
|
|
||||||
|
|
@ -42,14 +42,14 @@
|
||||||
|
|
||||||
;; "b" is marked as :stop on reload
|
;; "b" is marked as :stop on reload
|
||||||
(is (instance? mount.core.NotStartedState (dval b)))
|
(is (instance? mount.core.NotStartedState (dval b)))
|
||||||
(is (= (-> pre-reload :b :started)
|
(is (= (-> pre-reload :b :started)
|
||||||
(-> @counter :b :started)))
|
(-> @counter :b :started)))
|
||||||
(is (= (inc (-> pre-reload :b :stopped))
|
(is (= (inc (-> pre-reload :b :stopped))
|
||||||
(-> @counter :b :stopped)))
|
(-> @counter :b :stopped)))
|
||||||
|
|
||||||
;; "c" is not marked on reload, using "restart" as default
|
;; "c" is not marked on reload, using "restart" as default
|
||||||
(is (= :started (dval c)))
|
(is (= :started (dval c)))
|
||||||
(is (= (inc (-> pre-reload :c :started))
|
(is (= (inc (-> pre-reload :c :started))
|
||||||
(-> @counter :c :started)))
|
(-> @counter :c :started)))
|
||||||
(is (= (inc (-> pre-reload :c :stopped))
|
(is (= (inc (-> pre-reload :c :stopped))
|
||||||
(-> @counter :c :stopped))))))
|
(-> @counter :c :stopped))))))
|
||||||
|
|
|
||||||
|
|
@ -20,18 +20,18 @@
|
||||||
(f)
|
(f)
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
(use-fixtures :once
|
(use-fixtures :once
|
||||||
#?(:cljs {:before #(mount/start #'tapp.conf/config #'tapp.audit-log/log)
|
#?(:cljs {:before #(mount/start #'tapp.conf/config #'tapp.audit-log/log)
|
||||||
:after mount/stop}
|
:after mount/stop}
|
||||||
:clj with-parts))
|
:clj with-parts))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(deftest start-only-parts
|
(deftest start-only-parts
|
||||||
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
||||||
(is (instance? mount.core.NotStartedState (dval should-not-start)))))
|
(is (instance? mount.core.NotStartedState (dval should-not-start)))))
|
||||||
|
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(deftest start-only-parts
|
(deftest start-only-parts
|
||||||
(is (instance? datascript.db/DB @(dval log)))
|
(is (instance? datascript.db/DB @(dval log)))
|
||||||
(is (map? (dval config)))
|
(is (map? (dval config)))
|
||||||
(is (instance? mount.core.NotStartedState (dval should-not-start)))
|
(is (instance? mount.core.NotStartedState (dval should-not-start)))
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@
|
||||||
|
|
||||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||||
|
|
||||||
(use-fixtures :once
|
(use-fixtures :once
|
||||||
#?(:cljs {:before #(mount/start #'mount.test.fun-with-values/private-f)
|
#?(:cljs {:before #(mount/start #'mount.test.fun-with-values/private-f)
|
||||||
:after mount/stop}
|
:after mount/stop}
|
||||||
:clj #((mount/start #'mount.test.fun-with-values/private-f)
|
:clj #((mount/start #'mount.test.fun-with-values/private-f)
|
||||||
(%)
|
(%)
|
||||||
(mount/stop))))
|
(mount/stop))))
|
||||||
|
|
||||||
(deftest fun-with-values
|
(deftest fun-with-values
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
||||||
(is (instance? mount.core.NotStartedState (dval test-nrepl)))
|
(is (instance? mount.core.NotStartedState (dval test-nrepl)))
|
||||||
(mount/stop)))))
|
(mount/stop)))))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(deftest start-with
|
(deftest start-with
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
(is (= :nrepl-sub (dval nrepl)))
|
(is (= :nrepl-sub (dval nrepl)))
|
||||||
(is (= "conn-sub" (dval conn)))
|
(is (= "conn-sub" (dval conn)))
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
(testing "should start normally after start-with"
|
(testing "should start normally after start-with"
|
||||||
(let [_ (mount/start)]
|
(let [_ (mount/start)]
|
||||||
(is (map? (dval config)))
|
(is (map? (dval config)))
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
||||||
(is (instance? mount.core.NotStartedState (dval test-nrepl)))
|
(is (instance? mount.core.NotStartedState (dval test-nrepl)))
|
||||||
(mount/stop)))))
|
(mount/stop)))))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(deftest start-with-states
|
(deftest start-with-states
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
(is (instance? clojure.tools.nrepl.server.Server (dval nrepl)))
|
(is (instance? clojure.tools.nrepl.server.Server (dval nrepl)))
|
||||||
(is (= (dval conn) 42))
|
(is (= (dval conn) 42))
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
#_(testing "should not start the substitute itself" ;; was true when subbing with exsiting states
|
#_(testing "should not start the substitute itself" ;; was true when subbing with exsiting states
|
||||||
(let [_ (mount/start-with-states {#'tapp.nyse/conn swap-conn})]
|
(let [_ (mount/start-with-states {#'tapp.nyse/conn swap-conn})]
|
||||||
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
(f)
|
(f)
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
(use-fixtures :once
|
(use-fixtures :once
|
||||||
#?(:cljs {:before #(mount/start-without #'mount.test.helper/helper #'tapp.websockets/system-a)
|
#?(:cljs {:before #(mount/start-without #'mount.test.helper/helper #'tapp.websockets/system-a)
|
||||||
:after mount/stop}
|
:after mount/stop}
|
||||||
:clj without))
|
:clj without))
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
(is (instance? mount.core.NotStartedState (dval config)))
|
(is (instance? mount.core.NotStartedState (dval config)))
|
||||||
(is (instance? mount.core.NotStartedState (dval system-a)))
|
(is (instance? mount.core.NotStartedState (dval system-a)))
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
(testing "should start normally after stop-except"
|
(testing "should start normally after stop-except"
|
||||||
(let [_ (mount/start)]
|
(let [_ (mount/start)]
|
||||||
(is (map? (dval config)))
|
(is (map? (dval config)))
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
||||||
(is (instance? mount.core.NotStartedState (dval nrepl)))
|
(is (instance? mount.core.NotStartedState (dval nrepl)))
|
||||||
(mount/stop)))
|
(mount/stop)))
|
||||||
|
|
||||||
(testing "should start normally after stop-except"
|
(testing "should start normally after stop-except"
|
||||||
(let [_ (mount/start)]
|
(let [_ (mount/start)]
|
||||||
(is (map? (dval config)))
|
(is (map? (dval config)))
|
||||||
|
|
|
||||||
29
test/core/mount/test_self_host.cljs
Normal file
29
test/core/mount/test_self_host.cljs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
(ns mount.test-self-host
|
||||||
|
(:require
|
||||||
|
[cljs.test :as t]
|
||||||
|
|
||||||
|
mount.test.fun-with-values
|
||||||
|
mount.test.private-fun
|
||||||
|
mount.test.printing
|
||||||
|
mount.test.parts
|
||||||
|
mount.test.cleanup-dirty-states
|
||||||
|
mount.test.stop-except
|
||||||
|
mount.test.start-without
|
||||||
|
mount.test.start-with
|
||||||
|
mount.test.start-with-states
|
||||||
|
))
|
||||||
|
|
||||||
|
(t/run-tests
|
||||||
|
'mount.test.fun-with-values
|
||||||
|
'mount.test.private-fun
|
||||||
|
'mount.test.printing
|
||||||
|
'mount.test.parts
|
||||||
|
'mount.test.cleanup-dirty-states
|
||||||
|
;; 'mount.test.stop-except ;; TODO: can't run with deps.edn (due to "WebSocket is not defined")
|
||||||
|
;; 'mount.test.start-with ;; boot, lein have no problems
|
||||||
|
;; 'mount.test.start-with-states ;; most likely somm misconfigured in node..
|
||||||
|
'mount.test.start-without
|
||||||
|
)
|
||||||
|
|
||||||
|
(defn run-tests []
|
||||||
|
(t/run-all-tests #"mount.test.*"))
|
||||||
Loading…
Reference in a new issue