migrate IDBCursor interface to Class & move type definition to own module

This commit is contained in:
KtorZ 2017-07-28 00:12:55 +02:00
parent 54bcd27d7b
commit 23cf9e6410
No known key found for this signature in database
GPG Key ID: 3F72E8BC2894C015
6 changed files with 164 additions and 166 deletions

View File

@ -0,0 +1,13 @@
-- | Opaque typeclass definitions for easy reuse of functions over
-- | imported foreign types.
module Database.IndexedDB.Class where
-- | Cursor objects implement the IDBCursor interface.
-- | There is only ever one IDBCursor instance representing a given cursor.
-- | There is no limit on how many cursors can be used at the same time.
class IDBCursor cursor
-- | A concrete cursor not only shares IDBCursor properties, but also some
-- | specific attributes (see KeyCursor or CursorWithValue).
class (IDBCursor cursor) <= IDBConcreteCursor cursor

View File

@ -3,14 +3,6 @@ const toArray = function toArray(xs) {
};
exports._showCursor = function _showCursor(cursor) {
return '(IDBCursor ' +
'{ direction: ' + cursor.direction +
', key: ' + cursor.key +
', primaryKey: ' + cursor.primaryKey +
' })';
};
exports._showDatabase = function _showDatabase(db) {
return '(IDBDatabase ' +
'{ name: ' + db.name +

View File

@ -9,17 +9,14 @@
module Database.IndexedDB.Core
( IDB
, CursorDirection(..)
, CursorSource(..)
, Database
, Index
, KeyCursor
, KeyRange
, KeyPath
, ObjectStore
, Transaction
, TransactionMode(..)
, ValueCursor
, module Database.IndexedDB.IDBKey
) where
@ -35,18 +32,6 @@ import Database.IndexedDB.IDBKey
foreign import data IDB :: Effect
-- | A cursor has a direction that determines whether it moves in monotonically
-- | increasing or decreasing order of the record keys when iterated, and if it
-- | skips duplicated values when iterating indexes.
-- | The direction of a cursor also determines if the cursor initial position is at
-- | the start of its source or at its end.
data CursorDirection
= Next
| NextUnique
| Prev
| PrevUnique
-- | If the source of a cursor is an object store, the effective object store of
-- | the cursor is that object store and the effective key of the cursor is the
-- | cursors position. If the source of a cursor is an index, the effective object
@ -86,11 +71,6 @@ foreign import data Database :: Type
foreign import data Index :: Type
-- | A cursor is used to iterate over a range of records in an index or an object store
-- | in a specific direction. A KeyCursor doesn't hold any value.
foreign import data KeyCursor :: Type
-- | A key range is a continuous interval over some data type used for keys.
foreign import data KeyRange :: Type
@ -104,20 +84,6 @@ foreign import data ObjectStore :: Type
foreign import data Transaction :: Type
-- | A cursor is used to iterate over a range of records in an index or an object store
-- | in a specific direction. A ValueCursor also holds the value corresponding to matching key.
foreign import data ValueCursor :: Type
foreign import _showCursor :: forall cursor. cursor -> String
instance showKeyCursor :: Show KeyCursor where
show = _showCursor
instance showValueCursor :: Show ValueCursor where
show = _showCursor
foreign import _showDatabase
:: Database
-> String
@ -153,15 +119,6 @@ instance showTransaction :: Show Transaction where
show = _showTransaction
instance showCursorDirection :: Show CursorDirection where
show x =
case x of
Next -> "next"
NextUnique -> "nextunique"
Prev -> "prev"
PrevUnique -> "prevunique"
instance showTransactionMode :: Show TransactionMode where
show x =
case x of
@ -170,16 +127,6 @@ instance showTransactionMode :: Show TransactionMode where
VersionChange -> "versionchange"
instance readCursorDirection :: Read CursorDirection where
read s =
case s of
"next" -> Just Next
"nextunique" -> Just NextUnique
"prev" -> Just Prev
"prevunique" -> Just PrevUnique
_ -> Nothing
instance readTransactionMode :: Read TransactionMode where
read s =
case s of

View File

@ -11,6 +11,14 @@ const successHandler = function successHandler(cb) {
};
exports._showCursor = function _showCursor(cursor) {
return '(IDBCursor ' +
'{ direction: ' + cursor.direction +
', key: ' + cursor.key +
', primaryKey: ' + cursor.primaryKey +
' })';
};
exports._advance = function _advance(cursor, count) {
return function aff(success, error) {
try {

View File

@ -1,126 +1,130 @@
-- | A cursor is used to iterate over a range of records in an index or
-- | an object store in a specific direction.
module Database.IndexedDB.IDBCursor
( class IDBCursor, advance, continue, continuePrimaryKey, delete, update
-- * Cursor Manipulation
( KeyCursor
, ValueCursor
, CursorDirection(..)
, advance
, continue
, continuePrimaryKey
, delete
, update
-- * Concrete Cursor Manipulation
, direction
, key
, primaryKey
, source
, direction'
, key'
, primaryKey'
, source'
, value
) where
import Prelude (Unit, ($), (>>>), map)
import Prelude (class Show, Unit, ($), (>>>), map)
import Control.Monad.Aff (Aff)
import Data.Foreign (Foreign, toForeign, unsafeFromForeign)
import Data.Function.Uncurried as Fn
import Data.Function.Uncurried (Fn2, Fn3)
import Data.Maybe (Maybe)
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, toNullable)
import Data.String.Read (read)
import Data.String.Read (class Read, read)
import Database.IndexedDB.Core
import Database.IndexedDB.IDBKey.Internal (class IDBKey, Key(..), toKey, extractForeign)
import Database.IndexedDB.Class (class IDBCursor, class IDBConcreteCursor)
--------------------
-- TYPES
--
-- | A cursor is used to iterate over a range of records in an index or an object store
-- | in a specific direction. A KeyCursor doesn't hold any value.
foreign import data KeyCursor :: Type
-- | A cursor is used to iterate over a range of records in an index or an object store
-- | in a specific direction. A ValueCursor also holds the value corresponding to matching key.
foreign import data ValueCursor :: Type
-- | A cursor has a direction that determines whether it moves in monotonically
-- | increasing or decreasing order of the record keys when iterated, and if it
-- | skips duplicated values when iterating indexes.
-- | The direction of a cursor also determines if the cursor initial position is at
-- | the start of its source or at its end.
data CursorDirection
= Next
| NextUnique
| Prev
| PrevUnique
--------------------
-- INTERFACES
--
-- | Cursor objects implement the IDBCursor interface.
-- | There is only ever one IDBCursor instance representing a given cursor.
-- | There is no limit on how many cursors can be used at the same time.
class IDBCursor cursor where
-- | Advances the cursor through the next count records in range.
advance
:: forall e
. cursor
-> Int
-> Aff (idb :: IDB | e) Unit
-- | Advances the cursor to the next record in range matching or after key.
continue
:: forall e k. (IDBKey k)
=> cursor
-> Maybe k
-> Aff (idb :: IDB | e) Unit
-- | Advances the cursor through the next count records in range.
advance
:: forall e cursor. (IDBCursor cursor)
=> cursor
-> Int
-> Aff (idb :: IDB | e) Unit
advance =
Fn.runFn2 _advance
-- | Advances the cursor to the next record in range matching or after key and primaryKey. Throws an "InvalidAccessError" DOMException if the source is not an index.
continuePrimaryKey
:: forall e k. (IDBKey k)
=> cursor
-> k
-> k
-> Aff (idb :: IDB | e) Unit
-- | Delete the record pointed at by the cursor with a new value.
delete
:: forall e
. cursor
-> Aff (idb :: IDB | e) Unit
-- | Advances the cursor to the next record in range matching or after key.
continue
:: forall e k cursor. (IDBKey k) => (IDBCursor cursor)
=> cursor
-> Maybe k
-> Aff (idb :: IDB | e) Unit
continue c mk =
Fn.runFn2 _continue c (toNullable $ map (toKey >>> extractForeign) mk)
-- | Update the record pointed at by the cursor with a new value.
-- |
-- | Throws a "DataError" DOMException if the effective object store uses
-- | in-line keys and the key would have changed.
update
:: forall val e
. cursor
-> val
-> Aff (idb :: IDB | e) Key
-- | Advances the cursor to the next record in range matching or after key and primaryKey. Throws an "InvalidAccessError" DOMException if the source is not an index.
continuePrimaryKey
:: forall e k cursor. (IDBKey k) => (IDBCursor cursor)
=> cursor
-> k
-> k
-> Aff (idb :: IDB | e) Unit
continuePrimaryKey c k1 k2 =
Fn.runFn3 _continuePrimaryKey c (extractForeign $ toKey k1) (extractForeign $ toKey k2)
-- | Delete the record pointed at by the cursor with a new value.
delete
:: forall e cursor. (IDBCursor cursor)
=> cursor
-> Aff (idb :: IDB | e) Unit
delete =
_delete
-- | Update the record pointed at by the cursor with a new value.
-- |
-- | Throws a "DataError" DOMException if the effective object store uses
-- | in-line keys and the key would have changed.
update
:: forall val e cursor. (IDBCursor cursor)
=> cursor
-> val
-> Aff (idb :: IDB | e) Key
update c =
toForeign >>> Fn.runFn2 _update c >>> map Key
--------------------
-- ATTRIBUTES
--
-- | Returns the direction (Next|NextUnique|Prev|PrevUnique) of the cursor.
direction'
:: KeyCursor
-> CursorDirection
direction' =
Fn.runFn2 _direction (read >>> toNullable)
-- | Returns the key of the cursor. Throws a "InvalidStateError" DOMException
-- | if the cursor is advancing or is finished.
key'
:: forall e
. KeyCursor
-> Aff (idb :: IDB | e) Key
key' =
_key >>> map Key
-- | Returns the effective key of the cursor. Throws a "InvalidStateError" DOMException
-- | if the cursor is advancing or is finished.
primaryKey'
:: forall e
. KeyCursor
-> Aff (idb :: IDB | e) Key
primaryKey' =
_primaryKey >>> map Key
-- | Returns the IDBObjectStore or IDBIndex the cursor was opened from.
source'
:: KeyCursor
-> CursorSource
source' =
Fn.runFn3 _source ObjectStore Index
-- NOTE: Polymorphism not used here cause *we want* those methods to be distincs for
-- the concrete types mostly for consistency with the Database.IndexedDB.IDBIndex module
-- where the IDBIndex interfaces is shared by Index and ObjectStore, but attributes of
-- respective concrete types aren't shared.
-- | Returns the direction (Next|NextUnique|Prev|PrevUnique) of the cursor.
direction
:: ValueCursor
:: forall cursor. (IDBConcreteCursor cursor)
=> cursor
-> CursorDirection
direction =
Fn.runFn2 _direction (read >>> toNullable)
@ -129,8 +133,8 @@ direction =
-- | Returns the key of the cursor. Throws a "InvalidStateError" DOMException
-- | if the cursor is advancing or is finished.
key
:: forall e
. ValueCursor
:: forall e cursor. (IDBConcreteCursor cursor)
=> cursor
-> Aff (idb :: IDB | e) Key
key =
_key >>> map Key
@ -139,8 +143,8 @@ key =
-- | Returns the effective key of the cursor. Throws a "InvalidStateError" DOMException
-- | if the cursor is advancing or is finished.
primaryKey
:: forall e
. ValueCursor
:: forall e cursor. (IDBConcreteCursor cursor)
=> cursor
-> Aff (idb :: IDB | e) Key
primaryKey =
_primaryKey >>> map Key
@ -148,7 +152,8 @@ primaryKey =
-- | Returns the IDBObjectStore or IDBIndex the cursor was opened from.
source
:: ValueCursor
:: forall cursor. (IDBConcreteCursor cursor)
=> cursor
-> CursorSource
source =
Fn.runFn3 _source ObjectStore Index
@ -165,25 +170,57 @@ value =
--------------------
-- INSTANCES
--
instance keyCursorKeyCursor :: IDBCursor KeyCursor where
advance = Fn.runFn2 _advance
continue c mk = Fn.runFn2 _continue c (toNullable $ map (toKey >>> extractForeign) mk)
continuePrimaryKey c k1 k2 = Fn.runFn3 _continuePrimaryKey c (extractForeign $ toKey k1) (extractForeign $ toKey k2)
delete = _delete
update c = toForeign >>> Fn.runFn2 _update c >>> map Key
instance idbCursorKeyCursor :: IDBCursor KeyCursor
instance valueCursorKeyCursor :: IDBCursor ValueCursor where
advance = Fn.runFn2 _advance
continue c mk = Fn.runFn2 _continue c (toNullable $ map (toKey >>> extractForeign) mk)
continuePrimaryKey c k1 k2 = Fn.runFn3 _continuePrimaryKey c (extractForeign $ toKey k1) (extractForeign $ toKey k2)
delete = _delete
update c = toForeign >>> Fn.runFn2 _update c >>> map Key
instance idbCursorValueCursor :: IDBCursor ValueCursor
instance idbConcreteCursorKeyCursor :: IDBConcreteCursor KeyCursor
instance idbConcreteCursorValueCursor :: IDBConcreteCursor ValueCursor
instance showKeyCursor :: Show KeyCursor where
show = _showCursor
instance showValueCursor :: Show ValueCursor where
show = _showCursor
instance showCursorDirection :: Show CursorDirection where
show x =
case x of
Next -> "next"
NextUnique -> "nextunique"
Prev -> "prev"
PrevUnique -> "prevunique"
instance readCursorDirection :: Read CursorDirection where
read s =
case s of
"next" -> Just Next
"nextunique" -> Just NextUnique
"prev" -> Just Prev
"prevunique" -> Just PrevUnique
_ -> Nothing
--------------------
-- FFI
--
foreign import _showCursor
:: forall cursor
. cursor
-> String
foreign import _advance
:: forall cursor e
. Fn2 cursor Int (Aff (idb :: IDB | e) Unit)

View File

@ -13,7 +13,8 @@ import Data.Function.Uncurried (Fn2, Fn3, Fn4)
import Data.Maybe (Maybe)
import Data.Nullable (Nullable, toMaybe, toNullable)
import Database.IndexedDB.Core (IDB, CursorDirection, Index, Key, KeyCursor, KeyRange, KeyPath, ObjectStore, ValueCursor)
import Database.IndexedDB.Core (IDB, Index, Key, KeyRange, KeyPath, ObjectStore)
import Database.IndexedDB.IDBCursor (CursorDirection, KeyCursor, ValueCursor)
import Database.IndexedDB.IDBKey.Internal (class IDBKey, Key(..))