Skip to content

Commit

Permalink
Added new CLI features (db init).
Browse files Browse the repository at this point in the history
  • Loading branch information
ryugi committed May 27, 2017
1 parent 6b90433 commit f44cb49
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 56 deletions.
121 changes: 83 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
* [Dependencies](#dependencies-)
* [Documentation](#documentation-)
* [Usage](#usage-)
* [Initialization](#initialization-)
* [Configuration](#configuration-)
* [Build](#build-)
* [Configuration](#configuration-)
* [Starting](#starting-)
* [CLI Server](#cli-server-)
* [Data Initialization](#data-initialization-)
* [Projects and Tasks Population](#projects-and-tasks-population-)
* [Startup](#startup-)
* [History](#history-)
* [License](#license-)

Expand Down Expand Up @@ -75,16 +76,22 @@ application is running:
## Usage [↟](#contents)


### Initialization [↟](#contents)
### Build [↟](#contents)

Clone the repo. Then, inside the repo, initialize a time tracker:
Before you can do much with Tímı, you'll need to build it. As long as you
have all the dependencies install on your system (see above), it's as simple
as this:

```
$ make var/data/timi.db
$ make
```

This will create a sqlite3 db with filename `var/data/timi.db`, which contains
the right schema, but has no data yet.
This will do a lot, but can be summarized with the following:

* Download all the Clojure and JavaScript (Node.js) dependencies
* Build the server code
* Build the client code
* Build the CLI tool


### Configuration [↟](#contents)
Expand All @@ -106,17 +113,76 @@ Then update your new `config/local/config.edn` file, replacing the same value
for `:cookie-encryption-key` with the one `make cookie` generated for you.


### Build [↟](#contents)
### Starting [↟](#contents)

With the application built, you're ready to start it. If you just want to
use the application and not do any development work, simply do:

```
$ make run
```

If you'll be doing server-side development and want access to the REPL:

```
$ make repl
```

Once the REPL finishes loading, start the application with `(run)`. You can
reload new code and restart the application by typing `(reset)`. The server
running in the REPL will be available on
[http://localhost:5098](http://localhost:5098)

If you'll be doing client-side development, then do:

```
$ make dev
```

If you then load up the application in your browser at
[http://localhost:5099](http://localhost:5099),
you'll see a prompt appear back in your terminal: this is ClojureScript, and
you have access to the client-side of the application, as it's running in your
browser.


### CLI Server [↟](#contents)

One of the services that is started when the app comes up is a command-line
server, listening on port 5097. The Tímı cli tool that gets installed to
`./bin/timi` connects to this server to issue your commands and return results.
This feature allows for command-line operations that are much, much faster
than usual JVM commands (since there's no start-up cost for every command).

The Clojure and ClojureScript for the project can be built in one go with the
Now make sure you have easy access to `timi` by adding its location to
your `PATH`:

```
$ export PATH=$PATH:`pwd`/bin
```


### Data Initialization [↟](#contents)

Database setup is done using the `timi` CLI tool:

```
$ timi db init
```

If you are using the values defined for you in the sample config, this will
create a sqlite3 db with filename `var/data/timi.db`, which contains
the right schema, but has no data yet.

If you would like to override your configuration value. you can do the
following:

```
$ make
$ timi db init my/path/timi.db
```

If you just want to do one or the other, you may use `make build-clj` or
`make build-cljs`.
Note, however, that you will need to update your configuration file to point
to the new location of the database.


### Projects and Tasks Population [↟](#contents)
Expand All @@ -141,31 +207,10 @@ $ lein timi-create-task "Project management" :for-project 1 :billing-method :ove
$ lein timi-create-task "Programming" :for-project 1
```


### Startup [↟](#contents)

For deployment and non-interactive development, simply run the server:

```
$ make run
```

If everything went well, there should now be a web server running on
[http://localhost:5099](http://localhost:5099) (or whatever port you updated your
local configuration to have). Navigate to it and have fun!

If you would like to do interactive development with ClojureScript, Om, and/or
CSS, you can run this instead:

```
$ lein timi-figwheel
```

As soon as you see the help text with all the functions you can use, open up
[http://localhost:5099](http://localhost:5099) in your prefered browser. As soon
as you do, you should then see the Clojure prompt appear in your terminal where
you ran the command. You now have access to Om application state in the REPL
and can run the client-side code there.
At this point, you're ready to start tracking time! Visit either
[http://localhost:5098](http://localhost:5098) or
[http://localhost:5099](http://localhost:5099), depending upon how you have
started Tímı.


## History [↟](#contents)
Expand Down
15 changes: 13 additions & 2 deletions dev-resources/make/cljs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ NODE_MODS = ./node_modules
NODE_MODS_PATH = $(JS_DIR)/$(NODE_MODS)
CLJS_INSTALL_DIR = ./resources/public/dist

build-cljs: node
build-cljs-web: node
@# XXX min isn't working right now ...
@#@lein cljsbuild once min
@lein cljsbuild once

build-cljs-dev: node
build-cljs-cli: node
@# XXX min isn't working right now ...
@#@lein cljsbuild once min
@lein cljsbuild once cli
@chmod 755 ./bin/timi

build-cljs: build-cljs-web build-cljs-cli

build-cljs-dev: build-cljs-cli
@lein cljsbuild once

node: $(NODE_MODS_PATH)
Expand All @@ -19,6 +27,9 @@ $(NODE_MODS_PATH):
@cd $(JS_DIR) && \
npm install

dev:
@rlwrap lein timi-figwheel

clean-cljs:
@rm -rf $(CLJS_INSTALL_DIR)

Expand Down
3 changes: 0 additions & 3 deletions dev-resources/make/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ cookie:
run:
@lein timi-run

dev:
@rlwrap lein timi-figwheel

clean: clean-cljs clean-clj

clean-all: clean clean-node
Expand Down
9 changes: 1 addition & 8 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
{:id "cli"
:source-paths ["src/cljs/cli"]
:compiler {
:output-to "bin/timi-cli.js"
:output-to "bin/timi"
:output-dir "target/cljs/cli"
:optimizations :simple
:pretty-print true
Expand Down Expand Up @@ -162,12 +162,6 @@
;; XXX Note: most (if not all) of the aliases are going to change or go away
;; once we switch to the new CLI
:aliases {
"timi-help" [
"with-profile" "+local"
"run" "-m" "timi.cli"]
"timi-init" [
"with-profile" "+local"
"run" "-m" "timi.cli" "sqlite" "create-db" :filename]
"timi-create-project" [
"with-profile" "+local"
"run" "-m" "timi.cli" "projects" "create" :name]
Expand All @@ -186,7 +180,6 @@
["uberjar"]
["cljsbuild" "once"]
["cljsbuild" "once" "cli"]]
"timi-build-cli" ["with-profile" "+build" "cljsbuild" "once" "cli"]
"timi-deploy" ["with-profile" "build" "deploy" "clojars"]
"timi-server-docs" ["with-profile" "+build,+docs,+server-docs" "codox"]
"timi-client-docs" ["with-profile" "+build,+docs,+client-docs" "codox"]
Expand Down
118 changes: 117 additions & 1 deletion src/clj/timi/server/cli/commands/db.clj
Original file line number Diff line number Diff line change
@@ -1 +1,117 @@
(ns timi.server.cli.commands.db)
(ns timi.server.cli.commands.db
(:require
[clojure.pprint :refer [pprint]]
[clojure.string :as string]
[clojure.tools.cli :as cli]
[taoensso.timbre :as log]
[timi.server.cli.parser :as parser]
[timi.server.datasource.sqlite.migrations :as db-migrator]
[timi.server.util :as util]
[trifl.docs :as docs])
(:import
(clojure.lang PersistentHashMap)
(java.lang Object String)))

(def options
;; Note that any options added here need to be named differently than those
;; in timi.server.cli.core/options.
[])

(defn validate-subcommand
[subcommand]
(log/info "Validating subcommand ...")
(log/trace "Command:" subcommand)
(#{:help :init :dump} subcommand))

(defn help
"This function generates the output for the `help` options and/or commands."
[]
(docs/get-docstring 'timi.server.cli.commands.db 'run))

(defn handle-unknown-subcommand
[subcommand]
(let [msg (format "The subcommand '%s' is not supported."
(name subcommand))]
(log/error msg)
(format "\nERROR: %s\n\n%s" msg (help))))

;; XXX this will be generalized later (and moved) when different db backends
;; are supported
(defmulti get-connection-data
(fn [x & ys]
(mapv class (into [x] ys))))

(defmethod get-connection-data [PersistentHashMap]
[config]
(log/debug "Getting connection data from config ...")
(-> config
:persistence
(config)))

(defmethod get-connection-data [String String]
[db-type filename]
(log/debug "Creating connection data from db-type & filename ...")
{:subprotocol db-type
:subname filename})

(defmethod get-connection-data [String]
[filename]
(log/debug "Creating connection data from filename ...")
(get-connection-data "sqlite" filename))

(defn get-migration-path
[db-type]
(log/debug "Getting db migration path ...")
(format "datasources/%s/migrations" db-type))

;; XXX this will be generalized later (and moved) when different db backends
;; are supported
(defn init-db
([connection-data]
(log/info "Creating initial database ...")
(log/debug "connection-data:" connection-data)
(log/debug "connection-data:" (:subprotocol connection-data))
(db-migrator/apply-migrations!
connection-data
(-> connection-data
:subprotocol
(get-migration-path)))
(log/debug "Database created.")
:ok)
([config filename]
(log/debug "Checking for init type ...")
(log/debug "Config type:" (type config))
(log/debug "Filename type:" (type filename))
(log/debug "Filename:" filename)
(if (nil? filename)
(init-db (get-connection-data config))
(init-db (get-connection-data filename)))))

(defn dispatch
[config {:keys [options arguments errors data subcommands]}]
(let [subcommand (or (first subcommands) :help)]
(log/infof "Running '%s' subcommand ..." subcommand)
(log/trace "Using config:" config)
(log/debug "dispatch subcommands:" subcommands)
(log/debug "dispatch arguments:" arguments)
(case (validate-subcommand subcommand)
:help (help)
:dump :not-implemented
:init (init-db config (nth arguments 2 nil))
(handle-unknown-subcommand subcommand))))

(defn run
"
Usage: `timi db [subcommands [options]]`
Subommands:
```
help Display this help text
dump Dump the schema and inserts to stdout (not implemented)
init CONNECTION-STRING Initialize new app storage with the given
connection string (for sqlite this is just
a filename)
```
"
[config parsed]
(dispatch config parsed))
7 changes: 6 additions & 1 deletion src/clj/timi/server/cli/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[clojure.tools.cli :as cli]
[taoensso.timbre :as log]
[timi.server.cli.commands.config :as config-cmd]
[timi.server.cli.commands.db :as db-cmd]
[timi.server.cli.parser :as parser]
[timi.server.util :as util]
[trifl.docs :as docs]))
Expand All @@ -23,11 +24,14 @@
:help true
:show true}
:db {
:help true
:dump true
:init true}
:project {
:help true
:create true}
:task {
:help true
:create true}})

(defn help
Expand All @@ -38,6 +42,7 @@
(defn dispatch
[config {:keys [options arguments errors data command] :as parsed}]
(log/trace "dispatch keys:" parsed)
(log/trace "options:" options)
(or
(cond
(:help options)
Expand All @@ -57,7 +62,7 @@
(case command
:help (help)
:config (config-cmd/run config parsed)
:db "not implemented"
:db (db-cmd/run config parsed)
:project "not implemented"
:task "not implemented")))

Expand Down
Loading

0 comments on commit f44cb49

Please sign in to comment.