   ([o1 o2 & more]
      (apply upsert-merge (upsert-merge o1 o2) more)))
 
-
-;; Hash KV Index, meant to be for a root store index (unique keys)
-;; - Merging upsert against existing if keyfn output matches
-;; - Nil values in provided object deletes keys
-;; - Original object maintains identity
-(deftype HashIndex [keyfn hashmap]
-  ILookup
-  (-lookup [idx val]
-    (-lookup idx val nil))
-  (-lookup [idx val not-found]
-    (js-lookup hashmap val not-found))
-
-  IFn
-  (-invoke [idx k]
-    (-lookup idx k))
-  (-invoke [idx k not-found]
-    (-lookup idx k not-found))
-
-  ICounted
-  (-count [idx] (alength (js-keys hashmap)))
-
-  IIndex
-  (key-fn [idx] keyfn)
-  (index! [idx obj]
-    (let [key (keyfn obj)
-          old (js-lookup hashmap key)]
-      (js-assoc hashmap key (if old (upsert-merge old obj) obj))))
-  (unindex! [idx obj]
-    (let [key (keyfn obj)]
-      (js-dissoc hashmap key obj))))
-
-(defn root-index []
-  (HashIndex. #(aget % "id") #js {}))
-
 ;; Return a cursor for walking a range of the index
 (deftype Cursor [idx start end ^:mutable valid?]
   IReduce

        (if (< i end)
          (recur (inc i) (f ret (aget a i)))
          ret)))))

;; KV index using binary search/insert/remove on array
;; - Always inserts new objects in sorted order

  "Walk the entire store, or an index"
  ([store]
     ;; TODO - this is broken, add inform tracker, etc.
     (-get-cursor (.-root store)))
  ([store index start]
     (deps/inform-tracker store (js-obj (name index) (array start (last-val index)))) ;; shorthand
     (-get-cursor (get-index store index) start))
