@@ -12,22 +12,28 @@ module Supabase.Supabase
12 , ResultError
12 , ResultError
14 , SessionData
14 , SessionData
17 , class Equals
19 , class Equals
18 , class Select
20 , class Select
22 , getSession
25 , getSession
24 , onAuthStateChange
28 , onAuthStateChange
27 , signInWithOtp
33 , signInWithOtp
34+ , signInWithOtpOptions
@@ -35,25 +41,28 @@ module Supabase.Supabase
35import Prelude
41import Prelude
37import Control.Promise (Promise)
43import Control.Promise (Promise)
38−import Control.Promise as Promise
44+import Data.Either (Either(..))
39import Data.Function.Uncurried (Fn2, Fn3, runFn2, runFn3)
45import Data.Function.Uncurried (Fn2, Fn3, runFn2, runFn3)
40−import Data.Maybe (Maybe)
46+import Data.Maybe (Maybe(..))
41import Data.Nullable (Nullable)
47import Data.Nullable (Nullable)
42−import Data.Nullable as Nullable
43import Data.Tuple (Tuple(..))
48import Data.Tuple (Tuple(..))
44import Effect (Effect)
49import Effect (Effect)
45import Effect.Aff (Aff, Error)
50import Effect.Aff (Aff, Error)
51+import Effect.Exception (error)
46−import Effect.Uncurried (EffectFn1, mkEffectFn1)
52+import Effect.Uncurried (EffectFn1, EffectFn3, mkEffectFn1, runEffectFn3)
48−import Fetch.Core.Response as YogaJson.Core
49−import Fetch.Internal.Response as FetchInternalResponse
50import Foreign (Foreign)
53import Foreign (Foreign)
54+import Prim.Row (class Union)
51−import Supabase.Types (Client)
55+import Supabase.Types (Channel, ChannelName, Client)
52import Type.Function (type ($))
56import Type.Function (type ($))
53import Type.Row (type (+))
57import Type.Row (type (+))
58+import Yoga.JSON (class ReadForeign, class WriteForeign, writeImpl)
60+import Fetch.Internal.Response as FetchInternalResponse
61+import Data.Nullable as Nullable
62+import Control.Promise as Promise
54import Supabase.Util as Util
63import Supabase.Util as Util
55import Yoga.JSON (class ReadForeign, class WriteForeign, write) as YogaJson
64import Yoga.JSON (class ReadForeign, class WriteForeign, write) as YogaJson
56−import Yoga.JSON (class ReadForeign, class WriteForeign, writeImpl)
65+import Fetch.Core.Response as YogaJson.Core
58foreign import data QueryBuilder :: Type
67foreign import data QueryBuilder :: Type
59foreign import data FilterBuilder :: Type
68foreign import data FilterBuilder :: Type
@@ -91,7 +100,7 @@ foreign import selectQueryImpl :: QueryBuilder -> String -> FilterBuilder
92foreign import selectQueryWithCountImpl :: QueryBuilder -> String -> String -> FilterBuilder
101foreign import selectQueryWithCountImpl :: QueryBuilder -> String -> String -> FilterBuilder
94−class Select input builder output where
103+class Select input builder output | output -> builder where
95 select :: input -> builder -> output
104 select :: input -> builder -> output
97instance (YogaJson.ReadForeign output) => Select Unit FilterBuilder (Aff output) where
106instance (YogaJson.ReadForeign output) => Select Unit FilterBuilder (Aff output) where
@@ -120,6 +129,18 @@ else instance (YogaJson.ReadForeign output) => Equals FilterBuilder (Aff output)
120 equals :: String -> String -> FilterBuilder -> Aff output
129 equals :: String -> String -> FilterBuilder -> Aff output
121 equals l r builder = runFn2 (eqRunImpl builder) l r # Promise.toAffE >>= Util.fromJSON
130 equals l r builder = runFn2 (eqRunImpl builder) l r # Promise.toAffE >>= Util.fromJSON
132+foreign import orImpl :: forall builderIn builderOut. Array String -> builderIn -> builderOut
134+class Or builder output | output -> builder where
135+ or :: Array String -> builder -> output
137+instance Or FilterBuilder FilterBuilder where
138+ or :: Array String -> FilterBuilder -> FilterBuilder
139+ or keys fb = orImpl keys fb
140+else instance Or QueryBuilder FilterBuilder where
141+ or :: Array String -> QueryBuilder -> FilterBuilder
142+ or keys fb = orImpl keys fb
123foreign import singleImpl :: FilterBuilder -> Effect (Promise Foreign)
144foreign import singleImpl :: FilterBuilder -> Effect (Promise Foreign)
125single :: forall t. YogaJson.ReadForeign t => FilterBuilder -> Aff (Response t)
146single :: forall t. YogaJson.ReadForeign t => FilterBuilder -> Aff (Response t)
@@ -139,24 +160,34 @@ range { from: f, to } = rangeImpl f to >>> Promise.toAffE >=> Util.fromJSON
140type InternalAuthResponse = { error :: Nullable Error }
161type InternalAuthResponse = { error :: Nullable Error }
142−foreign import signInWithOtpImpl :: Client -> String -> Effect (Promise InternalAuthResponse)
144type AuthResponse = { error :: Maybe Error }
163type AuthResponse = { error :: Maybe Error }
165+foreign import signInWithOtpImpl :: Client -> String -> Effect (Promise InternalAuthResponse)
146signInWithOtp :: Client -> String -> Aff AuthResponse
167signInWithOtp :: Client -> String -> Aff AuthResponse
147signInWithOtp client email = signInWithOtpImpl client email # Promise.toAffE <#> \{ error } -> { error: Nullable.toMaybe error }
168signInWithOtp client email = signInWithOtpImpl client email # Promise.toAffE <#> \{ error } -> { error: Nullable.toMaybe error }
171+ ( shouldCreateUser :: Boolean
172+ , captchaToken :: String
175+foreign import signInWithOtpOptionsImpl :: forall options. EffectFn3 Client String options (Promise InternalAuthResponse)
177+signInWithOtpOptions :: forall options thru. Union options thru SignInOptions => Client -> String -> { | options } -> Aff AuthResponse
178+signInWithOtpOptions client email options = runEffectFn3 signInWithOtpOptionsImpl client email options # Promise.toAffE <#> \{ error } -> { error: Nullable.toMaybe error }
149foreign import signOutImpl :: Client -> Effect (Promise Unit)
180foreign import signOutImpl :: Client -> Effect (Promise Unit)
151signOut ∷ Client → Aff Unit
182signOut ∷ Client → Aff Unit
152signOut client = signOutImpl client # Promise.toAffE
183signOut client = signOutImpl client # Promise.toAffE
154−foreign import onAuthStateChangeImpl :: Client -> (EffectFn1 (Nullable Session) Unit) -> Effect Unit
185+foreign import onAuthStateChangeImpl :: Client -> (EffectFn1 (Nullable Session) Unit) -> Effect { data :: { id :: String, unsubscribe :: Effect Unit } }
156−onAuthStateChange ∷ Client → (Maybe Session → Effect Unit) → Effect Unit
187+onAuthStateChange ∷ Client → (Maybe Session → Effect Unit) → Effect { data :: { id :: String, unsubscribe :: Effect Unit } }
157onAuthStateChange client handler = onAuthStateChangeImpl client $ mkEffectFn1 (Nullable.toMaybe >>> handler)
188onAuthStateChange client handler = onAuthStateChangeImpl client $ mkEffectFn1 (Nullable.toMaybe >>> handler)
159−type User = { id :: String, email :: String }
190+type User = { id :: String, email :: String, user_metadata :: Foreign }
160type Session = { user :: User }
191type Session = { user :: User }
161type SessionData = { session :: Maybe Session }
192type SessionData = { session :: Maybe Session }
@@ -165,7 +196,10 @@ type ResultError = { code :: Maybe String, details :: Maybe String, message :: S
165type DataR d r = (data :: Maybe d | r)
196type DataR d r = (data :: Maybe d | r)
166type ErrorR r = (error ∷ Maybe ResultError | r)
197type ErrorR r = (error ∷ Maybe ResultError | r)
167type CountR r = (count :: Int | r)
198type CountR r = (count :: Int | r)
200+type StatusR :: forall k. k -> Row Type
168type StatusR r = (status ∷ Maybe Int)
201type StatusR r = (status ∷ Maybe Int)
169type Response d = { data :: Maybe d, error ∷ Maybe ResultError, status ∷ Maybe Int }
203type Response d = { data :: Maybe d, error ∷ Maybe ResultError, status ∷ Maybe Int }
171foreign import getSessionImpl :: Client -> Effect (Promise Foreign)
205foreign import getSessionImpl :: Client -> Effect (Promise Foreign)
@@ -177,10 +211,22 @@ type InternalFunctionResponse d = { "data" :: Nullable d, error :: Nullable { me
178foreign import invokeImpl :: forall body headers t. Client -> Fn3 String body headers (Effect $ Promise $ InternalFunctionResponse t)
212foreign import invokeImpl :: forall body headers t. Client -> Fn3 String body headers (Effect $ Promise $ InternalFunctionResponse t)
180−type FunctionResponse d = { "data" :: Maybe d, error :: Maybe { message :: String, context :: Fetch.Response }}
214+type FunctionResponse d = { "data" :: Maybe d, error :: Maybe { message :: String, context :: Fetch.Response } }
182invoke ∷ forall t body headers. ReadForeign t ⇒ Client → String → body → headers → Aff (FunctionResponse t)
216invoke ∷ forall t body headers. ReadForeign t ⇒ Client → String → body → headers → Aff (FunctionResponse t)
183invoke client fn body headers = runFn3 (invokeImpl client) fn body headers # Promise.toAffE <#> convert
217invoke client fn body headers = runFn3 (invokeImpl client) fn body headers # Promise.toAffE <#> convert
185 convertError { message, context } = { message, context: FetchInternalResponse.convert context }
219 convertError { message, context } = { message, context: FetchInternalResponse.convert context }
186 convert { "data": d, error } = { "data": Nullable.toMaybe d, error: Nullable.toMaybe error <#> convertError }
220 convert { "data": d, error } = { "data": Nullable.toMaybe d, error: Nullable.toMaybe error <#> convertError }
222+foreign import channel :: ChannelName -> Client -> Effect Channel
224+foreign import getUserImpl :: Client -> Effect (Promise { data :: Nullable User, error :: Nullable Error })
226+getUser :: Client -> Aff (Either Error User)
228+ res <- getUserImpl client # Promise.toAffE
229+ case Nullable.toMaybe res.data, Nullable.toMaybe res.error of
230+ Just user, _ -> pure $ Right user
231+ _, Just error -> pure $ Left error
232+ _, _ -> pure $ Left (error "Unexpected response error")