git.iko.soy/rowtype-yoga/purescript-yoga-json
on main help sign in
Migrate to js-bigints in order to remove npm dep
commitce7b317fa1e358b01e11d77d2e7aa3a96f768655 authorsigma-andex <77549848+sigma-andex@users.noreply.github.com> dateSun 16 Oct 2022, 11:17 (4 years ago) parent9d6263b
14 files changed+223−182
package.json−1 packages.dhall+5 spago.dhall+1−1 src/Yoga/JSON.js+9−9 src/Yoga/JSON.purs+51−53 src/Yoga/JSON/Error.purs+7−7 src/Yoga/JSON/Generics/EnumSumRep.purs+2−2 src/Yoga/JSON/Generics/UntaggedProductRep.purs+6−3 src/Yoga/JSON/Generics/UntaggedSumRep.purs+22−22 src/Yoga/JSON/Variant.purs+6−6 test/BasicsSpec.purs+51−46 test/ErrorsSpec.purs+9−8 test/GenericsSpec.purs+52−22 test/Main.purs+2−2
package.json−1
@@ -5,7 +5,6 @@
55 "coverage": "c8 --100 npm run test"
66 },
77 "dependencies": {
8− "big-integer": "^1.6.51"
98 },
109 "type": "module",
1110 "devDependencies": {
packages.dhall+5
@@ -3,3 +3,8 @@ let upstream =
33 sha256:348212b7c79da7d343bed71b48ed164d426f1977f92196babac49bd560b32e75
44
55in upstream
6+ with js-bigints =
7+ { dependencies = [ "maybe", "prelude" ]
8+ , version = "v1.2.0"
9+ , repo = "https://github.com/sigma-andex/purescript-js-bigints"
10+ }
spago.dhall+1−1
@@ -4,7 +4,7 @@
44, dependencies =
55 [ "arrays"
66 , "bifunctors"
7− , "bigints"
7+ , "js-bigints"
88 , "console"
99 , "control"
1010 , "datetime"
src/Yoga/JSON.js+9−9
@@ -1,18 +1,18 @@
11function reviver(key, value) {
2− if (key === 'big') {
3− return BigInt(value);
4− }
5− return value;
2+ if (key === "big") {
3+ return BigInt(value);
4+ }
5+ return value;
66}
77export const _parseJSON = (payload) => JSON.parse(payload, reviver);
88
99export const _undefined = undefined;
1010
1111function replacer(key, value) {
12− if (key === 'big') {
13− return value.toString();
14− }
15− return value;
12+ if (typeof value === "bigint") {
13+ return value.toString();
1614 }
17−
15+ return value;
16+}
17+
1818export const _unsafeStringify = (data) => JSON.stringify(data, replacer);
src/Yoga/JSON.purs+51−53
@@ -39,8 +39,6 @@ import Control.Monad.Except (ExceptT(..), except, runExcept, throwError, withExc
3939import Data.Array as Array
4040import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
4141import Data.Bifunctor (lmap)
42−import Data.BigInt (BigInt)
43−import Data.BigInt as BigInt
4442import Data.DateTime (DateTime)
4543import Data.Either (Either(..), hush, note)
4644import Data.Foldable (class Foldable, foldl)
@@ -68,6 +66,8 @@ import Foreign (F, Foreign, ForeignError(..), MultipleErrors, fail, isNull, isUn
6866import Foreign.Index (readProp)
6967import Foreign.Object (Object)
7068import Foreign.Object as Object
69+import Js.BigInt.BigInt (BigInt)
70+import Js.BigInt.BigInt (BigInt, fromInt, fromNumber, fromString) as BigInt
7171import Partial.Unsafe (unsafeCrashWith)
7272import Prim.Row as Row
7373import Prim.RowList (class RowToList, Cons, Nil, RowList)
@@ -194,18 +194,18 @@ instance ReadForeign BigInt where
194194 where
195195 tryInt f = readInt f <#> BigInt.fromInt
196196 tryNumber f = do
197− num <- readNumber f
197+ num ← readNumber f
198198 if Number.round num == num then
199199 BigInt.fromNumber num
200200 # note (err $ "Cannot convert Number " <> show num <> " to BigInt")
201201 # except
202− else
203− (Left $ err $ "Cannot convert decimal Number " <> show num <> " to BigInt")
204− # except
202+ else
203+ (Left $ err $ "Cannot convert decimal Number " <> show num <> " to BigInt")
204+ # except
205205 tryString f = do
206206 bi ← readString f
207207 BigInt.fromString bi
208− # note ( err $ "Cannot convert String " <> bi <> " to BigInt")
208+ # note (err $ "Cannot convert String " <> bi <> " to BigInt")
209209 # except
210210 err = pure <<< ForeignError
211211
@@ -235,27 +235,27 @@ instance ReadForeign a ⇒ ReadForeign (Nullable a) where
235235
236236instance (ReadForeign a, ReadForeign b) ⇒ ReadForeign (Either a b) where
237237 readImpl f = do
238− { type: tpe, value } :: { type :: String, value :: Foreign } <- readImpl f
238+ { type: tpe, value } ∷ { type ∷ String, value ∷ Foreign } ← readImpl f
239239 case tpe of
240− "left" -> Left <$> readImpl value
241− "right" -> Right <$> readImpl value
242− _ -> except $ Left (pure $ ForeignError $ "Invalid Either tag " <> tpe)
240+ "left" → Left <$> readImpl value
241+ "right" → Right <$> readImpl value
242+ _ → except $ Left (pure $ ForeignError $ "Invalid Either tag " <> tpe)
243243
244244instance ReadForeign a ⇒ ReadForeign (Object.Object a) where
245245 readImpl = gatherErrors <<< Object.mapWithKey readProp <=< readObject'
246246 where
247− gatherErrors :: Object (F a) -> F (Object a)
247+ gatherErrors ∷ Object (F a) → F (Object a)
248248 gatherErrors = Object.toUnfoldable
249249 >>> Array.foldl fn (Right (Object.empty))
250250 >>> except
251251 where
252− fn :: _ -> _ -> (Either MultipleErrors (Object a))
252+ fn ∷ _ → _ → (Either MultipleErrors (Object a))
253253 fn acc (Tuple k v) = do
254254 case acc, runExcept v of
255− Left errs, Left errsNew -> Left (errs <> errsNew)
256− Left errs, Right _ -> Left errs
257− Right obj, Right value -> Right (Object.insert k value obj)
258− Right _, Left errs -> Left errs
255+ Left errs, Left errsNew → Left (errs <> errsNew)
256+ Left errs, Right _ → Left errs
257+ Right obj, Right value → Right (Object.insert k value obj)
258+ Right _, Left errs → Left errs
259259
260260 readProp key value = except $ lmap (map (ErrorAtProperty key))
261261 (readImpl value # runExcept)
@@ -336,10 +336,10 @@ instance
336336 ReadForeignFields (Cons name ty tail) from to where
337337 getFields _ obj = except
338338 case runExcept first, runExcept rest of
339− Right f, Right r -> Right (f <<< r)
340− Left e1, Left e2 -> Left (e1 <> e2)
341− Right _, Left es -> Left es
342− Left es, Right _ -> Left es
339+ Right f, Right r → Right (f <<< r)
340+ Left e1, Left e2 → Left (e1 <> e2)
341+ Right _, Left es → Left es
342+ Left es, Right _ → Left es
343343 where
344344 value = enrichErrorWithPropName (readImpl =<< readProp name obj)
345345 first = Builder.insert nameP <$> value
@@ -379,8 +379,8 @@ instance
379379 , ReadForeignVariant tail row
380380 ) ⇒
381381 ReadForeignVariant (Cons name ty tail) row where
382− readVariantImpl _ o = readVariantImpl (Proxy :: Proxy tail) o <|> ado
383− value :: ty <- readProp name o >>= readImpl
382+ readVariantImpl _ o = readVariantImpl (Proxy ∷ Proxy tail) o <|> ado
383+ value ∷ ty ← readProp name o >>= readImpl
384384 in inj namep value
385385 where
386386 namep = Proxy ∷ Proxy name
@@ -428,8 +428,8 @@ instance WriteForeign a ⇒ WriteForeign (Nullable a) where
428428
429429instance (WriteForeign a, WriteForeign b) ⇒ WriteForeign (Either a b) where
430430 writeImpl value = case value of
431− Left l -> writeImpl { type: "left", value: writeImpl l}
432− Right r -> writeImpl { type: "right", value: writeImpl r}
431+ Left l → writeImpl { type: "left", value: writeImpl l }
432+ Right r → writeImpl { type: "right", value: writeImpl r }
433433
434434instance WriteForeign a ⇒ WriteForeign (Object.Object a) where
435435 writeImpl = unsafeToForeign <<< Object.mapWithKey (const writeImpl)
@@ -532,23 +532,19 @@ instance writeForeignNEArray ∷ WriteForeign a ⇒ WriteForeign (NonEmptyArray
532532 writeImpl a = writeImpl <<< toArray $ a
533533
534534-- Map instances
535−instance (WriteForeign a) => WriteForeign (Map String a) where
535+instance (WriteForeign a) ⇒ WriteForeign (Map String a) where
536536 writeImpl = foldrWithIndex Object.insert Object.empty >>> writeImpl
537−else
538−instance (WriteForeign a) => WriteForeign (Map Int a) where
537+else instance (WriteForeign a) ⇒ WriteForeign (Map Int a) where
539538 writeImpl = foldrWithIndex (show >>> Object.insert) Object.empty >>> writeImpl
540−else
541−instance (Newtype nt key, WriteForeign (Map key value)) => WriteForeign (Map nt value) where
542− writeImpl = (unsafeCoerce :: (_ -> Map key value )) >>> writeImpl
543−
544−instance (ReadForeign a) => ReadForeign (Map String a) where
545− readImpl = (readImpl :: (_ -> _ (Object a))) >>> map (foldrWithIndex Map.insert Map.empty)
546−else
547−instance (ReadForeign a) => ReadForeign (Map Int a) where
548− readImpl = (readImpl :: (_ -> _ (Object a))) >>> map (foldrWithIndex (unsafeStringToInt >>> Map.insert) Map.empty)
549−else
550−instance (Newtype nt key, ReadForeign (Map key value)) => ReadForeign (Map nt value) where
551− readImpl = (readImpl :: (_ -> _ (Map key value))) >>> map (unsafeCoerce :: (Map key value -> Map nt value))
539+else instance (Newtype nt key, WriteForeign (Map key value)) ⇒ WriteForeign (Map nt value) where
540+ writeImpl = (unsafeCoerce ∷ (_ → Map key value)) >>> writeImpl
541+
542+instance (ReadForeign a) ⇒ ReadForeign (Map String a) where
543+ readImpl = (readImpl ∷ (_ → _ (Object a))) >>> map (foldrWithIndex Map.insert Map.empty)
544+else instance (ReadForeign a) ⇒ ReadForeign (Map Int a) where
545+ readImpl = (readImpl ∷ (_ → _ (Object a))) >>> map (foldrWithIndex (unsafeStringToInt >>> Map.insert) Map.empty)
546+else instance (Newtype nt key, ReadForeign (Map key value)) ⇒ ReadForeign (Map nt value) where
547+ readImpl = (readImpl ∷ (_ → _ (Map key value))) >>> map (unsafeCoerce ∷ (Map key value → Map nt value))
552548
553549-- Date instances
554550instance WriteForeign JSDate where
@@ -566,21 +562,23 @@ instance ReadForeign DateTime where
566562 >>> note (pure $ ForeignError "Invalid date time")
567563 >>> except
568564
569−unsafeStringToInt :: String → Int
565+unsafeStringToInt ∷ String → Int
570566unsafeStringToInt = Int.fromString >>>
571− (fromMaybe' \_ -> unsafeCrashWith "impossible")
572−
573−sequenceCombining :: forall f a.
574− Monoid (f a) =>
575− Foldable f =>
576− Applicative f =>
577− f (F a) -> F (f a)
567+ (fromMaybe' \_ → unsafeCrashWith "impossible")
568+
569+sequenceCombining ∷
570+ ∀ f a.
571+ Monoid (f a) ⇒
572+ Foldable f ⇒
573+ Applicative f ⇒
574+ f (F a) →
575+ F (f a)
578576sequenceCombining = foldl fn (Right mempty) >>> except
579577 where
580− fn :: _ -> _ -> (Either MultipleErrors (f a))
578+ fn ∷ _ → _ → (Either MultipleErrors (f a))
581579 fn acc elem = do
582580 case acc, runExcept elem of
583− Left errs, Left errsNew -> Left (errs <> errsNew)
584− Left errs, Right _ -> Left errs
585− Right values, Right value -> Right (values <> pure value)
586− Right _, Left errs -> Left errs
581+ Left errs, Left errsNew → Left (errs <> errsNew)
582+ Left errs, Right _ → Left errs
583+ Right values, Right value → Right (values <> pure value)
584+ Right _, Left errs → Left errs
src/Yoga/JSON/Error.purs+7−7
@@ -4,18 +4,18 @@ import Prelude
44
55import Foreign (ForeignError(..))
66
7−toJSONPath :: ForeignError -> String
7+toJSONPath ∷ ForeignError → String
88toJSONPath fe = "$" <> path
99 where
1010 path = go fe
1111 go = case _ of
12− ForeignError _ -> ""
13− TypeMismatch _ _ -> ""
14− ErrorAtIndex i e -> "[" <> show i <> "]" <> go e
15− ErrorAtProperty _ (TypeMismatch _ "undefined") -> ""
16− ErrorAtProperty prop e -> "." <> prop <> go e
12+ ForeignError _ → ""
13+ TypeMismatch _ _ → ""
14+ ErrorAtIndex i e → "[" <> show i <> "]" <> go e
15+ ErrorAtProperty _ (TypeMismatch _ "undefined") → ""
16+ ErrorAtProperty prop e → "." <> prop <> go e
1717
18−renderHumanError :: ForeignError -> String
18+renderHumanError ∷ ForeignError → String
1919renderHumanError = errorToJSON >>> toHuman
2020 where
2121 toHuman { message, path } = message <> " at " <> path
src/Yoga/JSON/Generics/EnumSumRep.purs+2−2
@@ -36,8 +36,8 @@ genericWriteForeignEnum options a = genericEnumWriteForeign options (GR.from a)
3636
3737-- | Generic Enum Sum Representations, with constructor names as strings
3838class GenericEnumSumRep rep where
39− genericEnumReadForeign ∷ Options -> Foreign → Foreign.F rep
40− genericEnumWriteForeign ∷ Options -> rep → Foreign
39+ genericEnumReadForeign ∷ Options → Foreign → Foreign.F rep
40+ genericEnumWriteForeign ∷ Options → rep → Foreign
4141
4242instance
4343 ( GenericEnumSumRep a
src/Yoga/JSON/Generics/UntaggedProductRep.purs+6−3
@@ -58,18 +58,21 @@ genericWriteForeignUntaggedProduct ∷
5858genericWriteForeignUntaggedProduct a =
5959 JSON.write (genericWriteForeignUntaggedProductRep [] (GR.from a))
6060
61−
6261-- | Generic Untagged Product Representations, as a heterogeneous fixed-length array
6362-- | You should consider using records instead in almost any usage.
6463class WriteGenericUntaggedProduct rep where
6564 genericWriteForeignUntaggedProductRep ∷ Array Foreign → rep → Array Foreign
6665
67−instance (WriteGenericUntaggedProduct a) ⇒
66+instance
67+ ( WriteGenericUntaggedProduct a
68+ ) ⇒
6869 WriteGenericUntaggedProduct (GR.Constructor name a) where
6970 genericWriteForeignUntaggedProductRep arr (GR.Constructor a) =
7071 genericWriteForeignUntaggedProductRep arr a
7172
72−instance (JSON.WriteForeign a) ⇒
73+instance
74+ ( JSON.WriteForeign a
75+ ) ⇒
7376 WriteGenericUntaggedProduct (GR.Argument a) where
7477 genericWriteForeignUntaggedProductRep arr (GR.Argument a) =
7578 Array.snoc arr (JSON.write a)
src/Yoga/JSON/Generics/UntaggedSumRep.purs+22−22
@@ -8,69 +8,69 @@ import Foreign (Foreign)
88import Foreign as Foreign
99import Yoga.JSON as JSON
1010
11−genericReadForeignUntaggedSum
12− :: forall a rep
13− . GR.Generic a rep
14− => ReadGenericUntaggedSumRep rep
15− => Foreign
16− -> Foreign.F a
11+genericReadForeignUntaggedSum ∷
12+ ∀ a rep.
13+ GR.Generic a rep ⇒
14+ ReadGenericUntaggedSumRep rep ⇒
15+ Foreign →
16+ Foreign.F a
1717genericReadForeignUntaggedSum f = GR.to <$> genericReadForeignUntaggedSumRep f
1818
1919-- | Generic Untagged Sum Representations
2020-- | Note that because the members are untagged, you should verify your members are not the same type
2121class ReadGenericUntaggedSumRep rep where
22− genericReadForeignUntaggedSumRep :: Foreign -> Foreign.F rep
22+ genericReadForeignUntaggedSumRep ∷ Foreign → Foreign.F rep
2323
2424instance
2525 ( ReadGenericUntaggedSumRep a
2626 , ReadGenericUntaggedSumRep b
27− ) =>
27+ ) ⇒
2828 ReadGenericUntaggedSumRep (GR.Sum a b) where
2929 genericReadForeignUntaggedSumRep f = GR.Inl <$> genericReadForeignUntaggedSumRep f
3030 <|> GR.Inr <$> genericReadForeignUntaggedSumRep f
3131
3232instance
3333 ( ReadGenericUntaggedSumRep a
34− ) =>
34+ ) ⇒
3535 ReadGenericUntaggedSumRep (GR.Constructor name a) where
3636 genericReadForeignUntaggedSumRep f = GR.Constructor <$> genericReadForeignUntaggedSumRep f
3737
3838instance
3939 ( JSON.ReadForeign a
40− ) =>
40+ ) ⇒
4141 ReadGenericUntaggedSumRep (GR.Argument a) where
4242 genericReadForeignUntaggedSumRep f = GR.Argument <$> JSON.readImpl f
4343
44−genericWriteForeignUntaggedSum
45− :: forall a rep
46− . GR.Generic a rep
47− => WriteGenericUntaggedSumRep rep
48− => a
49− -> Foreign
44+genericWriteForeignUntaggedSum ∷
45+ ∀ a rep.
46+ GR.Generic a rep ⇒
47+ WriteGenericUntaggedSumRep rep ⇒
48+ a →
49+ Foreign
5050genericWriteForeignUntaggedSum a = GR.from a # genericWriteForeignUntaggedSumRep
5151
5252-- | Generic Untagged Sum Representations
5353-- | Note that because the members are untagged, you should verify your members are not the same type
5454class WriteGenericUntaggedSumRep rep where
55− genericWriteForeignUntaggedSumRep :: rep -> Foreign
55+ genericWriteForeignUntaggedSumRep ∷ rep → Foreign
5656
5757instance
5858 ( WriteGenericUntaggedSumRep a
5959 , WriteGenericUntaggedSumRep b
60− ) =>
60+ ) ⇒
6161 WriteGenericUntaggedSumRep (GR.Sum a b) where
6262 genericWriteForeignUntaggedSumRep = case _ of
63− GR.Inl a -> genericWriteForeignUntaggedSumRep a
64− GR.Inr a -> genericWriteForeignUntaggedSumRep a
63+ GR.Inl a → genericWriteForeignUntaggedSumRep a
64+ GR.Inr a → genericWriteForeignUntaggedSumRep a
6565
6666instance
6767 ( WriteGenericUntaggedSumRep a
68− ) =>
68+ ) ⇒
6969 WriteGenericUntaggedSumRep (GR.Constructor name a) where
7070 genericWriteForeignUntaggedSumRep (GR.Constructor a) = genericWriteForeignUntaggedSumRep a
7171
7272instance
7373 ( JSON.WriteForeign a
74− ) =>
74+ ) ⇒
7575 WriteGenericUntaggedSumRep (GR.Argument a) where
7676 genericWriteForeignUntaggedSumRep (GR.Argument a) = JSON.write a
src/Yoga/JSON/Variant.purs+6−6
@@ -20,8 +20,8 @@ newtype TaggedVariant ∷ Symbol → Symbol → Row Type → Type
2020newtype TaggedVariant tt vt v = TaggedVariant (Variant v)
2121
2222instance Newtype (TaggedVariant tt vt v) (Variant v)
23−derive newtype instance (Show (Variant v)) => Show (TaggedVariant tt vt v)
24−derive newtype instance (Eq (Variant v)) => Eq (TaggedVariant tt vt v)
23+derive newtype instance (Show (Variant v)) ⇒ Show (TaggedVariant tt vt v)
24+derive newtype instance (Eq (Variant v)) ⇒ Eq (TaggedVariant tt vt v)
2525
2626instance
2727 ( RowToList row rl
@@ -104,7 +104,7 @@ instance
104104 readVariantImpl _ o = readVariantImpl (Proxy ∷ Proxy tail) o <|> do
105105 type_ ← readProp typeTag o >>= readImpl
106106 if type_ == name then do
107− value :: ty <- readProp valueTag o >>= readImpl
107+ value ∷ ty ← readProp valueTag o >>= readImpl
108108 pure $ TaggedVariant (inj namep value)
109109 else
110110 (fail <<< ForeignError $ "Did not match variant tag " <> name)
@@ -121,8 +121,8 @@ newtype UntaggedVariant ∷ Row Type → Type
121121newtype UntaggedVariant v = UntaggedVariant (Variant v)
122122
123123instance Newtype (UntaggedVariant v) (Variant v)
124−derive newtype instance (Show (Variant v)) => Show (UntaggedVariant v)
125−derive newtype instance (Eq (Variant v)) => Eq (UntaggedVariant v)
124+derive newtype instance (Show (Variant v)) ⇒ Show (UntaggedVariant v)
125+derive newtype instance (Eq (Variant v)) ⇒ Eq (UntaggedVariant v)
126126
127127instance
128128 ( RowToList row rl
@@ -190,7 +190,7 @@ instance
190190 ReadForeignUntaggedVariant (Cons name ty tail) row where
191191 readUntaggedVariantImpl _ o =
192192 readUntaggedVariantImpl (Proxy ∷ Proxy tail) o <|> ado
193− v <- readImpl o
193+ v ← readImpl o
194194 in UntaggedVariant (inj namep v)
195195
196196 where
test/BasicsSpec.purs+51−46
@@ -3,23 +3,25 @@ module Test.BasicsSpec where
33import Prelude
44
55import Data.Array.NonEmpty as NEA
6−import Data.BigInt (BigInt)
76import Data.Either (Either(..))
87import Data.Foldable (traverse_)
98import Data.JSDate as JSDate
109import Data.List as List
1110import Data.List.Lazy as LazyList
1211import Data.Map as Map
13−import Data.Maybe (Maybe(..), fromMaybe')
12+import Data.Maybe (Maybe(..), fromJust, fromMaybe')
1413import Data.Newtype (class Newtype, un)
1514import Data.Nullable as Nullable
1615import Data.Tuple (Tuple(..))
1716import Data.Tuple.Nested ((/\))
1817import Data.Variant (Variant, inj)
18+import Debug (spy)
1919import Effect.Class (liftEffect)
2020import Effect.Now (nowDateTime)
2121import Foreign.Object as Object
22−import Partial.Unsafe (unsafeCrashWith)
22+import Js.BigInt.BigInt (BigInt)
23+import Js.BigInt.BigInt as BigInt
24+import Partial.Unsafe (unsafeCrashWith, unsafePartial)
2325import Test.Spec (Spec, describe, it)
2426import Test.Spec.Assertions (shouldEqual)
2527import Test.Util (roundtrips)
@@ -27,7 +29,7 @@ import Type.Proxy (Proxy(..))
2729import Yoga.JSON (class ReadForeign, class WriteForeign, readJSON, writeJSON)
2830import Yoga.JSON.Variant (TaggedVariant(..), UntaggedVariant(..))
2931
30−spec :: Spec Unit
32+spec ∷ Spec Unit
3133spec = describe "En- and decoding" $ do
3234
3335 describe "works on primitive types" do
@@ -40,63 +42,63 @@ spec = describe "En- and decoding" $ do
4042 it "roundtrips Maybe" do
4143 roundtrips (Just 3)
4244 -- just roundtrips Nothing doesn't work when rendering the JSON
43− roundtrips { empty: Nothing :: Maybe Int }
44− it "roundtrips Nullable" $ traverse_ roundtrips [Nullable.notNull 3, Nullable.null]
45+ roundtrips { empty: Nothing ∷ Maybe Int }
46+ it "roundtrips Nullable" $ traverse_ roundtrips [ Nullable.notNull 3, Nullable.null ]
4547 it "roundtrips Either" do
46− roundtrips ((Left 3) :: Either Int Int)
47− roundtrips ((Right 3) :: Either String Int)
48− writeJSON (Right 3 :: Either Int Int) `shouldEqual` """{"value":3,"type":"right"}"""
49− writeJSON (Left true :: Either Boolean Int) `shouldEqual` """{"value":true,"type":"left"}"""
48+ roundtrips ((Left 3) ∷ Either Int Int)
49+ roundtrips ((Right 3) ∷ Either String Int)
50+ writeJSON (Right 3 ∷ Either Int Int) `shouldEqual` """{"value":3,"type":"right"}"""
51+ writeJSON (Left true ∷ Either Boolean Int) `shouldEqual` """{"value":true,"type":"left"}"""
5052 it "roundtrips Tuple" $ do
5153 roundtrips (Tuple 3 4)
5254 roundtrips ("4" /\ 8 /\ Just 4)
53− it "roundtrips Array" $ traverse_ roundtrips [["A", "B"],[]]
54− it "roundtrips LazyList" $ traverse_ roundtrips (LazyList.fromFoldable [["A", "B"],[]])
55− it "roundtrips List" $ traverse_ roundtrips (List.fromFoldable [["A", "B"],[]])
56− it "roundtrips NonEmptyArray" $ roundtrips (NEA.cons' "A" ["B"])
55+ it "roundtrips Array" $ traverse_ roundtrips [ [ "A", "B" ], [] ]
56+ it "roundtrips LazyList" $ traverse_ roundtrips (LazyList.fromFoldable [ [ "A", "B" ], [] ])
57+ it "roundtrips List" $ traverse_ roundtrips (List.fromFoldable [ [ "A", "B" ], [] ])
58+ it "roundtrips NonEmptyArray" $ roundtrips (NEA.cons' "A" [ "B" ])
5759 it "roundtrips Object" $ roundtrips (Object.fromHomogeneous { a: 12, b: 54 })
58− it "roundtrips String Map" $ roundtrips (Map.fromFoldable [("A" /\ 8),("C" /\ 7)])
59− it "roundtrips Int Map" $ roundtrips (Map.fromFoldable [(4 /\ "B"),(8 /\ "D")])
60+ it "roundtrips String Map" $ roundtrips (Map.fromFoldable [ ("A" /\ 8), ("C" /\ 7) ])
61+ it "roundtrips Int Map" $ roundtrips (Map.fromFoldable [ (4 /\ "B"), (8 /\ "D") ])
6062 it "roundtrips Map with String newtype keys"
61− $ roundtrips (Map.fromFoldable [(Stringy "A" /\ "B"),(Stringy "C" /\ "D")])
63+ $ roundtrips (Map.fromFoldable [ (Stringy "A" /\ "B"), (Stringy "C" /\ "D") ])
6264 it "roundtrips Map with Int newtype keys"
63− $ roundtrips (Map.fromFoldable [(Inty 4 /\ "B"),(Inty 8 /\ "D")])
65+ $ roundtrips (Map.fromFoldable [ (Inty 4 /\ "B"), (Inty 8 /\ "D") ])
6466 it "roundtrips BigInt" do
6567 let
6668 inputStr = """{ "number":1, "big": 18014398509481982, "mediumBig": 1652955871799, "smallBig": 10 }"""
6769 expected = """{"smallBig":"10","number":1,"mediumBig":"1652955871799","big":"18014398509481982"}"""
68− parsed ∷ _ ({ number ∷ Int, mediumBig :: BigInt, big ∷ BigInt, smallBig ∷ BigInt })
70+
71+ parsed ∷ _ ({ number ∷ Int, mediumBig ∷ BigInt, big ∷ BigInt, smallBig ∷ BigInt })
6972 parsed = readJSON inputStr
7073 stringified = parsed <#> writeJSON
7174 stringified `shouldEqual` (Right expected)
72− -- [TODO] Comment in as soon as bug in big-integers is fixed
73− -- @sigma-andex: What bug? Can we link this???
74− -- it "roundtrips BigInt (2)" do
75− -- let
76− -- smallBig = BigInt.fromInt 10
77− -- big = unsafePartial $ fromJust $ BigInt.fromString "18014398509481982"
7875
79− -- expected = { big, smallBig }
80− -- json = spy "json" $ writeJSON expected
76+ it "roundtrips BigInt (2)" do
77+ let
78+ smallBig = BigInt.fromInt 10
79+ big = unsafePartial $ fromJust $ BigInt.fromString "18014398509481982"
80+
81+ expected = { big, smallBig }
82+ json = writeJSON expected
8183
82− -- parsed ∷ _ ({ big ∷ BigInt, smallBig ∷ BigInt })
83− -- parsed = readJSON json
84− -- (spy "parsed" parsed) `shouldEqual` (Right expected)
84+ parsed ∷ _ ({ big ∷ BigInt, smallBig ∷ BigInt })
85+ parsed = readJSON json
86+ parsed `shouldEqual` (Right expected)
8587
8688 describe "works with JSDate" do
8789 it "roundtrips" do
88− now <- JSDate.now # liftEffect
90+ now ← JSDate.now # liftEffect
8991 roundtrips now
90− someDate <- JSDate.parse "2022-01-01:00:00:00Z" # liftEffect
92+ someDate ← JSDate.parse "2022-01-01:00:00:00Z" # liftEffect
9193 let result = writeJSON someDate
9294 let expected = show "2022-01-01T00:00:00.000Z"
9395 result `shouldEqual` expected
9496
9597 describe "works with DateTime" do
9698 it "roundtrips" do
97− now <- nowDateTime # liftEffect
99+ now ← nowDateTime # liftEffect
98100 roundtrips now
99− someDate <- JSDate.parse "2022-01-01:00:00:00Z" <#> (JSDate.toDateTime >>> fromMaybe' \_ -> unsafeCrashWith "nope") # liftEffect
101+ someDate ← JSDate.parse "2022-01-01:00:00:00Z" <#> (JSDate.toDateTime >>> fromMaybe' \_ → unsafeCrashWith "nope") # liftEffect
100102 let result = writeJSON someDate
101103 let expected = show "2022-01-01T00:00:00.000Z"
102104 result `shouldEqual` expected
@@ -112,41 +114,43 @@ spec = describe "En- and decoding" $ do
112114
113115 describe "works on variant types" do
114116 it "roundtrips" do
115− roundtrips (inj (Proxy :: _ "erwin") "e" :: Variant ("erwin" :: String))
116− roundtrips (inj (Proxy :: _ "jackie") 7 :: Variant ExampleVariant)
117+ roundtrips (inj (Proxy ∷ _ "erwin") "e" ∷ Variant ("erwin" ∷ String))
118+ roundtrips (inj (Proxy ∷ _ "jackie") 7 ∷ Variant ExampleVariant)
117119
118120 describe "works on tagged variant types" do
119121 it "roundtrips" do
120− roundtrips (TaggedVariant (erwin "e") :: TaggedVariant "super" "hans" (Erwin ()))
122+ roundtrips (TaggedVariant (erwin "e") ∷ TaggedVariant "super" "hans" (Erwin ()))
121123 let bareVariant = erwin "e"
122− let res = writeJSON (TaggedVariant bareVariant :: TaggedVariant "type" "value" ExampleVariant)
124+ let res = writeJSON (TaggedVariant bareVariant ∷ TaggedVariant "type" "value" ExampleVariant)
123125 let expected = """{"value":"e","type":"erwin"}"""
124126 res `shouldEqual` expected
125127 let
126− parsed :: _ (TaggedVariant "type" "value" ExampleVariant)
128+ parsed ∷ _ (TaggedVariant "type" "value" ExampleVariant)
127129 parsed = readJSON expected
128130 (un TaggedVariant <$> parsed) `shouldEqual` Right bareVariant
129131
130132 describe "works on untagged variant types" do
131133 it "roundtrips" do
132− roundtrips (UntaggedVariant (erwin "e") :: UntaggedVariant (Erwin ()))
134+ roundtrips (UntaggedVariant (erwin "e") ∷ UntaggedVariant (Erwin ()))
133135 let bareVariant = erwin "e"
134− let res = writeJSON (UntaggedVariant bareVariant :: UntaggedVariant ExampleVariant)
136+ let res = writeJSON (UntaggedVariant bareVariant ∷ UntaggedVariant ExampleVariant)
135137 let expected = """"e""""
136138 res `shouldEqual` expected
137139 let
138− parsed :: _ (UntaggedVariant ExampleVariant)
140+ parsed ∷ _ (UntaggedVariant ExampleVariant)
139141 parsed = readJSON expected
140142 (un UntaggedVariant <$> parsed) `shouldEqual` Right bareVariant
141143
142−type ExampleVariant = ("erwin" :: String, "jackie" :: Int)
144+type ExampleVariant = ("erwin" ∷ String, "jackie" ∷ Int)
143145type ExampleTaggedVariant t v = TaggedVariant t v ExampleVariant
144146
145−erwin ∷ ∀ a r. a → Variant ( erwin ∷ a | r )
146−erwin = inj (Proxy :: Proxy "erwin")
147−type Erwin r = (erwin :: String | r)
147+erwin ∷ ∀ a r. a → Variant (erwin ∷ a | r)
148+erwin = inj (Proxy ∷ Proxy "erwin")
149+
150+type Erwin r = (erwin ∷ String | r)
148151
149152newtype Stringy = Stringy String
153+
150154derive instance Newtype Stringy _
151155derive newtype instance Show Stringy
152156derive newtype instance Eq Stringy
@@ -155,6 +159,7 @@ derive newtype instance WriteForeign Stringy
155159derive newtype instance ReadForeign Stringy
156160
157161newtype Inty = Inty Int
162+
158163derive instance Newtype Inty _
159164derive newtype instance Show Inty
160165derive newtype instance Eq Inty
test/ErrorsSpec.purs+9−8
@@ -22,7 +22,7 @@ spec = describe "Errors" do
2222 describe "are returned at once" do
2323 it "returns multiple errors for object" do
2424 let
25− res :: E (Object Int)
25+ res ∷ E (Object Int)
2626 res = JSON.readJSON """{ "something": "no", "else": true }"""
2727 e1 = ErrorAtProperty "something" (TypeMismatch "Int" "String")
2828 e2 = ErrorAtProperty "else" (TypeMismatch "Int" "Boolean")
@@ -30,7 +30,7 @@ spec = describe "Errors" do
3030
3131 it "returns multiple errors for record" do
3232 let
33− res :: E { a :: Int, b :: String }
33+ res ∷ E { a ∷ Int, b ∷ String }
3434 res = JSON.readJSON """{ "b": true }"""
3535 e1 = ErrorAtProperty "a" (TypeMismatch "Int" "Undefined")
3636 e2 = ErrorAtProperty "b" (TypeMismatch "String" "Boolean")
@@ -38,7 +38,7 @@ spec = describe "Errors" do
3838
3939 it "returns multiple errors for array" do
4040 let
41− res :: E (Array Int)
41+ res ∷ E (Array Int)
4242 res = JSON.readJSON """[1,"a",2,true]"""
4343 e1 = ErrorAtIndex 1 (TypeMismatch "Int" "String")
4444 e2 = ErrorAtIndex 3 (TypeMismatch "Int" "Boolean")
@@ -47,27 +47,28 @@ spec = describe "Errors" do
4747 describe "produces human-friendly errors" do
4848 it "For some object" do
4949 let
50− res :: E (Object Int)
50+ res ∷ E (Object Int)
5151 res = JSON.readJSON """{ "something": "no", "else": true }"""
5252 e1 = "Must provide a value of type 'Int' instead of 'String' at $.something"
5353 e2 = "Must provide a value of type 'Int' instead of 'Boolean' at $.else"
5454 (res # lmap (map renderHumanError >>> Array.fromFoldable))
55− `shouldEqual` (Left [e1, e2])
55+ `shouldEqual` (Left [ e1, e2 ])
5656
5757 it "For deeply nested keys" do
5858 let
59− res :: E { a :: { b :: { c :: { d :: String }}}}
59+ res ∷ E { a ∷ { b ∷ { c ∷ { d ∷ String } } } }
6060 res = JSON.readJSON """{ "a": { "b": { "c": { }}}}"""
6161 e = "Must provide a value of type 'String' at $.a.b.c.d"
6262 (res # lmap (map renderHumanError >>> Array.fromFoldable))
63− `shouldEqual` (Left [e])
63+ `shouldEqual` (Left [ e ])
6464
6565 describe "have the correct JSON path" do
6666 it "empty json" do
6767 (getErrorPath (Proxy ∷ _ {}) "") `shouldEqual` Just [ "$" ]
6868 it "nested json json" do
6969 let
70− xo ="""
70+ xo =
71+ """
7172 { "deeply": { "nested": { "array":
7273 [ { "of": { "values": "hello" } }
7374 , 8
test/GenericsSpec.purs+52−22
@@ -19,13 +19,13 @@ spec = describe "Generics" $ do
1919 describe "Enum" do
2020 describe "MyEnum = Enum1 | Enum2 | Enum3" do
2121 it "roundtrips" do
22− roundtrips (Enum1)
23− roundtrips (Enum3)
22+ roundtrips (Enum1)
23+ roundtrips (Enum3)
2424
2525 describe "works with custom constructor names" do
2626 it "roundtrips" do
27− roundtrips (SomeOtherEnum2)
28− writeJSON (SomeThirdEnum3) `shouldEqual` "\"some_third_enum_3\""
27+ roundtrips (SomeOtherEnum2)
28+ writeJSON (SomeThirdEnum3) `shouldEqual` "\"some_third_enum_3\""
2929
3030 describe "Untagged" do
3131
@@ -54,7 +54,6 @@ spec = describe "Generics" $ do
5454 writeJSON (ATaggedInt 1) `shouldEqual` """{"type":"ATaggedInt","value":1}"""
5555 writeJSON (ATaggedString "Abc") `shouldEqual` """{"type":"ATaggedString","value":"Abc"}"""
5656
57−
5857 describe "data HalfEnum = NotEnum Int | IsEnum" do
5958 it "roundtrips" do
6059 roundtrips (NotEnum 1)
@@ -65,55 +64,86 @@ spec = describe "Generics" $ do
6564 writeJSON (IsEnum) `shouldEqual` """{"kind":"is_enum"}"""
6665
6766data HalfEnum = NotEnum Int | IsEnum
67+
6868derive instance Generic HalfEnum _
6969derive instance Eq HalfEnum
70−instance Show HalfEnum where show = genericShow
71−halfEnumOptions :: GenericTaggedSum.Options
70+instance Show HalfEnum where
71+ show = genericShow
72+
73+halfEnumOptions ∷ GenericTaggedSum.Options
7274halfEnumOptions = { typeTag: "kind", valueTag: "data", toConstructorName: snakeCase }
73−instance ReadForeign HalfEnum where readImpl = genericReadForeignTaggedSum halfEnumOptions
74−instance WriteForeign HalfEnum where writeImpl = genericWriteForeignTaggedSum halfEnumOptions
75+
76+instance ReadForeign HalfEnum where
77+ readImpl = genericReadForeignTaggedSum halfEnumOptions
78+
79+instance WriteForeign HalfEnum where
80+ writeImpl = genericWriteForeignTaggedSum halfEnumOptions
7581
7682data MyEnum = Enum1 | Enum2 | Enum3
7783
7884derive instance Generic MyEnum _
7985derive instance Eq MyEnum
80−instance Show MyEnum where show = genericShow
86+instance Show MyEnum where
87+ show = genericShow
88+
8189instance ReadForeign MyEnum
82− where readImpl = genericReadForeignEnum Enum.defaultOptions
90+ where
91+ readImpl = genericReadForeignEnum Enum.defaultOptions
92+
8393instance WriteForeign MyEnum
84− where writeImpl = genericWriteForeignEnum Enum.defaultOptions
94+ where
95+ writeImpl = genericWriteForeignEnum Enum.defaultOptions
8596
8697data MyEnum2 = SomeEnum2 | SomeOtherEnum2 | SomeThirdEnum3
8798
8899derive instance Generic MyEnum2 _
89100derive instance Eq MyEnum2
90−instance Show MyEnum2 where show = genericShow
101+instance Show MyEnum2 where
102+ show = genericShow
103+
91104instance ReadForeign MyEnum2
92− where readImpl = genericReadForeignEnum { toConstructorName: snakeCase}
105+ where
106+ readImpl = genericReadForeignEnum { toConstructorName: snakeCase }
107+
93108instance WriteForeign MyEnum2
94− where writeImpl = genericWriteForeignEnum { toConstructorName: snakeCase}
109+ where
110+ writeImpl = genericWriteForeignEnum { toConstructorName: snakeCase }
95111
96112data IntOrString = AnInt Int | AString String
113+
97114derive instance Generic IntOrString _
98115derive instance Eq IntOrString
99−instance Show IntOrString where show = genericShow
100−instance ReadForeign IntOrString where readImpl = genericReadForeignUntaggedSum
101−instance WriteForeign IntOrString where writeImpl = genericWriteForeignUntaggedSum
116+instance Show IntOrString where
117+ show = genericShow
118+
119+instance ReadForeign IntOrString where
120+ readImpl = genericReadForeignUntaggedSum
121+
122+instance WriteForeign IntOrString where
123+ writeImpl = genericWriteForeignUntaggedSum
102124
103125data DoubleTrouble = IntAndString Int String
104126
105127derive instance Generic DoubleTrouble _
106128derive instance Eq DoubleTrouble
107−instance Show DoubleTrouble where show = genericShow
108−instance ReadForeign DoubleTrouble where readImpl = genericReadForeignUntaggedProduct
109−instance WriteForeign DoubleTrouble where writeImpl = genericWriteForeignUntaggedProduct
129+instance Show DoubleTrouble where
130+ show = genericShow
131+
132+instance ReadForeign DoubleTrouble where
133+ readImpl = genericReadForeignUntaggedProduct
134+
135+instance WriteForeign DoubleTrouble where
136+ writeImpl = genericWriteForeignUntaggedProduct
110137
111138data IntOrStringTagged = ATaggedInt Int | ATaggedString String
112139
113140derive instance Generic IntOrStringTagged _
114141derive instance Eq IntOrStringTagged
115−instance Show IntOrStringTagged where show = genericShow
142+instance Show IntOrStringTagged where
143+ show = genericShow
144+
116145instance ReadForeign IntOrStringTagged where
117146 readImpl = genericReadForeignTaggedSum defaultOptions
147+
118148instance WriteForeign IntOrStringTagged where
119149 writeImpl = genericWriteForeignTaggedSum defaultOptions
test/Main.purs+2−2
@@ -8,7 +8,7 @@ import Test.Spec.Discovery (discover)
88import Test.Spec.Reporter (consoleReporter)
99import Test.Spec.Runner (runSpec)
1010
11−main :: Effect Unit
11+main ∷ Effect Unit
1212main = launchAff_ $
1313 discover """\..*Spec"""
14− >>= runSpec [consoleReporter]
14+ >>= runSpec [ consoleReporter ]