Added documentation by adapting descriptions from the RFC
Getty Ritter
10 years ago
| 1 | 1 | {-# LANGUAGE OverloadedStrings #-} |
| 2 | ||
| 2 | 3 | |
| 3 | 4 | {-| |
| 4 | 5 | Module : Codec.ActivityStream.Dynamic |
| 9 | 10 | This is an interface to ActivityStreams that simply wraps an underlying |
| 10 | 11 | @aeson@ Object, and exposes a set of (convenient) lenses to access the |
| 11 | 12 | values inside. If an @aeson@ object is wrapped in the respective wrapper, |
| 12 |
it will contain the obligatory values for that type (e.g. an |
|
| 13 | it will contain the obligatory values for that type (e.g. an 'Activity' | |
| 13 | 14 | is guaranteed to have a @published@ date.) |
| 15 | ||
| 16 | Most of the inline documentation is drawn directly from the | |
| 17 | <http://activitystrea.ms/specs/json/1.0/ JSON Activity Streams 1.0> | |
| 18 | specification, with minor modifications | |
| 19 | to refer to the corresponding data types in this module and to clarify | |
| 20 | certain aspects. | |
| 14 | 21 | -} |
| 15 | 22 | |
| 16 | 23 | module Codec.ActivityStream.Dynamic |
| 17 | 24 | ( Lens' |
| 18 | -- * MediaLink | |
| 19 | , MediaLink | |
| 20 | , mlDuration | |
| 21 | , mlHeight | |
| 22 | , mlWidth | |
| 23 | , mlURL | |
| 24 | , mlRest | |
| 25 | , makeMediaLink | |
| 26 | 25 | -- * Object |
| 27 | 26 | , Object |
| 27 | , emptyObject | |
| 28 | -- ** Object Lenses | |
| 28 | 29 | , oAttachments |
| 29 | 30 | , oAuthor |
| 30 | 31 | , oContent |
| 39 | 40 | , oUpstreamDuplicates |
| 40 | 41 | , oURL |
| 41 | 42 | , oRest |
| 42 | , emptyObject | |
| 43 | 43 | -- * Activity |
| 44 | 44 | , Activity |
| 45 | , makeActivity | |
| 46 | , asObject | |
| 47 | -- ** Activity Lenses | |
| 45 | 48 | , acActor |
| 46 | 49 | , acContent |
| 47 | 50 | , acGenerator |
| 56 | 59 | , acURL |
| 57 | 60 | , acVerb |
| 58 | 61 | , acRest |
| 59 | , makeActivity | |
| 60 | , asObject | |
| 62 | -- * MediaLink | |
| 63 | , MediaLink | |
| 64 | , makeMediaLink | |
| 65 | -- ** MediaLink Lenses | |
| 66 | , mlDuration | |
| 67 | , mlHeight | |
| 68 | , mlWidth | |
| 69 | , mlURL | |
| 70 | , mlRest | |
| 61 | 71 | -- * Collection |
| 62 | 72 | , Collection |
| 73 | , makeCollection | |
| 74 | -- ** Collection Lenses | |
| 63 | 75 | , cTotalItems |
| 64 | 76 | , cItems |
| 65 | 77 | , cURL |
| 66 | 78 | , cRest |
| 67 | , makeCollection | |
| 68 | 79 | ) where |
| 69 | 80 | |
| 70 | 81 | import Data.Aeson ( FromJSON(..) |
| 77 | 88 | import qualified Data.HashMap.Strict as HM |
| 78 | 89 | import Data.Text (Text) |
| 79 | 90 | |
| 80 | import Codec.ActivityStream.LensInternal ( Lens' | |
| 81 | , makeLens | |
| 82 | , makeAesonLens | |
| 83 | , makeAesonLensMb | |
| 84 | ) | |
| 85 | ||
| 91 | import Codec.ActivityStream.LensInternal | |
| 92 | ||
| 93 | -- | Some types of objects may have an alternative visual representation in | |
| 94 | -- the form of an image, video or embedded HTML fragments. A 'MediaLink' | |
| 95 | -- represents a hyperlink to such resources. | |
| 86 | 96 | data MediaLink = MediaLink { fromMediaLink :: A.Object } deriving (Eq, Show) |
| 87 | 97 | |
| 88 | 98 | instance FromJSON MediaLink where |
| 89 | parseJSON (A.Object o) | HM.member "url" o = return (MediaLink o) | |
| 90 | | otherwise = fail "..." | |
| 91 |
parseJSON |
|
| 99 | parseJSON (A.Object o) | |
| 100 | | HM.member "url" o = return (MediaLink o) | |
| 101 | | otherwise = fail "MediaLink object contains no \"url\" property" | |
| 102 | parseJSON _ = fail "MediaLink not an object" | |
| 92 | 103 | |
| 93 | 104 | instance ToJSON MediaLink where |
| 94 | 105 | toJSON (MediaLink o) = A.Object o |
| 95 | 106 | |
| 107 | -- | Access the underlying JSON object that represents a Media Link | |
| 96 | 108 | mlRest :: Lens' MediaLink A.Object |
| 97 | 109 | mlRest = makeLens fromMediaLink (\ o' m -> m { fromMediaLink = o' }) |
| 98 | 110 | |
| 111 | -- | A hint to the consumer about the length, in seconds, of the media | |
| 112 | -- resource identified by the url property. A media link MAY contain | |
| 113 | -- a "duration" property when the target resource is a time-based | |
| 114 | -- media item such as an audio or video. | |
| 99 | 115 | mlDuration :: Lens' MediaLink (Maybe Int) |
| 100 | 116 | mlDuration = makeAesonLensMb "duration" mlRest |
| 101 | 117 | |
| 118 | -- | A hint to the consumer about the height, in pixels, of the media | |
| 119 | -- resource identified by the url property. A media link MAY contain | |
| 120 | -- a @height@ property when the target resource is a visual media item | |
| 121 | -- such as an image, video or embeddable HTML page. | |
| 102 | 122 | mlHeight :: Lens' MediaLink (Maybe Int) |
| 103 | 123 | mlHeight = makeAesonLensMb "height" mlRest |
| 104 | 124 | |
| 125 | -- | A hint to the consumer about the width, in pixels, of the media | |
| 126 | -- resource identified by the url property. A media link MAY contain | |
| 127 | -- a @width@ property when the target resource is a visual media item | |
| 128 | -- such as an image, video or embeddable HTML page. | |
| 105 | 129 | mlWidth :: Lens' MediaLink (Maybe Int) |
| 106 | 130 | mlWidth = makeAesonLensMb "width" mlRest |
| 107 | 131 | |
| 132 | -- | The IRI of the media resource being linked. A media link MUST have a | |
| 133 | -- @url@ property. | |
| 108 | 134 | mlURL :: Lens' MediaLink Text |
| 109 | 135 | mlURL = makeAesonLens "url" mlRest |
| 110 | 136 | |
| 111 |
-- | Create a @MediaLink@ with just a @url@ property |
|
| 137 | -- | Create a @MediaLink@ with just a @url@ property, and all other | |
| 138 | -- properties undefined. | |
| 112 | 139 | makeMediaLink :: Text -> MediaLink |
| 113 | 140 | makeMediaLink url = MediaLink (HM.insert "url" (toJSON url) HM.empty) |
| 114 | 141 | |
| 115 |
-- | |
|
| 142 | -- | Within the specification, an 'Object' is a thing, real or | |
| 143 | -- imaginary, which participates in an activity. It may be the | |
| 144 | -- entity performing the activity, or the entity on which the | |
| 145 | -- activity was performed. An object consists of properties | |
| 146 | -- defined below. Certain object types may | |
| 147 | -- further refine the meaning of these properties, or they may | |
| 148 | -- define additional properties. | |
| 149 | -- | |
| 150 | -- To maintain this flexibility in the Haskell environment, an | |
| 151 | -- 'Object' is an opaque wrapper over an underlying JSON value, | |
| 152 | -- and the 'oRest' accessor can be used to access that underlying | |
| 153 | -- value. | |
| 116 | 154 | |
| 117 | 155 | data Object = Object { fromObject :: A.Object } deriving (Eq, Show) |
| 118 | 156 | |
| 119 | 157 | instance FromJSON Object where |
| 120 | 158 | parseJSON (A.Object o) = return (Object o) |
| 121 |
parseJSON _ = fail " |
|
| 159 | parseJSON _ = fail "Object not an object" | |
| 122 | 160 | |
| 123 | 161 | instance ToJSON Object where |
| 124 | 162 | toJSON (Object o) = A.Object o |
| 125 | 163 | |
| 164 | -- | Access the underlying JSON object that represents an 'Object' | |
| 126 | 165 | oRest :: Lens' Object A.Object |
| 127 | 166 | oRest = makeLens fromObject (\ o' m -> m { fromObject = o' }) |
| 128 | 167 | |
| 168 | -- | A collection of one or more additional, associated objects, similar | |
| 169 | -- to the concept of attached files in an email message. An object MAY | |
| 170 | -- have an attachments property whose value is a JSON Array of 'Object's. | |
| 129 | 171 | oAttachments :: Lens' Object (Maybe [Object]) |
| 130 | 172 | oAttachments = makeAesonLensMb "attachments" oRest |
| 131 | 173 | |
| 174 | -- | Describes the entity that created or authored the object. An object | |
| 175 | -- MAY contain a single author property whose value is an 'Object' of any | |
| 176 | -- type. Note that the author field identifies the entity that created | |
| 177 | -- the object and does not necessarily identify the entity that | |
| 178 | -- published the object. For instance, it may be the case that an | |
| 179 | -- object created by one person is posted and published to a system by | |
| 180 | -- an entirely different entity. | |
| 132 | 181 | oAuthor :: Lens' Object (Maybe Object) |
| 133 | 182 | oAuthor = makeAesonLensMb "author" oRest |
| 134 | 183 | |
| 184 | -- | Natural-language description of the object encoded as a single JSON | |
| 185 | -- String containing HTML markup. Visual elements such as thumbnail | |
| 186 | -- images MAY be included. An object MAY contain a @content@ property. | |
| 135 | 187 | oContent :: Lens' Object (Maybe Text) |
| 136 | 188 | oContent = makeAesonLensMb "content" oRest |
| 137 | 189 | |
| 190 | -- | A natural-language, human-readable and plain-text name for the | |
| 191 | -- object. HTML markup MUST NOT be included. An object MAY contain | |
| 192 | -- a @displayName@ property. If the object does not specify an @objectType@ | |
| 193 | -- property, the object SHOULD specify a @displayName@. | |
| 138 | 194 | oDisplayName :: Lens' Object (Maybe Text) |
| 139 | 195 | oDisplayName = makeAesonLensMb "displayName" oRest |
| 140 | 196 | |
| 197 | -- | A JSON Array of one or more absolute IRI's | |
| 198 | -- <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]> identifying | |
| 199 | -- objects that duplicate this object's content. An object SHOULD | |
| 200 | -- contain a @downstreamDuplicates@ property when there are known objects, | |
| 201 | -- possibly in a different system, that duplicate the content in this | |
| 202 | -- object. This MAY be used as a hint for consumers to use when | |
| 203 | -- resolving duplicates between objects received from different sources. | |
| 141 | 204 | oDownstreamDuplicates :: Lens' Object (Maybe [Text]) |
| 142 | 205 | oDownstreamDuplicates = makeAesonLensMb "downstreamDuplicates" oRest |
| 143 | 206 | |
| 207 | -- | Provides a permanent, universally unique identifier for the object in | |
| 208 | -- the form of an absolute IRI | |
| 209 | -- <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]>. An | |
| 210 | -- object SHOULD contain a single @id@ property. If an object does not | |
| 211 | -- contain an @id@ property, consumers MAY use the value of the @url@ | |
| 212 | -- property as a less-reliable, non-unique identifier. | |
| 213 | ||
| 144 | 214 | oId :: Lens' Object (Maybe Text) |
| 145 | 215 | oId = makeAesonLensMb "id" oRest |
| 146 | 216 | |
| 217 | -- | Description of a resource providing a visual representation of the | |
| 218 | -- object, intended for human consumption. An object MAY contain an | |
| 219 | -- @image@ property whose value is a 'MediaLink'. | |
| 147 | 220 | oImage :: Lens' Object (Maybe MediaLink) |
| 148 | 221 | oImage = makeAesonLensMb "image" oRest |
| 149 | 222 | |
| 223 | -- | Identifies the type of object. An object MAY contain an @objectType@ | |
| 224 | -- property whose value is a JSON String that is non-empty and matches | |
| 225 | -- either the "isegment-nz-nc" or the \"IRI\" production in | |
| 226 | -- <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]>. Note | |
| 227 | -- that the use of a relative reference other than a simple name is | |
| 228 | -- not allowed. If no @objectType@ property is contained, the object has | |
| 229 | -- no specific type. | |
| 150 | 230 | oObjectType :: (FromJSON o, ToJSON o) => Lens' Object (Maybe o) |
| 151 | 231 | oObjectType = makeAesonLensMb "objectType" oRest |
| 152 | 232 | |
| 233 | -- | The date and time at which the object was published. An object MAY | |
| 234 | -- contain a @published@ property. | |
| 153 | 235 | oPublished :: Lens' Object (Maybe DateTime) |
| 154 | 236 | oPublished = makeAesonLensMb "published" oRest |
| 155 | 237 | |
| 238 | -- | Natural-language summarization of the object encoded as a single | |
| 239 | -- JSON String containing HTML markup. Visual elements such as thumbnail | |
| 240 | -- images MAY be included. An activity MAY contain a @summary@ property. | |
| 156 | 241 | oSummary :: Lens' Object (Maybe Text) |
| 157 | 242 | oSummary = makeAesonLensMb "summary" oRest |
| 158 | 243 | |
| 244 | -- | The date and time at which a previously published object has been | |
| 245 | -- modified. An Object MAY contain an @updated@ property. | |
| 159 | 246 | oUpdated :: Lens' Object (Maybe DateTime) |
| 160 | 247 | oUpdated = makeAesonLensMb "updated" oRest |
| 161 | 248 | |
| 249 | -- | A JSON Array of one or more absolute IRI's | |
| 250 | -- <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]> identifying | |
| 251 | -- objects that duplicate this object's content. An object SHOULD contain | |
| 252 | -- an @upstreamDuplicates@ property when a publisher is knowingly | |
| 253 | -- duplicating with a new ID the content from another object. This MAY be | |
| 254 | -- used as a hint for consumers to use when resolving duplicates between | |
| 255 | -- objects received from different sources. | |
| 162 | 256 | oUpstreamDuplicates :: Lens' Object (Maybe [Text]) |
| 163 | 257 | oUpstreamDuplicates = makeAesonLensMb "upstreamDuplicates" oRest |
| 164 | 258 | |
| 259 | -- | An IRI <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]> | |
| 260 | -- identifying a resource providing an HTML representation of the | |
| 261 | -- object. An object MAY contain a url property | |
| 165 | 262 | oURL :: Lens' Object (Maybe Text) |
| 166 | 263 | oURL = makeAesonLensMb "url" oRest |
| 167 | 264 | |
| 169 | 266 | emptyObject :: Object |
| 170 | 267 | emptyObject = Object HM.empty |
| 171 | 268 | |
| 172 |
-- | |
|
| 269 | -- | In its simplest form, an 'Activity' consists of an @actor@, a @verb@, an | |
| 270 | -- @object@, and a @target@. It tells the story of a person performing an | |
| 271 | -- action on or with an object -- "Geraldine posted a photo to her | |
| 272 | -- album" or "John shared a video". In most cases these components | |
| 273 | -- will be explicit, but they may also be implied. | |
| 173 | 274 | |
| 174 | 275 | data Activity = Activity { fromActivity :: A.Object } deriving (Eq, Show) |
| 175 | 276 | |
| 182 | 283 | instance ToJSON Activity where |
| 183 | 284 | toJSON (Activity o) = A.Object o |
| 184 | 285 | |
| 286 | -- | Access the underlying JSON object that represents an 'Activity' | |
| 185 | 287 | acRest :: Lens' Activity A.Object |
| 186 | 288 | acRest = makeLens fromActivity (\ o' m -> m { fromActivity = o' }) |
| 187 | 289 | |
| 290 | -- | Describes the entity that performed the activity. An activity MUST | |
| 291 | -- contain one @actor@ property whose value is a single 'Object'. | |
| 188 | 292 | acActor :: Lens' Activity Object |
| 189 | 293 | acActor = makeAesonLens "actor" acRest |
| 190 | 294 | |
| 295 | -- | Natural-language description of the activity encoded as a single | |
| 296 | -- JSON String containing HTML markup. Visual elements such as | |
| 297 | -- thumbnail images MAY be included. An activity MAY contain a | |
| 298 | -- @content@ property. | |
| 191 | 299 | acContent :: Lens' Activity (Maybe Text) |
| 192 | 300 | acContent = makeAesonLensMb "content" acRest |
| 193 | 301 | |
| 302 | -- | Describes the application that generated the activity. An activity | |
| 303 | -- MAY contain a @generator@ property whose value is a single 'Object'. | |
| 194 | 304 | acGenerator :: Lens' Activity (Maybe Object) |
| 195 | 305 | acGenerator = makeAesonLens "generator" acRest |
| 196 | 306 | |
| 307 | -- | Description of a resource providing a visual representation of the | |
| 308 | -- object, intended for human consumption. The image SHOULD have an | |
| 309 | -- aspect ratio of one (horizontal) to one (vertical) and SHOULD be | |
| 310 | -- suitable for presentation at a small size. An activity MAY have | |
| 311 | -- an @icon@ property. | |
| 197 | 312 | acIcon :: Lens' Activity (Maybe MediaLink) |
| 198 | 313 | acIcon = makeAesonLensMb "icon" acRest |
| 199 | 314 | |
| 315 | -- | Provides a permanent, universally unique identifier for the activity | |
| 316 | -- in the form of an absolute IRI | |
| 317 | -- <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]>. An | |
| 318 | -- activity SHOULD contain a single @id@ property. If an activity does | |
| 319 | -- not contain an @id@ property, consumers MAY use the value of the | |
| 320 | -- @url@ property as a less-reliable, non-unique identifier. | |
| 200 | 321 | acId :: Lens' Activity (Maybe Text) |
| 201 | 322 | acId = makeAesonLensMb "id" acRest |
| 202 | 323 | |
| 324 | -- | Describes the primary object of the activity. For instance, in the | |
| 325 | -- activity, "John saved a movie to his wishlist", the object of the | |
| 326 | -- activity is "movie". An activity SHOULD contain an @object@ property | |
| 327 | -- whose value is a single 'Object'. If the @object@ property is not | |
| 328 | -- contained, the primary object of the activity MAY be implied by | |
| 329 | -- context. | |
| 203 | 330 | acObject :: Lens' Activity (Maybe Object) |
| 204 | 331 | acObject = makeAesonLensMb "object" acRest |
| 205 | 332 | |
| 333 | -- | The date and time at which the activity was published. An activity | |
| 334 | -- MUST contain a @published@ property. | |
| 206 | 335 | acPublished :: Lens' Activity DateTime |
| 207 | 336 | acPublished = makeAesonLens "published" acRest |
| 208 | 337 | |
| 338 | -- | Describes the application that published the activity. Note that this | |
| 339 | -- is not necessarily the same entity that generated the activity. An | |
| 340 | -- activity MAY contain a @provider@ property whose value is a | |
| 341 | -- single 'Object'. | |
| 209 | 342 | acProvider :: Lens' Activity (Maybe Object) |
| 210 | 343 | acProvider = makeAesonLensMb "provider" acRest |
| 211 | 344 | |
| 345 | -- | Describes the target of the activity. The precise meaning of the | |
| 346 | -- activity's target is dependent on the activities verb, but will | |
| 347 | -- often be the object the English preposition "to". For instance, in | |
| 348 | -- the activity, "John saved a movie to his wishlist", the target of | |
| 349 | -- the activity is "wishlist". The activity target MUST NOT be used | |
| 350 | -- to identity an indirect object that is not a target of the | |
| 351 | -- activity. An activity MAY contain a @target@ property whose value | |
| 352 | -- is a single 'Object'. | |
| 212 | 353 | acTarget :: Lens' Activity (Maybe Object) |
| 213 | 354 | acTarget = makeAesonLensMb "target" acRest |
| 214 | 355 | |
| 356 | -- | Natural-language title or headline for the activity encoded as a | |
| 357 | -- single JSON String containing HTML markup. An activity MAY contain | |
| 358 | -- a @title@ property. | |
| 215 | 359 | acTitle :: Lens' Activity (Maybe Text) |
| 216 | 360 | acTitle = makeAesonLensMb "title" acRest |
| 217 | 361 | |
| 362 | -- | The date and time at which a previously published activity has | |
| 363 | -- been modified. An Activity MAY contain an @updated@ property. | |
| 218 | 364 | acUpdated :: Lens' Activity (Maybe DateTime) |
| 219 | 365 | acUpdated = makeAesonLensMb "updated" acRest |
| 220 | 366 | |
| 367 | -- | An IRI <http://www.ietf.org/rfc/rfc3987.txt RFC3987> | |
| 368 | -- identifying a resource providing an HTML representation of the | |
| 369 | -- activity. An activity MAY contain a @url@ property. | |
| 221 | 370 | acURL :: Lens' Activity (Maybe Text) |
| 222 | 371 | acURL = makeAesonLensMb "url" acRest |
| 223 | 372 | |
| 373 | -- | Identifies the action that the activity describes. An activity SHOULD | |
| 374 | -- contain a verb property whose value is a JSON String that is | |
| 375 | -- non-empty and matches either the \"isegment-nz-nc\" or the | |
| 376 | -- \"IRI\" production in <http://www.ietf.org/rfc/rfc3987.txt [RFC3987]>. | |
| 377 | -- Note that the use of a relative | |
| 378 | -- reference other than a simple name is not allowed. If the @verb@ is | |
| 379 | -- not specified, or if the value is null, the @verb@ is | |
| 380 | -- assumed to be \"post\". | |
| 224 | 381 | acVerb :: (FromJSON v, ToJSON v) => Lens' Activity (Maybe v) |
| 225 | 382 | acVerb = makeAesonLensMb "verb" acRest |
| 226 | 383 | |
| 238 | 395 | asObject :: Activity -> Object |
| 239 | 396 | asObject act = Object (fromActivity act) |
| 240 | 397 | |
| 241 |
-- | |
|
| 398 | -- | A "collection" is a generic list of 'Object's of any object type. | |
| 399 | -- The @objectType@ of each item in the collection MAY be omitted if | |
| 400 | -- the type of object can be established through context. The collection | |
| 401 | -- is used primarily as the root of an Activity Streams document as described | |
| 402 | -- in Section 4, | |
| 403 | -- but can be used as the value of extension properties in a variety of | |
| 404 | -- situations. | |
| 242 | 405 | |
| 243 | 406 | data Collection = Collection { fromCollection :: A.Object } deriving (Eq, Show) |
| 244 | 407 | |
| 249 | 412 | instance ToJSON Collection where |
| 250 | 413 | toJSON (Collection o) = A.Object o |
| 251 | 414 | |
| 415 | -- | Access the underlying JSON object that represents a 'Collection' | |
| 252 | 416 | cRest :: Lens' Collection A.Object |
| 253 | 417 | cRest = makeLens fromCollection (\ o' m -> m { fromCollection = o' }) |
| 254 | 418 | |
| 419 | -- | Non-negative integer specifying the total number of activities | |
| 420 | -- within the stream. The Stream serialization MAY contain a | |
| 421 | -- @totalItems@ property. (NOTE: there is a typo in the original | |
| 422 | -- specification, in which it inconsistently refers to this as | |
| 423 | -- either @totalItems@ or @count@.) | |
| 255 | 424 | cTotalItems :: Lens' Collection (Maybe Int) |
| 256 | 425 | cTotalItems = makeAesonLensMb "totalItems" cRest |
| 257 | 426 | |
| 427 | -- | An array containing a listing of 'Object's of any object type. | |
| 428 | -- If used in combination with the @url@ property, the @items@ array | |
| 429 | -- can be used to provide a subset of the objects that may be | |
| 430 | -- found in the resource identified by the @url@. | |
| 258 | 431 | cItems :: Lens' Collection (Maybe [Object]) |
| 259 | 432 | cItems = makeAesonLensMb "items" cRest |
| 260 | 433 | |
| 434 | -- | An IRI <http://activitystrea.ms/specs/json/1.0/#RFC3987 [RFC3987]> | |
| 435 | -- referencing a JSON document containing the full | |
| 436 | -- listing of objects in the collection. | |
| 261 | 437 | cURL :: Lens' Collection (Maybe Text) |
| 262 | 438 | cURL = makeAesonLensMb "url" cRest |
| 263 | 439 | |