Add spec version control for API endpoints
parent
e49a0e3dc3
commit
3fdd25d6d6
|
@ -1,4 +1,7 @@
|
||||||
module Internal.Api.Api exposing (TaskChain, request)
|
module Internal.Api.Api exposing
|
||||||
|
( TaskChain, request
|
||||||
|
, VersionControl, startWithVersion, startWithUnstableFeature, forVersion, sameForVersion, forUnstableFeature, versionChain
|
||||||
|
)
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
|
|
||||||
|
@ -12,14 +15,25 @@ implementation simple and understandable.
|
||||||
|
|
||||||
@docs TaskChain, request
|
@docs TaskChain, request
|
||||||
|
|
||||||
|
|
||||||
|
## Spec versions
|
||||||
|
|
||||||
|
To respect spec versions, there is often a variety of ways to communicate with
|
||||||
|
the homeserver. For this reason, users can differentiate spec versions using
|
||||||
|
these functions.
|
||||||
|
|
||||||
|
@docs VersionControl, startWithVersion, startWithUnstableFeature, forVersion, sameForVersion, forUnstableFeature, versionChain
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import Internal.Api.Chain as C
|
import Internal.Api.Chain as C
|
||||||
import Internal.Api.Request as R
|
import Internal.Api.Request as R
|
||||||
import Internal.Config.Log exposing (log)
|
import Internal.Config.Log exposing (Log, log)
|
||||||
import Internal.Tools.Json as Json
|
import Internal.Tools.Json as Json
|
||||||
import Internal.Values.Context exposing (APIContext)
|
import Internal.Values.Context as Context exposing (APIContext, Versions)
|
||||||
import Internal.Values.Vault as V
|
import Internal.Values.Vault as V
|
||||||
|
import Recursion
|
||||||
|
import Set
|
||||||
|
|
||||||
|
|
||||||
{-| A TaskChain helps create a chain of HTTP requests.
|
{-| A TaskChain helps create a chain of HTTP requests.
|
||||||
|
@ -32,10 +46,11 @@ type alias TaskChain ph1 ph2 =
|
||||||
-}
|
-}
|
||||||
request :
|
request :
|
||||||
{ attributes : List (R.Attribute { ph1 | baseUrl : () })
|
{ attributes : List (R.Attribute { ph1 | baseUrl : () })
|
||||||
, coder : Json.Coder V.VaultUpdate
|
, coder : Json.Coder returnValue
|
||||||
, contextChange : V.VaultUpdate -> (APIContext { ph1 | baseUrl : () } -> APIContext { ph2 | baseUrl : () })
|
, contextChange : V.VaultUpdate -> (APIContext { ph1 | baseUrl : () } -> APIContext { ph2 | baseUrl : () })
|
||||||
, method : String
|
, method : String
|
||||||
, path : List String
|
, path : List String
|
||||||
|
, toUpdate : returnValue -> ( V.VaultUpdate, List Log )
|
||||||
}
|
}
|
||||||
-> TaskChain ph1 ph2
|
-> TaskChain ph1 ph2
|
||||||
request data =
|
request data =
|
||||||
|
@ -61,4 +76,120 @@ request data =
|
||||||
}
|
}
|
||||||
|> R.withAttributes data.attributes
|
|> R.withAttributes data.attributes
|
||||||
, toContextChange = data.contextChange
|
, toContextChange = data.contextChange
|
||||||
|
, toUpdate = data.toUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| This type allows different definitions for different spec versions,
|
||||||
|
allowing the Elm SDK to communicate differently to the server depending on
|
||||||
|
how up-to-date the server is.
|
||||||
|
-}
|
||||||
|
type VersionControl a ph1 ph2
|
||||||
|
= VC
|
||||||
|
{ name : VersionType
|
||||||
|
, chain : a -> TaskChain (WithV ph1) (WithV ph2)
|
||||||
|
, prev : Maybe (VersionControl a ph1 ph2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type VersionType
|
||||||
|
= SpecVersion String
|
||||||
|
| UnstableFeature String
|
||||||
|
|
||||||
|
|
||||||
|
type alias WithV ph =
|
||||||
|
{ ph | versions : () }
|
||||||
|
|
||||||
|
|
||||||
|
{-| Start with a given spec version supporting a given API endpoint.
|
||||||
|
-}
|
||||||
|
startWithVersion : String -> (a -> TaskChain (WithV ph1) (WithV ph2)) -> VersionControl a ph1 ph2
|
||||||
|
startWithVersion name chain =
|
||||||
|
VC
|
||||||
|
{ name = SpecVersion name
|
||||||
|
, chain = chain
|
||||||
|
, prev = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Start with a given unstable feature supporting a given API endpoint.
|
||||||
|
-}
|
||||||
|
startWithUnstableFeature : String -> (a -> TaskChain (WithV ph1) (WithV ph2)) -> VersionControl a ph1 ph2
|
||||||
|
startWithUnstableFeature name chain =
|
||||||
|
VC
|
||||||
|
{ name = UnstableFeature name
|
||||||
|
, chain = chain
|
||||||
|
, prev = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Add a new unstable feature that supports a different version of the API endpoint.
|
||||||
|
-}
|
||||||
|
forUnstableFeature : String -> (a -> TaskChain (WithV ph1) (WithV ph2)) -> VersionControl a ph1 ph2 -> VersionControl a ph1 ph2
|
||||||
|
forUnstableFeature name chain prev =
|
||||||
|
VC
|
||||||
|
{ name = UnstableFeature name
|
||||||
|
, chain = chain
|
||||||
|
, prev = Just prev
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Add a new spec version that supports a different version of the API endpoint.
|
||||||
|
-}
|
||||||
|
forVersion : String -> (a -> TaskChain (WithV ph1) (WithV ph2)) -> VersionControl a ph1 ph2 -> VersionControl a ph1 ph2
|
||||||
|
forVersion name chain prev =
|
||||||
|
VC
|
||||||
|
{ name = SpecVersion name
|
||||||
|
, chain = chain
|
||||||
|
, prev = Just prev
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Add another spec version that has the API endpoint defined the same as the previous API endpoint.
|
||||||
|
-}
|
||||||
|
sameForVersion : String -> VersionControl a ph1 ph2 -> VersionControl a ph1 ph2
|
||||||
|
sameForVersion name (VC data) =
|
||||||
|
VC
|
||||||
|
{ name = SpecVersion name
|
||||||
|
, chain = data.chain
|
||||||
|
, prev = Just (VC data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
supportedVersion : Versions -> VersionType -> Bool
|
||||||
|
supportedVersion { versions, unstableFeatures } name =
|
||||||
|
case name of
|
||||||
|
SpecVersion n ->
|
||||||
|
List.member n versions
|
||||||
|
|
||||||
|
UnstableFeature n ->
|
||||||
|
Set.member n unstableFeatures
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- NOTE: Interesting detail! For some reason, I cannot add the `context`
|
||||||
|
-- NOTE: variable to the top line of the defined input values!
|
||||||
|
-- NOTE: Maybe this is a bug?
|
||||||
|
|
||||||
|
|
||||||
|
{-| Once you are done, turn a VersionControl type into a Task Chain.
|
||||||
|
-}
|
||||||
|
versionChain : VersionControl a ph1 ph2 -> a -> TaskChain (WithV ph1) (WithV ph2)
|
||||||
|
versionChain vc input =
|
||||||
|
\context ->
|
||||||
|
case Context.getVersions context of
|
||||||
|
versions ->
|
||||||
|
Recursion.runRecursion
|
||||||
|
(\mvc ->
|
||||||
|
case mvc of
|
||||||
|
Nothing ->
|
||||||
|
Recursion.base (C.fail R.NoSupportedVersion context)
|
||||||
|
|
||||||
|
Just (VC data) ->
|
||||||
|
if supportedVersion versions data.name then
|
||||||
|
Recursion.base (data.chain input context)
|
||||||
|
|
||||||
|
else
|
||||||
|
Recursion.recurse data.prev
|
||||||
|
)
|
||||||
|
(Just vc)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module Internal.Api.Chain exposing
|
module Internal.Api.Chain exposing
|
||||||
( TaskChain, CompleteChain
|
( TaskChain, CompleteChain
|
||||||
, IdemChain, toTask
|
, IdemChain, toTask
|
||||||
|
, fail, succeed
|
||||||
)
|
)
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
|
@ -23,6 +24,11 @@ avoid leaking values passing through the API in unexpected ways.
|
||||||
|
|
||||||
@docs IdemChain, toTask
|
@docs IdemChain, toTask
|
||||||
|
|
||||||
|
|
||||||
|
## Operations
|
||||||
|
|
||||||
|
@docs fail, succeed
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import Internal.Config.Log exposing (Log)
|
import Internal.Config.Log exposing (Log)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module Internal.Api.Request exposing
|
module Internal.Api.Request exposing
|
||||||
( ApiCall, ApiPlan, Attribute, callAPI, withAttributes, toChain
|
( ApiCall, ApiPlan, Attribute, callAPI, withAttributes, toChain
|
||||||
, Request, Error(..)
|
, Request, Error(..)
|
||||||
, accessToken, withTransactionId, timeout
|
, accessToken, withTransactionId, timeout, onStatusCode
|
||||||
, fullBody, bodyBool, bodyInt, bodyString, bodyValue, bodyOpBool, bodyOpInt, bodyOpString, bodyOpValue
|
, fullBody, bodyBool, bodyInt, bodyString, bodyValue, bodyOpBool, bodyOpInt, bodyOpString, bodyOpValue
|
||||||
, queryBool, queryInt, queryString, queryOpBool, queryOpInt, queryOpString
|
, queryBool, queryInt, queryString, queryOpBool, queryOpInt, queryOpString
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,7 @@ Sometimes, APIs might fail. As a result, you may receive an error.
|
||||||
|
|
||||||
### General attributes
|
### General attributes
|
||||||
|
|
||||||
@docs accessToken, withTransactionId, timeout
|
@docs accessToken, withTransactionId, timeout, onStatusCode
|
||||||
|
|
||||||
|
|
||||||
### Body
|
### Body
|
||||||
|
@ -98,7 +98,9 @@ type ContextAttr
|
||||||
-}
|
-}
|
||||||
type Error
|
type Error
|
||||||
= InternetException Http.Error
|
= InternetException Http.Error
|
||||||
|
| NoSupportedVersion
|
||||||
| ServerReturnsBadJSON String
|
| ServerReturnsBadJSON String
|
||||||
|
| ServerReturnsError String Json.Value
|
||||||
|
|
||||||
|
|
||||||
{-| Ordinary shape of an HTTP request.
|
{-| Ordinary shape of an HTTP request.
|
||||||
|
@ -396,10 +398,35 @@ getUrl { attributes, baseUrl, path } =
|
||||||
(getQueryParams attributes)
|
(getQueryParams attributes)
|
||||||
|
|
||||||
|
|
||||||
|
{-| When the HTTP request cannot be deciphered but the status code is known,
|
||||||
|
return with a given default error.
|
||||||
|
-}
|
||||||
|
onStatusCode : Int -> String -> Attribute a
|
||||||
|
onStatusCode code err _ =
|
||||||
|
StatusCodeResponse code
|
||||||
|
( err
|
||||||
|
|> E.string
|
||||||
|
|> Tuple.pair "errcode"
|
||||||
|
|> List.singleton
|
||||||
|
|> E.object
|
||||||
|
|> ServerReturnsError err
|
||||||
|
, String.concat
|
||||||
|
-- TODO: Move to Internal.Config.Text
|
||||||
|
[ "Received an invalid HTTP response from Matrix server "
|
||||||
|
, "but managed to decode it using the status code "
|
||||||
|
, String.fromInt code
|
||||||
|
, ": Default to errcode "
|
||||||
|
, err
|
||||||
|
]
|
||||||
|
|> log.warn
|
||||||
|
|> List.singleton
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
{-| Resolve the response of a Matrix API call.
|
{-| Resolve the response of a Matrix API call.
|
||||||
-}
|
-}
|
||||||
rawApiCallResolver : Json.Coder a -> Dict.Dict Int ( Error, List Log ) -> Http.Resolver ( Error, List Log ) ( a, List Log )
|
rawApiCallResolver : Json.Coder a -> (a -> ( b, List Log )) -> Dict.Dict Int ( Error, List Log ) -> Http.Resolver ( Error, List Log ) ( b, List Log )
|
||||||
rawApiCallResolver coder statusCodeErrors =
|
rawApiCallResolver coder f statusCodeErrors =
|
||||||
Http.stringResolver
|
Http.stringResolver
|
||||||
(\response ->
|
(\response ->
|
||||||
case response of
|
case response of
|
||||||
|
@ -427,12 +454,30 @@ rawApiCallResolver coder statusCodeErrors =
|
||||||
Http.BadStatus_ metadata body ->
|
Http.BadStatus_ metadata body ->
|
||||||
statusCodeErrors
|
statusCodeErrors
|
||||||
|> Dict.get metadata.statusCode
|
|> Dict.get metadata.statusCode
|
||||||
|> decodeServerResponse (Json.decode coder) body
|
|> decodeServerResponse
|
||||||
|
(Json.decode coder
|
||||||
|
|> D.map
|
||||||
|
(\( u, l ) ->
|
||||||
|
case f u of
|
||||||
|
( u2, l2 ) ->
|
||||||
|
( u2, List.append l l2 )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
body
|
||||||
|
|
||||||
Http.GoodStatus_ metadata body ->
|
Http.GoodStatus_ metadata body ->
|
||||||
statusCodeErrors
|
statusCodeErrors
|
||||||
|> Dict.get metadata.statusCode
|
|> Dict.get metadata.statusCode
|
||||||
|> decodeServerResponse (Json.decode coder) body
|
|> decodeServerResponse
|
||||||
|
(Json.decode coder
|
||||||
|
|> D.map
|
||||||
|
(\( u, l ) ->
|
||||||
|
case f u of
|
||||||
|
( u2, l2 ) ->
|
||||||
|
( u2, List.append l l2 )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
body
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -511,9 +556,10 @@ timeout f _ =
|
||||||
-}
|
-}
|
||||||
toChain :
|
toChain :
|
||||||
{ logHttp : Request ( Error, List Log ) ( update, List Log ) -> ( update, List Log )
|
{ logHttp : Request ( Error, List Log ) ( update, List Log ) -> ( update, List Log )
|
||||||
, coder : Json.Coder update
|
, coder : Json.Coder httpOut
|
||||||
, request : ApiPlan ph1
|
, request : ApiPlan ph1
|
||||||
, toContextChange : update -> (APIContext ph1 -> APIContext ph2)
|
, toContextChange : update -> (APIContext ph1 -> APIContext ph2)
|
||||||
|
, toUpdate : httpOut -> ( update, List Log )
|
||||||
}
|
}
|
||||||
-> C.TaskChain Error update ph1 ph2
|
-> C.TaskChain Error update ph1 ph2
|
||||||
toChain data apiContext =
|
toChain data apiContext =
|
||||||
|
@ -526,7 +572,7 @@ toChain data apiContext =
|
||||||
, headers = getHeaders call.attributes
|
, headers = getHeaders call.attributes
|
||||||
, url = getUrl call
|
, url = getUrl call
|
||||||
, body = Http.jsonBody (getBody call.attributes)
|
, body = Http.jsonBody (getBody call.attributes)
|
||||||
, resolver = rawApiCallResolver data.coder (getStatusCodes call.attributes)
|
, resolver = rawApiCallResolver data.coder data.toUpdate (getStatusCodes call.attributes)
|
||||||
, timeout = getTimeout call.attributes
|
, timeout = getTimeout call.attributes
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
module Internal.Api.Task exposing (Task, run)
|
module Internal.Api.Task exposing (Task, run)
|
||||||
{-| # Task module
|
|
||||||
|
{-|
|
||||||
|
|
||||||
|
|
||||||
|
# Task module
|
||||||
|
|
||||||
This module is used to define how API calls are made. These completed API tasks
|
This module is used to define how API calls are made. These completed API tasks
|
||||||
can be directly converted to Cmd types that the end user of the SDK can access.
|
can be directly converted to Cmd types that the end user of the SDK can access.
|
||||||
|
@ -8,9 +12,11 @@ These tasks do not affect the `Vault` directly, but instead, return a
|
||||||
`VaultUpdate` type that the user can apply to keep their `Vault` type
|
`VaultUpdate` type that the user can apply to keep their `Vault` type
|
||||||
up-to-date.
|
up-to-date.
|
||||||
|
|
||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
@docs Task, run
|
@docs Task, run
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import Internal.Api.Chain as C
|
import Internal.Api.Chain as C
|
||||||
|
|
|
@ -247,6 +247,7 @@ fields :
|
||||||
{ context :
|
{ context :
|
||||||
{ accessToken : Desc
|
{ accessToken : Desc
|
||||||
, baseUrl : Desc
|
, baseUrl : Desc
|
||||||
|
, experimental : Desc
|
||||||
, password : Desc
|
, password : Desc
|
||||||
, refreshToken : Desc
|
, refreshToken : Desc
|
||||||
, username : Desc
|
, username : Desc
|
||||||
|
@ -329,6 +330,9 @@ fields =
|
||||||
, baseUrl =
|
, baseUrl =
|
||||||
[ "The base URL of the Matrix server."
|
[ "The base URL of the Matrix server."
|
||||||
]
|
]
|
||||||
|
, experimental =
|
||||||
|
[ "Experimental features supported by the homeserver."
|
||||||
|
]
|
||||||
, password =
|
, password =
|
||||||
[ "The user's password for authentication purposes."
|
[ "The user's password for authentication purposes."
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Internal.Values.Context exposing
|
||||||
, setAccessToken, getAccessToken
|
, setAccessToken, getAccessToken
|
||||||
, setBaseUrl, getBaseUrl
|
, setBaseUrl, getBaseUrl
|
||||||
, setTransaction, getTransaction
|
, setTransaction, getTransaction
|
||||||
, setVersions, getVersions
|
, Versions, setVersions, getVersions
|
||||||
)
|
)
|
||||||
|
|
||||||
{-| The Context is the set of variables that the user (mostly) cannot control.
|
{-| The Context is the set of variables that the user (mostly) cannot control.
|
||||||
|
@ -45,13 +45,14 @@ information that can be inserted.
|
||||||
|
|
||||||
### Versions
|
### Versions
|
||||||
|
|
||||||
@docs setVersions, getVersions
|
@docs Versions, setVersions, getVersions
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import Internal.Config.Leaks as L
|
import Internal.Config.Leaks as L
|
||||||
import Internal.Config.Text as Text
|
import Internal.Config.Text as Text
|
||||||
import Internal.Tools.Json as Json
|
import Internal.Tools.Json as Json
|
||||||
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
{-| The Context type stores all the information in the Vault. This data type is
|
{-| The Context type stores all the information in the Vault. This data type is
|
||||||
|
@ -60,6 +61,7 @@ static and hence can be passed on easily.
|
||||||
type alias Context =
|
type alias Context =
|
||||||
{ accessToken : Maybe String
|
{ accessToken : Maybe String
|
||||||
, baseUrl : Maybe String
|
, baseUrl : Maybe String
|
||||||
|
, experimental : Maybe (Set String)
|
||||||
, password : Maybe String
|
, password : Maybe String
|
||||||
, refreshToken : Maybe String
|
, refreshToken : Maybe String
|
||||||
, username : Maybe String
|
, username : Maybe String
|
||||||
|
@ -78,10 +80,14 @@ type APIContext ph
|
||||||
, baseUrl : String
|
, baseUrl : String
|
||||||
, context : Context
|
, context : Context
|
||||||
, transaction : String
|
, transaction : String
|
||||||
, versions : List String
|
, versions : Versions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias Versions =
|
||||||
|
{ versions : List String, unstableFeatures : Set String }
|
||||||
|
|
||||||
|
|
||||||
{-| Create an unformatted APIContext type.
|
{-| Create an unformatted APIContext type.
|
||||||
-}
|
-}
|
||||||
apiFormat : Context -> APIContext {}
|
apiFormat : Context -> APIContext {}
|
||||||
|
@ -91,7 +97,10 @@ apiFormat context =
|
||||||
, baseUrl = context.baseUrl |> Maybe.withDefault L.baseUrl
|
, baseUrl = context.baseUrl |> Maybe.withDefault L.baseUrl
|
||||||
, context = context
|
, context = context
|
||||||
, transaction = context.transaction |> Maybe.withDefault L.transaction
|
, transaction = context.transaction |> Maybe.withDefault L.transaction
|
||||||
, versions = context.versions |> Maybe.withDefault L.versions
|
, versions =
|
||||||
|
{ versions = context.versions |> Maybe.withDefault L.versions
|
||||||
|
, unstableFeatures = context.experimental |> Maybe.withDefault Set.empty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +108,7 @@ apiFormat context =
|
||||||
-}
|
-}
|
||||||
coder : Json.Coder Context
|
coder : Json.Coder Context
|
||||||
coder =
|
coder =
|
||||||
Json.object7
|
Json.object8
|
||||||
{ name = Text.docs.context.name
|
{ name = Text.docs.context.name
|
||||||
, description = Text.docs.context.description
|
, description = Text.docs.context.description
|
||||||
, init = Context
|
, init = Context
|
||||||
|
@ -118,6 +127,13 @@ coder =
|
||||||
, coder = Json.string
|
, coder = Json.string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
(Json.field.optional.value
|
||||||
|
{ fieldName = "experimental"
|
||||||
|
, toField = .experimental
|
||||||
|
, description = Text.fields.context.experimental
|
||||||
|
, coder = Json.set Json.string
|
||||||
|
}
|
||||||
|
)
|
||||||
(Json.field.optional.value
|
(Json.field.optional.value
|
||||||
{ fieldName = "password"
|
{ fieldName = "password"
|
||||||
, toField = .password
|
, toField = .password
|
||||||
|
@ -175,6 +191,7 @@ init : Context
|
||||||
init =
|
init =
|
||||||
{ accessToken = Nothing
|
{ accessToken = Nothing
|
||||||
, baseUrl = Nothing
|
, baseUrl = Nothing
|
||||||
|
, experimental = Nothing
|
||||||
, refreshToken = Nothing
|
, refreshToken = Nothing
|
||||||
, password = Nothing
|
, password = Nothing
|
||||||
, username = Nothing
|
, username = Nothing
|
||||||
|
@ -227,13 +244,13 @@ setTransaction value (APIContext c) =
|
||||||
|
|
||||||
{-| Get an inserted versions list.
|
{-| Get an inserted versions list.
|
||||||
-}
|
-}
|
||||||
getVersions : APIContext { a | versions : () } -> List String
|
getVersions : APIContext { a | versions : () } -> Versions
|
||||||
getVersions (APIContext c) =
|
getVersions (APIContext c) =
|
||||||
c.versions
|
c.versions
|
||||||
|
|
||||||
|
|
||||||
{-| Insert a versions list into the APIContext.
|
{-| Insert a versions list into the APIContext.
|
||||||
-}
|
-}
|
||||||
setVersions : List String -> APIContext a -> APIContext { a | versions : () }
|
setVersions : Versions -> APIContext a -> APIContext { a | versions : () }
|
||||||
setVersions value (APIContext c) =
|
setVersions value (APIContext c) =
|
||||||
APIContext { c | versions = value }
|
APIContext { c | versions = value }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Internal.Values.Room exposing
|
module Internal.Values.Room exposing
|
||||||
( Room, init
|
( Room, init
|
||||||
, RoomUpdate, update
|
, RoomUpdate(..), update
|
||||||
, Batch, addBatch, addSync, addEvents, mostRecentEvents
|
, Batch, addBatch, addSync, addEvents, mostRecentEvents
|
||||||
, getAccountData, setAccountData
|
, getAccountData, setAccountData
|
||||||
, coder, encode, decode
|
, coder, encode, decode
|
||||||
|
@ -56,6 +56,7 @@ import Internal.Tools.Json as Json
|
||||||
import Internal.Values.Event as Event exposing (Event)
|
import Internal.Values.Event as Event exposing (Event)
|
||||||
import Internal.Values.StateManager as StateManager exposing (StateManager)
|
import Internal.Values.StateManager as StateManager exposing (StateManager)
|
||||||
import Internal.Values.Timeline as Timeline exposing (Timeline)
|
import Internal.Values.Timeline as Timeline exposing (Timeline)
|
||||||
|
import Internal.Values.User as User exposing (User)
|
||||||
import Json.Encode as E
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +82,9 @@ type alias Room =
|
||||||
from the Matrix API.
|
from the Matrix API.
|
||||||
-}
|
-}
|
||||||
type RoomUpdate
|
type RoomUpdate
|
||||||
= AddSync Batch
|
= AddEvent Event
|
||||||
|
| AddSync Batch
|
||||||
|
| Invite User
|
||||||
| More (List RoomUpdate)
|
| More (List RoomUpdate)
|
||||||
| SetAccountData String Json.Value
|
| SetAccountData String Json.Value
|
||||||
|
|
||||||
|
@ -245,9 +248,17 @@ setAccountData key value room =
|
||||||
update : RoomUpdate -> Room -> Room
|
update : RoomUpdate -> Room -> Room
|
||||||
update ru room =
|
update ru room =
|
||||||
case ru of
|
case ru of
|
||||||
|
AddEvent _ ->
|
||||||
|
-- TODO: Add event
|
||||||
|
room
|
||||||
|
|
||||||
AddSync batch ->
|
AddSync batch ->
|
||||||
addSync batch room
|
addSync batch room
|
||||||
|
|
||||||
|
Invite user ->
|
||||||
|
-- TODO: Invite user
|
||||||
|
room
|
||||||
|
|
||||||
More items ->
|
More items ->
|
||||||
List.foldl update room items
|
List.foldl update room items
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue