Need help with shoreleave?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

ohpauleez
127 Stars 5 Forks Other 49 Commits 0 Opened issues

Description

A smarter client-side for ClojureScript

Services available

!
?

Need anything else?

Contributors list

No Data

shoreleave

A smarter client-side in ClojureScript

Shoreleave is a collection of integrated libraries that focuses on:

  • Security
  • Idiomatic interfaces
  • Common client-side strategies
  • HTML5 capabilities
  • ClojureScript's advantages

Installing and using

You can pull all the pieces of Shoreleave into your project by adding the following to your

project.clj
(defproject ...

:dependencies [[org.clojure/clojure "1.4.0"] [shoreleave "0.3.0"] [shoreleave/shoreleave-remote-ring "0.3.0"] ... ] ... )

Individual utilies can be pulled in with

[shoreleave/UTILITY "0.3.0"]
. See the specific repo/artifact names below.

Overview

Shoreleave has support for the following:

Common client-side interactions

  • An idiomatic interface to cookies
  • An idiomatic interface to browser history (with extended support for HTML5 History API)
  • HTML Blob construction and on-demand asset building
  • An idiomatic interface to browser storage (Local Storage, Session Storage. App Cache coming soon)
  • Common auxiliary functions out-of-the-box to handle query strings, browser-repl, hash strings, and CLJS/JS interop
  • and more...

A remotes package

Shoreleave's remotes package includes XHR, Pooled-XHR, JSONP, and HTTP-RPC capabilities.

CSRF protection is built in if your Clojure server is using the ring-anti-forgery middleware. See shoreleave-baseline for anti-forgery details.

The HTTP-RPC allows for exposing a server-side namespace as a client-side API, via a single server-side call,

remote-ns
.

A typical Compojure setup might look like:

(ns baseline.handler
  (:require [compojure.handler :as handler]
            [baseline.routes :as routes]
            [baseline.config :refer [config]]
            [ring.middleware.gzip]
            [ring.middleware.file-info]
            [ring.middleware.anti-forgery]
            [ring.middleware.session.cookie :refer [cookie-store]]
            [shoreleave.middleware.rpc]
            [hiccup.middleware]))

(def app routes/all-routes)

(defn get-handler [app] (-> app (shoreleave.middleware.rpc/wrap-rpc) (ring.middleware.anti-forgery/wrap-anti-forgery) (ring.middleware.gzip/wrap-gzip) (handler/site {:session {:cookie-name "baseline" :store (cookie-store {:key (config :session-secret)}) ;:store (cookie-store) :cookie-attrs {:max-age (config :session-max-age-seconds) :http-only true}}}) (ring.middleware.file-info/wrap-file-info) (hiccup.middleware/wrap-base-url)))

(def war-handler (get-handler app))

With a routes file that might look like this:

(ns baseline.routes
  (:require [compojure.core :as c-core :refer [defroutes
                                               GET POST PUT DELETE
                                               HEAD OPTIONS PATCH
                                               ANY]]
            [compojure.route :as c-route]
            [shoreleave.middleware.rpc :refer [remote-ns]]
            ;; Controllers
            [baseline.controllers.site :as cont-site]
            ;; Public APIs
            [baseline.controllers.api]))

;; Remote APIs exposed ;; ------------------- (remote-ns 'baseline.controllers.api :as "api")

;; Controller routes, ROA oriented ;; ------------------------------- (defroutes site (GET "/" {session :session} (cont-site/index session)) (GET "/test" [] (cont-site/test-shoreleave)))

;; Core system routes ;; ------------------ (defroutes app-routes (c-route/resources "/") (c-route/not-found "404 Page not found."))

;; The top-level collection of all routes ;; -------------------------------------- (def all-routes (c-core/routes site app-routes))

You can also define single "global" rpc functions:

(defremote ping []
  (do
    (println "Pinged by client!")
    "PONG - from the server"))

See the full example in the shoreleave-baseline project

A pub/sub abstraction (and implementations)

Why would I ever want to use this?

Shoreleave's pub/sub system enables you to completely decouple parts of your app and declaratively bind them together. New features and functionalities can be built by composing pre-existing services/publishables.

Additionally you can express cross-cutting functionality (like logging or metrics reporting) as a service.

Reactive ClojureScript

This gives you the heart of Reactive JavaScript (RxJS), without the additional verbs (both a benefit and a tradeoff). It's often most beneficial to use DOM listeners as entry-points into the pub/sub system.


Shoreleave's pub/sub system is built upon two protocols: "brokers" and "publishables"

Out of the box, Shoreleave allows you to publish funtions, atoms, web workers, and anything that implements (str ...)/.toString, as topics. The

simple
pub/sub bus has very little overhead, but operates synchronously. You can trade-off some performance for an async bus, the
event
pubsub bus.

(In-progress) The cross document bus has a small amount of overhead, but allows you to publish and subscribe from/to functions that live in other web workers or windows (in-browser concurrency for "free").

In most cases, the simple bus is the best choice.

Common external API support

Shoreleave has JSONP-wrapped support for external APIs including:

  • Google Maps
  • DuckDuckGo Zero-Click
  • (Coming soon) Wikipedia and Alpha

An enhanced ClojureScript experience

  • The ability to create embedded web workers

Where's the code?

There is a starter project that you can use as template, similar to how ClojureScript:One worked. It's also a great source to see how to build out Shoreleave+Compojure projects. * shoreleave-baseline application - marg docs of the kitchensink branch

Shoreleave is a big project and has been split up into smaller pieces within the Shoreleave organization:

Deprecated

What's new in the latest version?

The latest version is

0.3.0
  • Example application and template project, shoreleave-baseline
  • Finalized protocols and support for browser web storage (localStorage, sessionStorage)
  • Ring middleware updated and moved to be the standard Shoreleave server-side component
  • Dropped Noir support
  • Updated remotes support for better error handling
  • Improved pub/sub handling of various flow combinations
  • subscribe->
    added the pub/sub bus procotol - allows threading of flows
  • Replaced deprecated CLJS protocol usage
  • Code migrated from this project to CLJS proper
  • removed jQuery support from remotes
  • Updated all interfaces to their HTML5 finalized specs
  • bug fixes and performance improvements
  • Added more documentation

Plays well with others

Shoreleave makes no assumptions about other libraries you might be using in your app.

I have found it to pair particularly well with Enfocus

Examples and usage

Please the github doc pages (ie: Marginalia docs) above for library specifics.

There is a community-contributed demo app thanks to the hard work of Robert Stuttaford

Google Group and General Help

There is a Shoreleave CLJS Google Group. Please feel free to post all questions and general comments there.

Additionally, you can ping

ohpauleez
in #clojure on Freenode.

License

Copyright (C) 2012-2013 Paul deGrandis

Distributed under the Eclipse Public License, the same as Clojure.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.