Parcourir la source

initial import

Harlan Iverson il y a 9 ans
commit
ed949232f3
36 fichiers modifiés avec 1510 ajouts et 0 suppressions
  1. 7 0
      MIT-LICENSE.txt
  2. 159 0
      README.md
  3. 1 0
      clojure-objc-sample
  4. 5 0
      core/project.clj
  5. 37 0
      core/src/com/github/harlanji/clojure-stack/core.clj
  6. 19 0
      core/src/com/github/harlanji/clojure-stack/lifecycle.clj
  7. 9 0
      ios-client/project.clj
  8. 522 0
      ios-client/sample/sample.xcodeproj/project.pbxproj
  9. 7 0
      ios-client/sample/sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  10. 41 0
      ios-client/sample/sample.xcodeproj/project.xcworkspace/xcshareddata/sample.xccheckout
  11. BIN
      ios-client/sample/sample.xcodeproj/project.xcworkspace/xcuserdata/harlan.xcuserdatad/UserInterfaceState.xcuserstate
  12. 20 0
      ios-client/sample/sample.xcodeproj/project.xcworkspace/xcuserdata/harlan.xcuserdatad/WorkspaceSettings.xcsettings
  13. 112 0
      ios-client/sample/sample.xcodeproj/xcuserdata/harlan.xcuserdatad/xcschemes/sample.xcscheme
  14. 27 0
      ios-client/sample/sample.xcodeproj/xcuserdata/harlan.xcuserdatad/xcschemes/xcschememanagement.plist
  15. 15 0
      ios-client/sample/sample/AppDelegate.h
  16. 33 0
      ios-client/sample/sample/AppDelegate.m
  17. 1 0
      ios-client/sample/sample/Config.xcconfig
  18. 23 0
      ios-client/sample/sample/Images.xcassets/AppIcon.appiconset/Contents.json
  19. 23 0
      ios-client/sample/sample/Images.xcassets/LaunchImage.launchimage/Contents.json
  20. 2 0
      ios-client/sample/sample/en.lproj/InfoPlist.strings
  21. 18 0
      ios-client/sample/sample/main.m
  22. 38 0
      ios-client/sample/sample/sample-Info.plist
  23. 16 0
      ios-client/sample/sample/sample-Prefix.pch
  24. 2 0
      ios-client/sample/sampleTests/en.lproj/InfoPlist.strings
  25. 22 0
      ios-client/sample/sampleTests/sampleTests-Info.plist
  26. 34 0
      ios-client/sample/sampleTests/sampleTests.m
  27. 68 0
      ios-client/src/sample/core.clj
  28. 17 0
      project.clj
  29. 25 0
      project.org
  30. 14 0
      pubsub-service/project.clj
  31. 48 0
      pubsub-service/src/pubsub/demo.clj
  32. 76 0
      pubsub-service/src/pubsub/main.clj
  33. 25 0
      pubsub-service/src/pubsub/sequencer.clj
  34. 1 0
      resources/public/index.html
  35. 39 0
      web-client/project.clj
  36. 4 0
      web-client/resources/src/com/github/harlanji/pubsub_demo_web.clj

+ 7 - 0
MIT-LICENSE.txt

@@ -0,0 +1,7 @@
+Copyright (c) 2016 Harlan Iverson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 159 - 0
README.md

@@ -0,0 +1,159 @@
+# Clojure Stack
+
+An industry grade project using clojure everywhere. 
+
+To be presented at ForwardJS 4.
+
+## Purpose
+
+A baseline Clojure stack that runs on any and all platforms, that is nice to develop and horizontally scalable.
+
+## What's here?
+
+* Leiningen based multi-module project setup with modules for each platform
+  * API via bidi with REPL control
+  * Web via clojurescript / re-frame
+  * iOS via clojure-objc / lein-objcbuild
+  * Androd via clojure-android / lein-droid
+  * Core via component
+* Integration with Vagrant and Marathon
+* Scalable production deploment configuration
+* Development environment mirroring production environment
+* Jenkins configuration
+* No bullshit (pull request if you disagree)
+
+
+## Philosophy
+
+### Claims
+
+
+* Continuous Delivery shortens the feedback loop
+* Using a single notation everywhere makes it easy to switch contexts
+* Developing in a production-like environment minimizes surprises
+* Automation is the best process documentation
+* Strong typing need not be obtrusive and static, and is necessary for any evolving system
+* EDN minimally represents all fundamental data structures; the end game of text formats
+* Clojure is easy to read and understand, and is not quite LISP (it's EDN)
+* Investment in Open Source Software leads to better software product outcomes
+
+
+## Choices
+
+### Clojure
+
+The fundamental data structures representing code and data; nothing more, nothing less.
+
+* Same language on and between all platforms
+* core.async channels and CSP concurrency everywhere
+* EDN everywhere, successor to JSON
+
+#### re-frame
+
+Based on reagent, which using a special atom as the client side sate. Stacks a nice pattern for composable reactive
+processing of UI actions. Plays well with CQRS and Doman Driven Design.
+
+
+#### component
+
+A separation of concerns model for use on all platforms.
+
+We use a custom lifecycle dispatcher that uses multimethods, as suggested by the author's documentation.
+
+```clojure
+(ns my.component
+  (:require [clojure.tools.logging :refer [debugf infof]
+            [component :refer [react-to] :as c]))
+  
+(defmulti react)
+
+; namespaced keywords for dispatch
+; (when (= *ns* 'my.component) (= ::my-message :my.component/my-message))
+
+(defmethod react :component/start [c]
+  (debugf "Starting my.component"))
+  
+(defmethod react :component/stop [c]
+  (debugf "Stopping my.component"))
+
+(defmethod react ::my-message [c msg]
+  (infof "Got a message, what are we going to do about it? %s" msg))
+
+; alternative syntax (experimental)
+(react-to ::my-message [event]
+  (infof "Got a message, what are we going to do about it? %s" msg))
+```
+
+
+```
+
+(defmacro defupon
+  ""
+  [command & body]
+  (let [react-symbol (symbol (str *ns*) "upon")
+        react-multi `(defmulti ~react-symbol #(:component/event %2))]
+    `(do
+       (when-not ~(find-var react-symbol)
+         (println "Defining default react dispatcher: ")
+         ~react-multi) 
+       (defmethod ~react-symbol ~command [~'component ~'event]
+         ~@body))))
+
+
+(let [say-reactor '(defupon :say 
+                     (format "say with component=%s, event=%s" component event))]
+  (println (macroexpand-1 say-reactor))
+  (eval say-reactor))
+
+(let [component {:name :my.component}
+      event {:component/event :say
+             :message "hi"}]
+  (upon component event))
+
+
+```
+
+```
+
+(defmacro defaction
+  ""
+  [command & body]
+  `(let [react-symbol# ~(find-var (symbol (str *ns*) "react"))]
+     (when-not react-symbol#
+       (println "Defining default react dispatcher")
+       (defmulti ~'react-symbol# #(:command %2)))
+     (defmethod react-symbol# ~command [~'component ~'event]
+       ~@body)))
+
+
+```
+
+
+
+### Marathon deployment
+
+Deploy non-Docker packages. Nothing in particular against Docker, but I don't see the case for it with Marathon 
+and debootstrap.
+
+### Ansible
+
+familiar with it. yaml basaed DSL. as simple as you want it to be. downside? not edn.
+
+### Ubuntu
+
+APT
+debootstrap
+
+## Tool suggestions
+
+IntelliJ Idea with Cursive (free licenses for OSS!)
+
+emacs with clojure-mode and org-mode
+
+homebrew + cask
+
+
+
+## Thanks
+
+Thanks to all the authors and contributors of the projects used and literature referenced.

+ 1 - 0
clojure-objc-sample

@@ -0,0 +1 @@
+Subproject commit 15850085b2d0c398b91cf319c5ddacf335459896

+ 5 - 0
core/project.clj

@@ -0,0 +1,5 @@
+(defproject com.github.harlanji.clojure-stack/core "0.0.1-SNAPSHOT"
+  :plugins [[lein-modules "0.3.11"]]
+  :dependencies [[org.clojure/clojure "_"]
+                 [com.stuartsierra/component "_"]]
+  )

+ 37 - 0
core/src/com/github/harlanji/clojure-stack/core.clj

@@ -0,0 +1,37 @@
+(ns com.github.harlanji.clojure-stack.core)
+
+(def event-key :component/event)
+
+(defmacro defupon
+  "A shortcut to defining multi-methods. Automatically creates a dispatcher that dispatches by
+   :command/event field of the single argument."
+  [event & body]
+  (let [react-symbol (symbol (str *ns*) "upon")
+        react-multi `(defmulti ~react-symbol #(get %2 event-key))]
+       `(do
+          (when-not ~(find-var react-symbol)
+                    (println "Defining default react dispatcher: ")
+                    ~react-multi)
+          (defmethod ~react-symbol ~event [~'component ~'event]
+                     ~@body))))
+
+(defn event
+  "Shortcut methods to create an event."
+  ([event-name]
+    {event-key event-name})
+  ([event-name m]
+    (merge m (event event-name)))
+  ([event-name k v & kvs]
+    (event event-name (apply hash-map k v kvs))))
+
+
+(comment "test:"
+  (let [say-reactor '(defupon :request-say
+                              (format "say with component=%s, event=%s" component event))]
+       (println (macroexpand-1 say-reactor))
+       (eval say-reactor))
+
+  (let [component {:name :my.component}
+        say-hi (event :request-say :message "hi")]
+       (upon component say-hi))
+ )

+ 19 - 0
core/src/com/github/harlanji/clojure-stack/lifecycle.clj

@@ -0,0 +1,19 @@
+(ns com.github.harlanji.clojure-stack.lifecycle
+    (:require [com.stuartsierra.component :as component]
+              [com.github.harlanji.clojure-stack/core :refer [upon event]]))
+
+(defn- start* [component]
+       (upon component (event :component/start)))
+
+(defn- stop* [component]
+       (upon component (event :component/stop)))
+
+
+(defn start [component]
+      (if (is? )
+        (component/start component)
+        (component/update-system component start*)))
+(defn stop [component]
+      (if (is? )
+        (component/stop component)
+        (component/update-system-reverse component stop*)))

+ 9 - 0
ios-client/project.clj

@@ -0,0 +1,9 @@
+(defproject com.github.harlanji/pubsub-demo-web "0.0.1-SNAPSHOT"
+  :description ""
+  :plugins [[lein-objcbuild "_"]]
+  :objcbuild {:archs [:i386 :x86_64 #_:armv7 #_:armv7s]
+              :frameworks [:UIKit :Foundation :CFNetwork]}
+  :aot :all
+  :dependencies [[uikit "0.1.5"]
+                 [galdolber/clojure-objc "1.7.0-beta2"]]
+  :source-paths ^:replace ["ios-client/src"])

+ 522 - 0
ios-client/sample/sample.xcodeproj/project.pbxproj

@@ -0,0 +1,522 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		84405DDC189226CD007FACBA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84405DDB189226CD007FACBA /* Foundation.framework */; };
+		84405DDE189226CD007FACBA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84405DDD189226CD007FACBA /* CoreGraphics.framework */; };
+		84405DE0189226CD007FACBA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84405DDF189226CD007FACBA /* UIKit.framework */; };
+		84405DE6189226CD007FACBA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84405DE4189226CD007FACBA /* InfoPlist.strings */; };
+		84405DE8189226CD007FACBA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84405DE7189226CD007FACBA /* main.m */; };
+		84405DEC189226CD007FACBA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84405DEB189226CD007FACBA /* AppDelegate.m */; };
+		84405DEE189226CD007FACBA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84405DED189226CD007FACBA /* Images.xcassets */; };
+		84405DF5189226CE007FACBA /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84405DF4189226CE007FACBA /* XCTest.framework */; };
+		84405DF6189226CE007FACBA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84405DDB189226CD007FACBA /* Foundation.framework */; };
+		84405DF7189226CE007FACBA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84405DDF189226CD007FACBA /* UIKit.framework */; };
+		84405DFF189226CE007FACBA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84405DFD189226CE007FACBA /* InfoPlist.strings */; };
+		84405E01189226CE007FACBA /* sampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 84405E00189226CE007FACBA /* sampleTests.m */; };
+		DCA169951C2C9D16003FAB11 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCA169941C2C9D16003FAB11 /* CFNetwork.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		84405DF8189226CE007FACBA /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 84405DD0189226CD007FACBA /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 84405DD7189226CD007FACBA;
+			remoteInfo = sample;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		8427847118979C96000BC335 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
+		84405DD8189226CD007FACBA /* sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		84405DDB189226CD007FACBA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		84405DDD189226CD007FACBA /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		84405DDF189226CD007FACBA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		84405DE3189226CD007FACBA /* sample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "sample-Info.plist"; sourceTree = "<group>"; };
+		84405DE5189226CD007FACBA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		84405DE7189226CD007FACBA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		84405DE9189226CD007FACBA /* sample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "sample-Prefix.pch"; sourceTree = "<group>"; };
+		84405DEA189226CD007FACBA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		84405DEB189226CD007FACBA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		84405DED189226CD007FACBA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
+		84405DF3189226CE007FACBA /* sampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		84405DF4189226CE007FACBA /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+		84405DFC189226CE007FACBA /* sampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "sampleTests-Info.plist"; sourceTree = "<group>"; };
+		84405DFE189226CE007FACBA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		84405E00189226CE007FACBA /* sampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = sampleTests.m; sourceTree = "<group>"; };
+		DCA169941C2C9D16003FAB11 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		84405DD5189226CD007FACBA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DCA169951C2C9D16003FAB11 /* CFNetwork.framework in Frameworks */,
+				84405DDE189226CD007FACBA /* CoreGraphics.framework in Frameworks */,
+				84405DE0189226CD007FACBA /* UIKit.framework in Frameworks */,
+				84405DDC189226CD007FACBA /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		84405DF0189226CE007FACBA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84405DF5189226CE007FACBA /* XCTest.framework in Frameworks */,
+				84405DF7189226CE007FACBA /* UIKit.framework in Frameworks */,
+				84405DF6189226CE007FACBA /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		84405DCF189226CD007FACBA = {
+			isa = PBXGroup;
+			children = (
+				84405DE1189226CD007FACBA /* sample */,
+				84405DFA189226CE007FACBA /* sampleTests */,
+				84405DDA189226CD007FACBA /* Frameworks */,
+				84405DD9189226CD007FACBA /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		84405DD9189226CD007FACBA /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				84405DD8189226CD007FACBA /* sample.app */,
+				84405DF3189226CE007FACBA /* sampleTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		84405DDA189226CD007FACBA /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				DCA169941C2C9D16003FAB11 /* CFNetwork.framework */,
+				84405DDB189226CD007FACBA /* Foundation.framework */,
+				84405DDD189226CD007FACBA /* CoreGraphics.framework */,
+				84405DDF189226CD007FACBA /* UIKit.framework */,
+				84405DF4189226CE007FACBA /* XCTest.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		84405DE1189226CD007FACBA /* sample */ = {
+			isa = PBXGroup;
+			children = (
+				84405DEA189226CD007FACBA /* AppDelegate.h */,
+				84405DEB189226CD007FACBA /* AppDelegate.m */,
+				84405DED189226CD007FACBA /* Images.xcassets */,
+				84405DE2189226CD007FACBA /* Supporting Files */,
+			);
+			path = sample;
+			sourceTree = "<group>";
+		};
+		84405DE2189226CD007FACBA /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				8427847118979C96000BC335 /* Config.xcconfig */,
+				84405DE3189226CD007FACBA /* sample-Info.plist */,
+				84405DE4189226CD007FACBA /* InfoPlist.strings */,
+				84405DE7189226CD007FACBA /* main.m */,
+				84405DE9189226CD007FACBA /* sample-Prefix.pch */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		84405DFA189226CE007FACBA /* sampleTests */ = {
+			isa = PBXGroup;
+			children = (
+				84405E00189226CE007FACBA /* sampleTests.m */,
+				84405DFB189226CE007FACBA /* Supporting Files */,
+			);
+			path = sampleTests;
+			sourceTree = "<group>";
+		};
+		84405DFB189226CE007FACBA /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				84405DFC189226CE007FACBA /* sampleTests-Info.plist */,
+				84405DFD189226CE007FACBA /* InfoPlist.strings */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		84405DD7189226CD007FACBA /* sample */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 84405E04189226CE007FACBA /* Build configuration list for PBXNativeTarget "sample" */;
+			buildPhases = (
+				84405DD4189226CD007FACBA /* Sources */,
+				84405DD5189226CD007FACBA /* Frameworks */,
+				84405DD6189226CD007FACBA /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = sample;
+			productName = sample;
+			productReference = 84405DD8189226CD007FACBA /* sample.app */;
+			productType = "com.apple.product-type.application";
+		};
+		84405DF2189226CE007FACBA /* sampleTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 84405E07189226CE007FACBA /* Build configuration list for PBXNativeTarget "sampleTests" */;
+			buildPhases = (
+				84405DEF189226CE007FACBA /* Sources */,
+				84405DF0189226CE007FACBA /* Frameworks */,
+				84405DF1189226CE007FACBA /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				84405DF9189226CE007FACBA /* PBXTargetDependency */,
+			);
+			name = sampleTests;
+			productName = sampleTests;
+			productReference = 84405DF3189226CE007FACBA /* sampleTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		84405DD0189226CD007FACBA /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0510;
+				ORGANIZATIONNAME = "clojure-objc";
+				TargetAttributes = {
+					84405DD7189226CD007FACBA = {
+						DevelopmentTeam = LHP68VSNAM;
+					};
+					84405DF2189226CE007FACBA = {
+						TestTargetID = 84405DD7189226CD007FACBA;
+					};
+				};
+			};
+			buildConfigurationList = 84405DD3189226CD007FACBA /* Build configuration list for PBXProject "sample" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 84405DCF189226CD007FACBA;
+			productRefGroup = 84405DD9189226CD007FACBA /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				84405DD7189226CD007FACBA /* sample */,
+				84405DF2189226CE007FACBA /* sampleTests */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		84405DD6189226CD007FACBA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84405DE6189226CD007FACBA /* InfoPlist.strings in Resources */,
+				84405DEE189226CD007FACBA /* Images.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		84405DF1189226CE007FACBA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84405DFF189226CE007FACBA /* InfoPlist.strings in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		84405DD4189226CD007FACBA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84405DEC189226CD007FACBA /* AppDelegate.m in Sources */,
+				84405DE8189226CD007FACBA /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		84405DEF189226CE007FACBA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84405E01189226CE007FACBA /* sampleTests.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		84405DF9189226CE007FACBA /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 84405DD7189226CD007FACBA /* sample */;
+			targetProxy = 84405DF8189226CE007FACBA /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		84405DE4189226CD007FACBA /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				84405DE5189226CD007FACBA /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		84405DFD189226CE007FACBA /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				84405DFE189226CE007FACBA /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		84405E02189226CE007FACBA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 7.1;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		84405E03189226CE007FACBA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 7.1;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		84405E05189226CE007FACBA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 8427847118979C96000BC335 /* Config.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				CLANG_ENABLE_OBJC_ARC = NO;
+				CODE_SIGN_IDENTITY = "iPhone Developer";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "sample/sample-Prefix.pch";
+				GCC_WARN_UNUSED_FUNCTION = NO;
+				GCC_WARN_UNUSED_VALUE = NO;
+				GCC_WARN_UNUSED_VARIABLE = NO;
+				HEADER_SEARCH_PATHS = (
+					"$(CLOJUREOBJC)/include",
+					"$(SRCROOT)/../../target/include",
+					"$(inherited)",
+				);
+				INFOPLIST_FILE = "sample/sample-Info.plist";
+				LIBRARY_SEARCH_PATHS = (
+					"$(CLOJUREOBJC)",
+					"$(SRCROOT)/../../target",
+				);
+				ONLY_ACTIVE_ARCH = NO;
+				OTHER_CFLAGS = "-Wno-unsequenced";
+				OTHER_LDFLAGS = (
+					"-lz",
+					"-ljre_emul",
+					"-lffi",
+					"-ObjC",
+					"-lclojure-objc",
+					"-lpubsub-clojure-demo",
+					"-licucore",
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE = "";
+				VALID_ARCHS = "armv7 armv7s";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		84405E06189226CE007FACBA /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 8427847118979C96000BC335 /* Config.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				CLANG_ENABLE_OBJC_ARC = NO;
+				CODE_SIGN_IDENTITY = "iPhone Developer";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "sample/sample-Prefix.pch";
+				GCC_WARN_UNUSED_FUNCTION = NO;
+				GCC_WARN_UNUSED_VALUE = NO;
+				GCC_WARN_UNUSED_VARIABLE = NO;
+				HEADER_SEARCH_PATHS = (
+					"$(CLOJUREOBJC)/include",
+					"$(SRCROOT)/../../target/include",
+					"$(inherited)",
+				);
+				INFOPLIST_FILE = "sample/sample-Info.plist";
+				LIBRARY_SEARCH_PATHS = (
+					"$(CLOJUREOBJC)",
+					"$(SRCROOT)/../../target",
+				);
+				OTHER_CFLAGS = "-Wno-unsequenced";
+				OTHER_LDFLAGS = (
+					"-lz",
+					"-ljre_emul",
+					"-lffi",
+					"-ObjC",
+					"-lclojure-objc",
+					"-lpubsub-clojure-demo",
+					"-licucore",
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE = "";
+				VALID_ARCHS = "armv7 armv7s";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+		84405E08189226CE007FACBA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/sample.app/sample";
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(SDKROOT)/Developer/Library/Frameworks",
+					"$(inherited)",
+					"$(DEVELOPER_FRAMEWORKS_DIR)",
+				);
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "sample/sample-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				INFOPLIST_FILE = "sampleTests/sampleTests-Info.plist";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TEST_HOST = "$(BUNDLE_LOADER)";
+				WRAPPER_EXTENSION = xctest;
+			};
+			name = Debug;
+		};
+		84405E09189226CE007FACBA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/sample.app/sample";
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(SDKROOT)/Developer/Library/Frameworks",
+					"$(inherited)",
+					"$(DEVELOPER_FRAMEWORKS_DIR)",
+				);
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "sample/sample-Prefix.pch";
+				INFOPLIST_FILE = "sampleTests/sampleTests-Info.plist";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TEST_HOST = "$(BUNDLE_LOADER)";
+				WRAPPER_EXTENSION = xctest;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		84405DD3189226CD007FACBA /* Build configuration list for PBXProject "sample" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				84405E02189226CE007FACBA /* Debug */,
+				84405E03189226CE007FACBA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		84405E04189226CE007FACBA /* Build configuration list for PBXNativeTarget "sample" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				84405E05189226CE007FACBA /* Debug */,
+				84405E06189226CE007FACBA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		84405E07189226CE007FACBA /* Build configuration list for PBXNativeTarget "sampleTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				84405E08189226CE007FACBA /* Debug */,
+				84405E09189226CE007FACBA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 84405DD0189226CD007FACBA /* Project object */;
+}

+ 7 - 0
ios-client/sample/sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:sample.xcodeproj">
+   </FileRef>
+</Workspace>

+ 41 - 0
ios-client/sample/sample.xcodeproj/project.xcworkspace/xcshareddata/sample.xccheckout

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDESourceControlProjectFavoriteDictionaryKey</key>
+	<false/>
+	<key>IDESourceControlProjectIdentifier</key>
+	<string>6D50E748-A10A-4474-A8BF-3154459A4F5C</string>
+	<key>IDESourceControlProjectName</key>
+	<string>sample</string>
+	<key>IDESourceControlProjectOriginsDictionary</key>
+	<dict>
+		<key>5964956D66FC04634E6A8382ACEBA04DCDACD78C</key>
+		<string>https://github.com/galdolber/clojure-objc-sample.git</string>
+	</dict>
+	<key>IDESourceControlProjectPath</key>
+	<string>sample/sample.xcodeproj</string>
+	<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
+	<dict>
+		<key>5964956D66FC04634E6A8382ACEBA04DCDACD78C</key>
+		<string>../../..</string>
+	</dict>
+	<key>IDESourceControlProjectURL</key>
+	<string>https://github.com/galdolber/clojure-objc-sample.git</string>
+	<key>IDESourceControlProjectVersion</key>
+	<integer>111</integer>
+	<key>IDESourceControlProjectWCCIdentifier</key>
+	<string>5964956D66FC04634E6A8382ACEBA04DCDACD78C</string>
+	<key>IDESourceControlProjectWCConfigurations</key>
+	<array>
+		<dict>
+			<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
+			<string>public.vcs.git</string>
+			<key>IDESourceControlWCCIdentifierKey</key>
+			<string>5964956D66FC04634E6A8382ACEBA04DCDACD78C</string>
+			<key>IDESourceControlWCCName</key>
+			<string>clojure-objc-sample</string>
+		</dict>
+	</array>
+</dict>
+</plist>

BIN
ios-client/sample/sample.xcodeproj/project.xcworkspace/xcuserdata/harlan.xcuserdatad/UserInterfaceState.xcuserstate


+ 20 - 0
ios-client/sample/sample.xcodeproj/project.xcworkspace/xcuserdata/harlan.xcuserdatad/WorkspaceSettings.xcsettings

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildLocationStyle</key>
+	<string>UseAppPreferences</string>
+	<key>CustomBuildLocationType</key>
+	<string>RelativeToDerivedData</string>
+	<key>DerivedDataLocationStyle</key>
+	<string>Default</string>
+	<key>IssueFilterStyle</key>
+	<string>ShowActiveSchemeOnly</string>
+	<key>LiveSourceIssuesEnabled</key>
+	<true/>
+	<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
+	<true/>
+	<key>SnapshotLocationStyle</key>
+	<string>Default</string>
+</dict>
+</plist>

+ 112 - 0
ios-client/sample/sample.xcodeproj/xcuserdata/harlan.xcuserdatad/xcschemes/sample.xcscheme

@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0640"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "84405DD7189226CD007FACBA"
+               BuildableName = "sample.app"
+               BlueprintName = "sample"
+               ReferencedContainer = "container:sample.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "84405DF2189226CE007FACBA"
+               BuildableName = "sampleTests.xctest"
+               BlueprintName = "sampleTests"
+               ReferencedContainer = "container:sample.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "84405DF2189226CE007FACBA"
+               BuildableName = "sampleTests.xctest"
+               BlueprintName = "sampleTests"
+               ReferencedContainer = "container:sample.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "84405DD7189226CD007FACBA"
+            BuildableName = "sample.app"
+            BlueprintName = "sample"
+            ReferencedContainer = "container:sample.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "84405DD7189226CD007FACBA"
+            BuildableName = "sample.app"
+            BlueprintName = "sample"
+            ReferencedContainer = "container:sample.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "84405DD7189226CD007FACBA"
+            BuildableName = "sample.app"
+            BlueprintName = "sample"
+            ReferencedContainer = "container:sample.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 27 - 0
ios-client/sample/sample.xcodeproj/xcuserdata/harlan.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>sample.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>84405DD7189226CD007FACBA</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>84405DF2189226CE007FACBA</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 15 - 0
ios-client/sample/sample/AppDelegate.h

@@ -0,0 +1,15 @@
+//
+//  AppDelegate.h
+//  sample
+//
+//  Created by Gal Dolber on 1/24/14.
+//  Copyright (c) 2014 clojure-objc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end

+ 33 - 0
ios-client/sample/sample/AppDelegate.m

@@ -0,0 +1,33 @@
+//
+//  AppDelegate.m
+//  sample
+//
+//  Created by Gal Dolber on 1/24/14.
+//  Copyright (c) 2014 clojure-objc. All rights reserved.
+//
+
+#import "AppDelegate.h"
+#import "clojure/lang/RT.h"
+#import "clojure/lang/Var.h"
+#import "clojure/lang/ObjC.h"
+#import "ReplClient.h"
+#import "sample/core_main.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+    [ClojureLangObjC setObjC];
+    [ClojureLangRT load__WithNSString:@"clojure/core"];
+
+    // to start repl: uncomment, start jvm repl and call (remote-repl)
+    // [ReplClient connect:@"localhost"];
+    // return YES;
+    
+    // to run app
+    [ClojureLangRT load__WithNSString:@"sample/core"];
+    [Samplecore_main_get_VAR_() invoke];
+    return YES;
+}
+
+@end

+ 1 - 0
ios-client/sample/sample/Config.xcconfig

@@ -0,0 +1 @@
+CLOJUREOBJC="/Users/harlan/.clojure-objc/1.7.0-RC1"

+ 23 - 0
ios-client/sample/sample/Images.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 23 - 0
ios-client/sample/sample/Images.xcassets/LaunchImage.launchimage/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "subtype" : "retina4",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 2 - 0
ios-client/sample/sample/en.lproj/InfoPlist.strings

@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+

+ 18 - 0
ios-client/sample/sample/main.m

@@ -0,0 +1,18 @@
+//
+//  main.m
+//  sample
+//
+//  Created by Gal Dolber on 1/24/14.
+//  Copyright (c) 2014 clojure-objc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[])
+{
+    @autoreleasepool {
+        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+    }
+}

+ 38 - 0
ios-client/sample/sample/sample-Info.plist

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>clojure-objc.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

+ 16 - 0
ios-client/sample/sample/sample-Prefix.pch

@@ -0,0 +1,16 @@
+//
+//  Prefix header
+//
+//  The contents of this file are implicitly included at the beginning of every source file.
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_3_0
+#warning "This project uses features only available in iOS SDK 3.0 and later."
+#endif
+
+#ifdef __OBJC__
+    #define J2OBJC_DISABLE_ALL_CHECKS 1
+    #import <Foundation/Foundation.h>
+#endif

+ 2 - 0
ios-client/sample/sampleTests/en.lproj/InfoPlist.strings

@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+

+ 22 - 0
ios-client/sample/sampleTests/sampleTests-Info.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>clojure-objc.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>

+ 34 - 0
ios-client/sample/sampleTests/sampleTests.m

@@ -0,0 +1,34 @@
+//
+//  sampleTests.m
+//  sampleTests
+//
+//  Created by Gal Dolber on 1/24/14.
+//  Copyright (c) 2014 clojure-objc. All rights reserved.
+//
+
+#import <XCTest/XCTest.h>
+
+@interface sampleTests : XCTestCase
+
+@end
+
+@implementation sampleTests
+
+- (void)setUp
+{
+    [super setUp];
+    // Put setup code here. This method is called before the invocation of each test method in the class.
+}
+
+- (void)tearDown
+{
+    // Put teardown code here. This method is called after the invocation of each test method in the class.
+    [super tearDown];
+}
+
+- (void)testExample
+{
+    XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
+}
+
+@end

+ 68 - 0
ios-client/src/sample/core.clj

@@ -0,0 +1,68 @@
+(ns sample.core
+    (:require [uikit.core :as uikit]))
+
+(def white (-> ($ UIColor)
+               ($ :whiteColor)))
+
+(declare abc)
+
+(defn on-tap [scope]
+      ;(uikit/alert! "Clojure" "Oh hai!")
+      (uikit/alert! "Clojure" (abc))
+      )
+
+(def my-screen [:UIView :main
+                {:setBackgroundColor white
+                 :constraints        ["C:button.centerx=main.centerx"
+                                      "C:button.centery=main.centery"]}
+                [(uikit/button 1) :button {:setTitle:forState ["Tap me!" 0]
+                                           :gestures          {:UITapGestureRecognizer #'on-tap}}]])
+
+
+
+(defn main []
+      (let [window (-> ($ UIWindow)
+                       ($ :alloc)
+                       ($ :initWithFrame (-> ($ UIScreen)
+                                             ($ :mainScreen)
+                                             ($ :bounds))))
+            nav (-> ($ UINavigationController)
+                    ($ :new))]
+           (doto window
+                 ($ :makeKeyAndVisible)
+                 ($ :setRootViewController nav)
+                 ($ :setBackgroundColor white))
+           (reset! uikit/current-top-controller nav)
+           ($ nav :setNavigationBarHidden true)
+           (uikit/nav-push (uikit/controller "Screen title" my-screen))))
+
+
+
+
+
+(defn abc []
+      (let [;url (-> ($ NSString)
+            ;        ($ :stringWithFormat ["http://localhost:3000/consume/@%/@%/@%" "abc" 0 1]))
+
+            ;url ($ ($ NSCommon) :invokeSuperSel ($ NSString) :withDispatchClass nil :withSelector "stringWithFormat:" :withArgs ["http://localhost:3000/consume/@%/@%/@%" "abc" 0 1])
+
+            url (-> ($ NSURL)
+                    ($ :URLWithString "http://localhost:3000/consume/bc/0/1"))
+
+            error (-> ($ NSError)
+                      ($ :alloc)
+                      ($ :init))
+
+            request (-> ($ NSMutableURLRequest)
+                        ($ :requestWithURL url))
+
+            ;response-data (-> ($ NSConnectionURL)
+            ;                  ($ :sendSynchronousRequest request :returningResponse nil :error error))
+
+            ;result (-> ($ NSString)
+            ;           ($ :alloc)
+            ;           ($ :initWithResponseData response-data :encoding ($ NSUTF8StringEncoding)))
+            ]
+           ;result
+            "YO ABC"
+           ))

+ 17 - 0
project.clj

@@ -0,0 +1,17 @@
+(defproject com.github.harlanji/clojure-stack "0.0.1-SNAPSHOT"
+  :description "A demo PubSub microservice."
+
+  :plugins [[lein-modules "0.3.11"]
+            [lein-ancient "0.6.8"]]
+
+
+  :modules {:dirs ["core"
+                   "pubsub-service"]
+            :versions {com.github.harlanji.clojure-stack/core "0.0.1-SNAPSHOT"
+                       com.github.harlanji.clojure-stack/pubsub-service "0.0.1-SNAPSHOT"
+                       lein-objcbuild "0.1.10"
+                       org.clojure/clojure "1.7.0"
+                       org.clojure/clojurescript "1.7.170"
+                       com.stuartsierra/component "0.3.1"}
+            }
+  )

+ 25 - 0
project.org

@@ -0,0 +1,25 @@
+#+TITLE: Clojure Stack Project Organizer
+
+* Development Environment
+** TODO Create Vagrantfile
+** TODO Setup Vagrant and Marathon via Ansible
+
+
+* iOS
+** TODO Verify X Code build
+** TODO Create streaming client component
+** TODO Look into CocoaPods
+
+As Jordan Z About this.
+
+* Web
+** TODO Create re-frame Project
+** TODO Create streaming client component
+
+
+* Core Service
+** TODO Make Pub/Sub Service
+** TODO Make Materialized KV Service (Aggregate Object)
+** TODO Integrate Component
+* Fun
+** Create Dataflow DAG visualizer

+ 14 - 0
pubsub-service/project.clj

@@ -0,0 +1,14 @@
+(defproject com.github.harlanji.clojure-stack/pubsub-service "0.0.1-SNAPSHOT"
+            :plugins [[lein-modules "0.3.11"]
+                      [lein-ring "0.9.7"]]
+            :dependencies [[org.clojure/clojure "_"]
+                           [prismatic/schema "1.0.3"]
+                           [org.clojure/tools.cli "0.3.3"]
+                           [nginx-clojure "0.4.3"]
+                           [ring/ring-core "1.4.0"]
+                           [ring/ring-json "0.4.0"]
+                           [bidi "1.21.1"]
+                           [com.github.harlanji.clojure-stack/core "_"]]
+            :ring {:init pubsub.demo/init
+                   :handler pubsub.demo/app}
+)

+ 48 - 0
pubsub-service/src/pubsub/demo.clj

@@ -0,0 +1,48 @@
+(ns pubsub.demo
+  (:require [bidi.ring :refer [make-handler resources-maybe]]
+            [ring.middleware.json :refer [wrap-json-response wrap-json-body]]
+            [ring.util.response :refer [response]]
+            ))
+
+(defn init []
+  (comment "-use mesos disco for kafka and zookeeper URLs")
+  (println "Hello! Init done."))
+
+
+
+(def messages (atom {}))
+
+(defn produce
+  [req]
+  (let [{channel :channel} (:route-params req)
+        body (:body req)
+        channel-messages (conj (get @messages channel []) body)]
+    (println "produced body:" body)
+    (swap! messages assoc channel channel-messages)
+    {:status 200 :body {:latest-offset (count channel-messages)
+                        :avail (keys req)}}))
+
+(clojure.tools.nrepl.middleware.interruptible-eval)
+
+(defn consume
+  [req]
+  (println "consume")
+  (let [{channel :channel offset :offset count_ :count} (:route-params req)
+        channel-messages (get @messages channel [])
+        messages (subvec channel-messages (Long/valueOf offset) (Long/valueOf count_))]
+    {:status 200 :body {:messages messages}}))
+
+
+(def pubsub-routes ["/" {["produce/" :channel] {:put produce}
+                         ["consume/" :channel "/" :offset "/" :count] {:get consume}
+                         "" (resources-maybe {:prefix "public/"})}])
+
+
+(def app (-> (make-handler pubsub-routes)
+
+             ; todo support EDN. implement these to mirror json. ie use body, not params.
+             ;wrap-edn-body
+             ;wrap-edn-response
+
+             wrap-json-body
+             wrap-json-response))

+ 76 - 0
pubsub-service/src/pubsub/main.clj

@@ -0,0 +1,76 @@
+(ns pubsub.main
+    (:require [clojure.tools.cli :refer [parse-opts]]
+              [clojure.string :as string]
+              [pubsub.demo :as server])
+    (:import [java.net InetAddress])
+    (:gen-class))
+
+(def cli-options
+  [;; First three strings describe a short-option, long-option with optional
+   ;; example argument description, and a description. All three are optional
+   ;; and positional.
+   ["-p" "--port PORT" "Port number"
+    :default 80
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
+   ["-H" "--hostname HOST" "Remote host"
+    :default (InetAddress/getByName "localhost")
+    ;; Specify a string to output in the default column in the options summary
+    ;; if the default value's string representation is very ugly
+    :default-desc "localhost"
+    :parse-fn #(InetAddress/getByName %)]
+   ;; If no required argument description is given, the option is assumed to
+   ;; be a boolean option defaulting to nil
+   [nil "--detach" "Detach from controlling process"]
+   ["-v" nil "Verbosity level; may be specified multiple times to increase value"
+    ;; If no long-option is specified, an option :id must be given
+    :id :verbosity
+    :default 0
+    ;; Use assoc-fn to create non-idempotent options
+    :assoc-fn (fn [m k _] (update-in m [k] inc))]
+   ["-h" "--help"]])
+
+(defn usage [options-summary]
+      (->> ["This is my program. There are many like it, but this one is mine."
+            ""
+            "Usage: program-name [options] action"
+            ""
+            "Options:"
+            options-summary
+            ""
+            "Actions:"
+            "  start    Start a new server"
+            "  stop     Stop an existing server"
+            "  status   Print a server's status"
+            ""
+            "Please refer to the manual page for more information."]
+           (string/join \newline)))
+
+(defn error-msg [errors]
+      (str "The following errors occurred while parsing your command:\n\n"
+           (string/join \newline errors)))
+
+(defn exit [status msg]
+      (println msg)
+      (System/exit status))
+
+
+
+(defn start-server [options]
+      (server/init options)
+      (serve server/app (:port options)))
+
+(defn -main [& args]
+      (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)]
+           ;; Handle help and error conditions
+           (cond
+             (:help options) (exit 0 (usage summary))
+             (not= (count arguments) 1) (exit 1 (usage summary))
+             errors (exit 1 (error-msg errors)))
+           ;; Execute program with options
+           (case (first arguments)
+                 "start" (start-server options)
+                 "stop" (println "stop")
+                 "status" (println "status")
+                 "options" (println options)
+                 (exit 1 (usage summary)))))

+ 25 - 0
pubsub-service/src/pubsub/sequencer.clj

@@ -0,0 +1,25 @@
+(ns pubsub.sequencer)
+
+(def routing-table (atom {}))
+
+(defrecord Sequencing [sequence-number
+                       group-local-sequencer-number
+                       forwarding-table
+                       reverse-path-table
+                       output-buffer ; channel?
+                       input-buffer])
+
+
+
+(defrecord SequencerNode [ingress
+                          distribute])
+
+(def ingress (chan))
+(def distribute {:va (chan)
+                 :ca (chan)
+                 :ir (chan)})
+
+(defn sequence []
+      (let []
+           ()))
+

+ 1 - 0
resources/public/index.html

@@ -0,0 +1 @@
+Hello PubSub Demo!

+ 39 - 0
web-client/project.clj

@@ -0,0 +1,39 @@
+(defproject com.github.harlanji/pubsub-demo-web "0.0.1-SNAPSHOT"
+            :description ""
+
+            :plugins [[lein-cljsbuild "1.1.1"]
+                      [lein-figwheel  "0.5.0-2"]]
+
+            :hooks [leiningen.cljsbuild]
+
+            :profiles {:dev {:cljsbuild
+                             {:builds {:client {:source-paths ["devsrc"]
+                                                :compiler     {:main com.github.harlanji.pubsub-demo-web/main
+                                                               :asset-path "js"
+                                                               :optimizations :none
+                                                               :source-map true
+                                                               :source-map-timestamp true}}}}}
+
+                       :prod {:cljsbuild
+                              {:builds {:client {:compiler    {:optimizations :advanced
+                                                               :elide-asserts true
+                                                               :pretty-print false}}}}}}
+
+            :dependencies [[org.clojure/clojure       "_"]
+                           [org.clojure/clojurescript "_"]
+                           [reagent "0.6.0-alpha"]
+                           [re-frame "0.7.0-alpha"]]
+
+            :plugins [[lein-cljsbuild "1.1.1"]
+                      [lein-figwheel  "0.5.0-2"]]
+
+
+            :figwheel {:repl false}
+
+            :clean-targets ^{:protect false} ["resources/public/js"]
+
+            :cljsbuild {:builds {:client {:source-paths ["src"]
+                                          :compiler     {:output-dir "resources/public/js"
+                                                         :output-to  "resources/public/js/client.js"}}}}
+
+            )

+ 4 - 0
web-client/resources/src/com/github/harlanji/pubsub_demo_web.clj

@@ -0,0 +1,4 @@
+(ns com.github.harlanji.pubsub-demo-web
+    )
+
+(defn main [])