              (write-text-file to options))))))
 
 (defn write-edn-file
+  {:doc (with-opts-docstr
+          "Writes a PCollection of edn strings to disk or Google Storage, with records separated by newlines.
+See https://cloud.google.com/dataflow/java-sdk/JavaDoc/com/google/cloud/dataflow/sdk/io/TextIO.Write.html
+
+  Example:
+    (write-edn-file \"gs://target/path\" pcoll)"
+          base-schema text-writer-schema)
+   :added "0.1.0"}
   ([to options ^PCollection pcoll]
    (let [opts (assoc options :label (str "write-edn-file-to-" (clean-filename to)))]
      (-> pcoll
-         (.apply (with-opts base-schema opts
+         (.apply (with-opts (merge base-schema text-writer-schema) opts
                    (write-edn-file-transform to opts))))))
   ([to pcoll] (write-edn-file to {} pcoll)))
 

             (from-edn options))))))

(defn read-edn-file
  ([from options ^Pipeline p]
   (let [opts (assoc options :label (str "read-edn-file-from-"
                                         (clean-filename from)))]
     (-> p
         (.apply (with-opts base-schema opts
                   (read-edn-file-transform from opts))))))
  ([from p] (read-edn-file from {} p)))


   {:side-inputs {:docstr "Adds a map of PCollectionViews as side inputs to the underlying ParDo Transform. They can be accessed there by key in the datasplash.dv/*side-inputs* var."
                  :action (fn [transform inputs]
                            (.withSideInputs transform (map val (sort-by key inputs))))}
    :without-coercion-to-clj {:docstr "Avoids coercing Dataflow types to Clojure, like KV. Coercion will happen by default"}}))

(defn map-op
  ([transform label coder]
