   (when-let [id (resolve-id db-snap id)]
     (get-in* db-snap [:data id])))
 
-(defn get [db-snap id attr]
-  (get* (entity db-snap id) attr))
-
-(defn get-in [db-snap id & ks]
+(defn get [db-snap id & args]
+  (apply get* (cons (entity db-snap id) args)))
+
+(defn get-in [db-snap id ks]
   (get-in* (entity db-snap id) ks))
 
 (defn add-index [[db-snap reports] id a v]

  {:db/retract-entity retract-entity
   :db/retract-attr   retract-attr
   :db/add            add
   :db/update         update})

(defn find-id-by-unique-attr [db-snap tx]
  (when (map? tx)
        (when-let [a (->> (keys tx)
                          (filter (partial unique? db-snap))
                          first)]
          (resolve-id db-snap [a (get* tx a)]))))

(defn get-id [tx]
  (cond (map? tx) (:db/id tx)

          :else (do
                  (throw (js/Error (str "Not a valid id: " id)))))))

(defn has? [db-snap e]
  (contains? (:data db-snap) (resolve-id db-snap e)))

(defn create-id! [db]
  (:entity-count (swap! db update* :entity-count
                        (fn [c] (first (filter #(not (has? @db %))
                                               (iterate inc (inc c))))))))


(defn- listen-path!
  [db path f]
  (doto db
    (swap! update-in path #((fnil conj #{}) % f))))

(defn listen!
  ([db f]
   (listen-path! db [:listeners :tx-log] f))
  ([db id f]
   (listen-path! db [:listeners :entity id] f))
  ([db id attr f]
   (listen-path! db [:listeners :entity-attr id attr] f)))

(defn- unlisten-path!
  [db path f]
  (doto db
    (swap! update-in path #(disj % f))))

(defn unlisten!
  ([db f]
   (unlisten-path! db [:listeners :tx-log] f))
  ([db id f]
   (unlisten-path! db [:listeners :entity id] f))
  ([db id attr f]
   (unlisten-path! db [:listeners :entity-attr id attr] f)))

(defn upsert-attr? [id]
  (and (number? id) (neg? id)))
