git.iko.soy/rowtype-yoga/purescript-yoga-json
on main help sign in
38 files changed+5121−976
since splitsnapshots
unifiedsplit
.github/workflows/ci.yml+7−5 .gitignore+5 .nycrc.json+8 .tidyrc.json+1−1 .vscode/settings.json+3 CHANGELOG.md+34 README.md+153−5 bower.json−28 docs/simple-json-migration.md+47 package-lock.json+1157 package.json+11 packages.dhall−5 spago.dhall−27 spago.lock+1747 spago.yaml+52 src/JSON.js−5 src/JSON.purs−394 src/Yoga/JSON.js+19 src/Yoga/JSON.purs+683 src/Yoga/JSON/Derive.purs+13 src/Yoga/JSON/Error.purs+56 src/Yoga/JSON/Generics.purs+8 src/Yoga/JSON/Generics/EnumSumRep.purs+65 src/Yoga/JSON/Generics/TaggedSumRep.purs+131 src/Yoga/JSON/Generics/UntaggedProductRep.purs+86 src/Yoga/JSON/Generics/UntaggedSumRep.purs+76 src/Yoga/JSON/Variant.purs+197 test.dhall−9 test/BasicsSpec.purs+257 test/EnumSumGeneric.purs−66 test/ErrorsSpec.purs+84 test/Generic.purs−69 test/GenericsSpec.purs+149 test/Inferred.purs−52 test/Main.purs+10−151 test/QuickStart.purs−130 test/Util.purs+20−29 test/WriteViaSpec.purs+42
.github/workflows/ci.yml+7−5
@@ -13,13 +13,15 @@ jobs:
1313 - uses: actions/checkout@v2
1414
1515 - uses: purescript-contrib/setup-purescript@main
16+ with:
17+ spago: "unstable"
1618
1719 - uses: actions/setup-node@v2
1820 with:
19− node-version: "14"
21+ node-version: "20"
2022
2123 - name: Cache PureScript dependencies
22− uses: actions/cache@v2
24+ uses: actions/cache@v4
2325 # This cache uses the .dhall files to know when it should reinstall
2426 # and rebuild packages. It caches both the installed packages from
2527 # the `.spago` directory and compilation artifacts from the `output`
@@ -27,11 +29,11 @@ jobs:
2729 # have changed. If you do not want to cache compiled output, remove
2830 # the `output` path.
2931 with:
30− key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }}
32+ key: ${{ runner.os }}-spago-${{ hashFiles('**/*.yaml') }}
3133 path: |
3234 .spago
3335 output
34−
36+ - run: npm install
3537 - run: spago build
3638
37− - run: spago -x test.dhall test
39+ - run: npm run coverage
.gitignore+5
@@ -6,3 +6,8 @@
66/.purs*
77/.psa*
88/.spago/
9+/.nyc_output/
10+/coverage/
11+/.idea/
12+.spec-results
13+.DS_Store
.nycrc.jsonnew file+8
@@ -0,0 +1,8 @@
1+{
2+ "all": true,
3+ "extension": [".purs"],
4+ "include": [ "src/**/*.purs"],
5+ "exclude": [ "src/Yoga/JSON/Generics.purs"],
6+ "excludeAfterRemap": true,
7+ "sourceMap": true
8+}
.tidyrc.json+1−1
@@ -6,5 +6,5 @@
66 "ribbon": 1,
77 "typeArrowPlacement": "last",
88 "unicode": "always",
9− "width": 80
9+ "width": 160
1010}
.vscode/settings.jsonnew file+3
@@ -0,0 +1,3 @@
1+{
2+ "purescript.buildCommand": "spago -x test.dhall build --purs-args --json-errors"
3+}
CHANGELOG.mdnew file+34
@@ -0,0 +1,34 @@
1+# Changelog
2+
3+## v5.2.2
4+
5+- Fix variant decoding selecting absent branches whose payload decoders accept missing values, such as empty records and `Maybe`. Branches now require an own property matching their label.
6+
7+## v4.0.1
8+
9+- Allow the type of `read*` functions to be visibly applied (#24 by @postsolar)
10+
11+## v4.0.0
12+- Replace `bigints` dependency with `js-bigints` so that no more external npm dependency is needed (#11 by @sigma-andex)
13+
14+## v3.0.2
15+- Minor internal updates
16+- Improve error handling
17+- Add codecs and `JSDate` (@i-am-the-slime)
18+
19+## v3.0.1
20+- Readme update
21+
22+## v3.0.0
23+- Add codecs for enums and more instances (#9 by @i-am-the-slime)
24+- Add codecs for `Map` and `Map` with newtype (#4 by @i-am-the-slime)
25+
26+## v2.0.0
27+- Add support for `BigInt` (#5 by @sigma-andex)
28+- Improve Generics (#3 by @i-am-the-slime)
29+
30+## v1.0.1
31+- Add Generics (#2 by @i-am-the-slime)
32+
33+## v1.0.0
34+- Initial commit
README.md+153−5
@@ -1,14 +1,162 @@
1−# 🐏👑 purescript-json
1+# purescript-yoga-json
22
3−**Note**: This is a fork [simple-json](https://github.com/justinwoo/purescript-simple-json) ([MIT Licence](./LICENSE/simple-json.LICENSE)).
3+`yoga-json` is a light-weight and simple json library for purescript.
44
5+**Note**: This library was initially forked from the amazing [simple-json](https://github.com/justinwoo/purescript-simple-json) ([MIT Licence](./LICENSE/simple-json.LICENSE)).
6+Replace your imports from `Simple.JSON` to `Yoga.JSON` to migrate.
57## Table of Contents
8+* [features](#features)
9+* [installation](#installation)
610* [usage](#usage)
7−* [migrate from `simple-json`](#migrate-from-purescript-simple-json)
11+
12+## Features
13+
14+* 😌 simple and easy to use json codecs
15+* 🪶 light-weight
16+* 🤖 built-in support for many common types (`Sum` types, Tuples, BigInts, Maps, JSDate, DateTime, Eithers, NonEmptyStrings )
17+* 🖍 human-friendly error reporting
18+
19+## Installation
20+
21+```
22+spago install yoga-json
23+```
824
925## Usage
1026
27+`purescript-yoga-json` basically provides two functions `writeJSON` and `readJSON`.
28+
29+Use `writeJSON` to serialise a type to a JSON string:
30+
31+```purescript
32+import Yoga.JSON as JSON
33+
34+serialised :: String
35+serialised =
36+ JSON.writeJSON { first_name: "Lola", last_name: "Flores" }
37+ -- {"last_name":"Flores","first_name":"Lola"}
38+```
39+
40+Use `readJSON` to deserialise a JSON string:
41+```purescript
42+import Yoga.JSON as JSON
43+
44+deserialised :: Either MultipleErrors { first_name :: String, last_name :: String }
45+deserialised = JSON.readJSON """{ "first_name": "Lola", "last_name": "Flores" }"""
46+-- Right { first_name: "Lola", last_name: "Flores" }
47+```
48+
49+As the parsing can fail, `readJSON` returns an `Either`, potentially containing a `Left` data constructor with `MultipleErrors`. If you don't care about the specific errors, you can use `readJSON_`, which returns a `Maybe`:
50+
51+```purescript
52+deserialised :: Maybe { first_name :: String, last_name :: String }
53+deserialised = JSON.readJSON_ """{ "first_name": "Lola", "last_name": "Flores" }"""
54+-- Just { first_name: "Lola", last_name: "Flores" }
55+```
56+
57+
58+## Sum types
59+
60+`purescript-yoga-json` provides utility functions to easily generate serialisers and deserialisers for your sum types.
61+
62+Let's start with a simple example of a sum type where our data constructors do not contain any further values:
63+
64+```
65+import Data.Either (Either)
66+import Data.Generic.Rep (class Generic)
67+import Yoga.JSON as JSON
68+import Yoga.JSON.Generics (genericReadForeignEnum, genericWriteForeignEnum)
69+import Yoga.JSON.Generics.EnumSumRep as Enum
70+
71+data MyEnum = Enum1 | Enum2 | Enum3
72+```
73+
74+Now, we need to derive a `Generic` instance for it:
75+
76+```
77+derive instance Generic MyEnum _
78+-- and optionally a Show instance
79+instance Show MyEnum where
80+ show = genericShow
81+```
82+
83+Next, we define a `WriteForeign` instance and implement the `writeImpl` function using `genericWriteForeignEnum Enum.defaultOptions`.
84+
85+```purescript
86+instance WriteForeign MyEnum
87+ where
88+ writeImpl = genericWriteForeignEnum Enum.defaultOptions
89+```
90+
91+Similarly, we implement the `ReadForeign` instance using `genericReadForeignEnum Enum.defaultOptions`
92+```purescript
93+instance ReadForeign MyEnum
94+ where
95+ readImpl = genericReadForeignEnum Enum.defaultOptions
96+```
97+
98+That's all, we can now serialise our data type:
99+```purescript
100+serialised = writeJSON { "myEnum": Enum3 }
101+-- {"myEnum":"Enum3"}
102+```
103+and deserialise it:
104+```purescript
105+deserialised :: E { "myEnum" :: MyEnum }
106+deserialised = readJSON serialised
107+-- Right { myEnum: Enum3 }
108+```
109+
110+### Writing custom codecs
111+
112+In order to write your own, custom codecs you will need to provide instances for `WriteForeign` and `ReadForeign`.
113+
114+Let's see an example. We define a simple data type `TrafficLight` that has three data constructors `Red`, `Yellow` and `Green`:
115+```purescript
116+data TrafficLight = Red | Yellow | Green
117+```
118+We would like to serialise these constructors as lower case strings `"red"`, `"yellow"` and `"green"`.
119+
120+First we need to provide an implementation for the `WriteForeign` type class, that tells `yoga-json` how to serialise the type. We pattern match on the three different data constructors and write them as the three `String`s red, yellow and green, using the same `writeImpl` function:
121+```purescript
122+instance WriteForeign TrafficLight where
123+ writeImpl Red = writeImpl "red"
124+ writeImpl Yellow = writeImpl "yellow"
125+ writeImpl Green = writeImpl "green"
126+```
127+This works, because `yoga-json` already knows how to serialise a `String`.
128+
129+Similarly, we need to provide an implementation for the `ReadForeign` type class, that tells `yoga-json` how to deserialise the type. We start by deserialising into a primitive type, typically a String or an Object, and then convert it to our desired Purescript type.
130+
131+Since we don't know the input `String`, it might contain invalid data and therefore deserialisation might fail. `yoga-json` uses the `ExceptT` monad to reflect this. We can return valid values using `pure` and `fail` on invalid values:
132+
133+```purescript
134+instance ReadForeign TrafficLight where
135+ readImpl json = do
136+ -- deserialise into a string
137+ str :: String <- readImpl json
138+ -- now we pattern match on our valid types
139+ case str of
140+ "red" -> pure Red
141+ "yellow" -> pure Yellow
142+ "green" -> pure Green
143+ -- and fail if we get an invalid type
144+ other -> fail $ ForeignError $ "Failed to parse " <> other <> " as TrafficLight"
145+```
146+
147+Now we can serialise our data type:
148+```purescript
149+serialised = writeJSON { "trafficLight": Red }
150+-- {"trafficLight":"red"}
151+```
11152
12−## Migrate from `purescript-simple-json`
153+and deserialise it:
154+```purescript
155+deserialised :: E { "trafficLight" :: TrafficLight }
156+deserialised = readJSON """{ "trafficLight": "green" }"""
157+-- Right { trafficLight: Green }
13158
14−`purescript-json` is a drop-in replacement for `purescript-simple-json`. Just change the imports from `Simple.JSON` to `JSON`.
159+deserialisedUnknown :: E { "trafficLight" :: TrafficLight }
160+deserialisedUnknown = readJSON """{ "trafficLight": "purple" }"""
161+-- Left (NonEmptyList (NonEmpty (ErrorAtProperty "trafficLight" (ForeignError "Failed to parse purple as TrafficLight")) Nil))
162+```
bower.jsondeleted−28
@@ -1,28 +0,0 @@
1−{
2− "name": "purescript-json",
3− "license": "MIT",
4− "repository": {
5− "type": "git",
6− "url": "git://github.com/rowtype-yoga/purescript-json.git"
7− },
8− "ignore": [
9− "**/.*",
10− "node_modules",
11− "bower_components",
12− "output"
13− ],
14− "dependencies": {
15− "purescript-prelude": "^6.0.0",
16− "purescript-typelevel-prelude": "^7.0.0",
17− "purescript-record": "^4.0.0",
18− "purescript-variant": "^8.0.0",
19− "purescript-nullable": "^6.0.0",
20− "purescript-foreign-object": "^4.0.0",
21− "purescript-foreign": "^7.0.0",
22− "purescript-exceptions": "^6.0.0",
23− "purescript-arrays": "^7.0.0"
24− },
25− "devDependencies": {
26− "purescript-assert": "^6.0.0"
27− }
28−}
docs/simple-json-migration.mdnew file+47
@@ -0,0 +1,47 @@
1+# Migrate from `purescript-simple-json`
2+
3+`purescript-yoga-json` is a fork of [simple-json](https://github.com/justinwoo/purescript-simple-json) ([MIT Licence](./LICENSE/simple-json.LICENSE)) and almost (read below if you use variants) a drop-in replacement for `purescript-simple-json`. Just change the imports from `Simple.JSON` to `Yoga.JSON`.
4+
5+## Additions over `simple-json`
6+
7+### Errors
8+yoga-json will actually report multiple errors at once in the case of records, objects, and arrays.
9+There's also a way to make errors more readable with `renderHumanError`:
10+(e.g. `Must provide a value of type 'Int' instead of 'Object' at $.a.b.c.d[1]`)
11+
12+
13+### Tuples
14+There is an inbuilt codec for `Tuple`s thanks to @ursi
15+`yoga-json` represents tuples as arrays in JSON.
16+
17+### Eithers
18+There is an inbuilt codec for `Either`s.
19+`yoga-json` represents eithers as objects with a `type` and a `value` tag in JSON.
20+
21+### JSDate and DateTime
22+Both are encoded as ISO8601 strings as spat out by `JSDate.toISOString`.
23+
24+### Generics
25+It includes @justinwoo's codecs for en- and decoding generics inspired by
26+[simple-json-generics](https://github.com/justinwoo/purescript-simple-json-generics)
27+
28+It is possible to customise the representation of enums, tagged sum types, and untagged sum types via options.
29+
30+### BigInts
31+There is an inbuilt codec for `BigInt`. Writing a `BigInt` however will result in a String. This is a current limitation of JavaScript and the only way around it - it seems - is writing your own JSON.stringify method (which is out of scope of this project).
32+
33+## Differences to `simple-json`
34+
35+### 💣 Variant codec
36+If you want to emulate `simple-json`'s format you may use the newtype `TaggedVariant`
37+
38+```purescript
39+type YourVariantRow = ( a :: Int, b :: String )
40+type YourVariant = Variant YourVariantRow
41+x :: YourVariant
42+x = inj (Proxy :: Proxy "a") 5
43+-- encoded = writeJSON x
44+-- ^ Let's say you had this before
45+-- You can now do:
46+encoded = writeJSON (TaggedVariant "type" "value" x)
47+```
package-lock.jsonnew file+1157
@@ -0,0 +1,1157 @@
1+{
2+ "name": "purescript-yoga-json",
3+ "lockfileVersion": 2,
4+ "requires": true,
5+ "packages": {
6+ "": {
7+ "name": "purescript-yoga-json",
8+ "devDependencies": {
9+ "c8": "^7.12.0",
10+ "rimraf": "^3.0.2"
11+ }
12+ },
13+ "node_modules/@bcoe/v8-coverage": {
14+ "version": "0.2.3",
15+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
16+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
17+ "dev": true
18+ },
19+ "node_modules/@istanbuljs/schema": {
20+ "version": "0.1.3",
21+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
22+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
23+ "dev": true,
24+ "engines": {
25+ "node": ">=8"
26+ }
27+ },
28+ "node_modules/@jridgewell/resolve-uri": {
29+ "version": "3.1.0",
30+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
31+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
32+ "dev": true,
33+ "engines": {
34+ "node": ">=6.0.0"
35+ }
36+ },
37+ "node_modules/@jridgewell/sourcemap-codec": {
38+ "version": "1.4.14",
39+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
40+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
41+ "dev": true
42+ },
43+ "node_modules/@jridgewell/trace-mapping": {
44+ "version": "0.3.17",
45+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
46+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
47+ "dev": true,
48+ "dependencies": {
49+ "@jridgewell/resolve-uri": "3.1.0",
50+ "@jridgewell/sourcemap-codec": "1.4.14"
51+ }
52+ },
53+ "node_modules/@types/istanbul-lib-coverage": {
54+ "version": "2.0.4",
55+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
56+ "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
57+ "dev": true
58+ },
59+ "node_modules/ansi-regex": {
60+ "version": "5.0.1",
61+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
62+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
63+ "dev": true,
64+ "engines": {
65+ "node": ">=8"
66+ }
67+ },
68+ "node_modules/ansi-styles": {
69+ "version": "4.3.0",
70+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
71+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
72+ "dev": true,
73+ "dependencies": {
74+ "color-convert": "^2.0.1"
75+ },
76+ "engines": {
77+ "node": ">=8"
78+ },
79+ "funding": {
80+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
81+ }
82+ },
83+ "node_modules/balanced-match": {
84+ "version": "1.0.2",
85+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
86+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
87+ "dev": true
88+ },
89+ "node_modules/brace-expansion": {
90+ "version": "1.1.11",
91+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
92+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
93+ "dev": true,
94+ "dependencies": {
95+ "balanced-match": "^1.0.0",
96+ "concat-map": "0.0.1"
97+ }
98+ },
99+ "node_modules/c8": {
100+ "version": "7.12.0",
101+ "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz",
102+ "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==",
103+ "dev": true,
104+ "dependencies": {
105+ "@bcoe/v8-coverage": "^0.2.3",
106+ "@istanbuljs/schema": "^0.1.3",
107+ "find-up": "^5.0.0",
108+ "foreground-child": "^2.0.0",
109+ "istanbul-lib-coverage": "^3.2.0",
110+ "istanbul-lib-report": "^3.0.0",
111+ "istanbul-reports": "^3.1.4",
112+ "rimraf": "^3.0.2",
113+ "test-exclude": "^6.0.0",
114+ "v8-to-istanbul": "^9.0.0",
115+ "yargs": "^16.2.0",
116+ "yargs-parser": "^20.2.9"
117+ },
118+ "bin": {
119+ "c8": "bin/c8.js"
120+ },
121+ "engines": {
122+ "node": ">=10.12.0"
123+ }
124+ },
125+ "node_modules/cliui": {
126+ "version": "7.0.4",
127+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
128+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
129+ "dev": true,
130+ "dependencies": {
131+ "string-width": "^4.2.0",
132+ "strip-ansi": "^6.0.0",
133+ "wrap-ansi": "^7.0.0"
134+ }
135+ },
136+ "node_modules/color-convert": {
137+ "version": "2.0.1",
138+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
139+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
140+ "dev": true,
141+ "dependencies": {
142+ "color-name": "~1.1.4"
143+ },
144+ "engines": {
145+ "node": ">=7.0.0"
146+ }
147+ },
148+ "node_modules/color-name": {
149+ "version": "1.1.4",
150+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
151+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
152+ "dev": true
153+ },
154+ "node_modules/concat-map": {
155+ "version": "0.0.1",
156+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
157+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
158+ "dev": true
159+ },
160+ "node_modules/convert-source-map": {
161+ "version": "1.9.0",
162+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
163+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
164+ "dev": true
165+ },
166+ "node_modules/cross-spawn": {
167+ "version": "7.0.6",
168+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
169+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
170+ "dev": true,
171+ "license": "MIT",
172+ "dependencies": {
173+ "path-key": "^3.1.0",
174+ "shebang-command": "^2.0.0",
175+ "which": "^2.0.1"
176+ },
177+ "engines": {
178+ "node": ">= 8"
179+ }
180+ },
181+ "node_modules/emoji-regex": {
182+ "version": "8.0.0",
183+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
184+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
185+ "dev": true
186+ },
187+ "node_modules/escalade": {
188+ "version": "3.1.1",
189+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
190+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
191+ "dev": true,
192+ "engines": {
193+ "node": ">=6"
194+ }
195+ },
196+ "node_modules/find-up": {
197+ "version": "5.0.0",
198+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
199+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
200+ "dev": true,
201+ "dependencies": {
202+ "locate-path": "^6.0.0",
203+ "path-exists": "^4.0.0"
204+ },
205+ "engines": {
206+ "node": ">=10"
207+ },
208+ "funding": {
209+ "url": "https://github.com/sponsors/sindresorhus"
210+ }
211+ },
212+ "node_modules/foreground-child": {
213+ "version": "2.0.0",
214+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
215+ "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
216+ "dev": true,
217+ "dependencies": {
218+ "cross-spawn": "^7.0.0",
219+ "signal-exit": "^3.0.2"
220+ },
221+ "engines": {
222+ "node": ">=8.0.0"
223+ }
224+ },
225+ "node_modules/fs.realpath": {
226+ "version": "1.0.0",
227+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
228+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
229+ "dev": true
230+ },
231+ "node_modules/get-caller-file": {
232+ "version": "2.0.5",
233+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
234+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
235+ "dev": true,
236+ "engines": {
237+ "node": "6.* || 8.* || >= 10.*"
238+ }
239+ },
240+ "node_modules/glob": {
241+ "version": "7.2.3",
242+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
243+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
244+ "dev": true,
245+ "dependencies": {
246+ "fs.realpath": "^1.0.0",
247+ "inflight": "^1.0.4",
248+ "inherits": "2",
249+ "minimatch": "^3.1.1",
250+ "once": "^1.3.0",
251+ "path-is-absolute": "^1.0.0"
252+ },
253+ "engines": {
254+ "node": "*"
255+ },
256+ "funding": {
257+ "url": "https://github.com/sponsors/isaacs"
258+ }
259+ },
260+ "node_modules/has-flag": {
261+ "version": "4.0.0",
262+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
263+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
264+ "dev": true,
265+ "engines": {
266+ "node": ">=8"
267+ }
268+ },
269+ "node_modules/html-escaper": {
270+ "version": "2.0.2",
271+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
272+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
273+ "dev": true
274+ },
275+ "node_modules/inflight": {
276+ "version": "1.0.6",
277+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
278+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
279+ "dev": true,
280+ "dependencies": {
281+ "once": "^1.3.0",
282+ "wrappy": "1"
283+ }
284+ },
285+ "node_modules/inherits": {
286+ "version": "2.0.4",
287+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
288+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
289+ "dev": true
290+ },
291+ "node_modules/is-fullwidth-code-point": {
292+ "version": "3.0.0",
293+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
294+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
295+ "dev": true,
296+ "engines": {
297+ "node": ">=8"
298+ }
299+ },
300+ "node_modules/isexe": {
301+ "version": "2.0.0",
302+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
303+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
304+ "dev": true
305+ },
306+ "node_modules/istanbul-lib-coverage": {
307+ "version": "3.2.0",
308+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
309+ "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
310+ "dev": true,
311+ "engines": {
312+ "node": ">=8"
313+ }
314+ },
315+ "node_modules/istanbul-lib-report": {
316+ "version": "3.0.0",
317+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
318+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
319+ "dev": true,
320+ "dependencies": {
321+ "istanbul-lib-coverage": "^3.0.0",
322+ "make-dir": "^3.0.0",
323+ "supports-color": "^7.1.0"
324+ },
325+ "engines": {
326+ "node": ">=8"
327+ }
328+ },
329+ "node_modules/istanbul-reports": {
330+ "version": "3.1.5",
331+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
332+ "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
333+ "dev": true,
334+ "dependencies": {
335+ "html-escaper": "^2.0.0",
336+ "istanbul-lib-report": "^3.0.0"
337+ },
338+ "engines": {
339+ "node": ">=8"
340+ }
341+ },
342+ "node_modules/locate-path": {
343+ "version": "6.0.0",
344+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
345+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
346+ "dev": true,
347+ "dependencies": {
348+ "p-locate": "^5.0.0"
349+ },
350+ "engines": {
351+ "node": ">=10"
352+ },
353+ "funding": {
354+ "url": "https://github.com/sponsors/sindresorhus"
355+ }
356+ },
357+ "node_modules/make-dir": {
358+ "version": "3.1.0",
359+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
360+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
361+ "dev": true,
362+ "dependencies": {
363+ "semver": "^6.0.0"
364+ },
365+ "engines": {
366+ "node": ">=8"
367+ },
368+ "funding": {
369+ "url": "https://github.com/sponsors/sindresorhus"
370+ }
371+ },
372+ "node_modules/minimatch": {
373+ "version": "3.1.2",
374+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
375+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
376+ "dev": true,
377+ "dependencies": {
378+ "brace-expansion": "^1.1.7"
379+ },
380+ "engines": {
381+ "node": "*"
382+ }
383+ },
384+ "node_modules/once": {
385+ "version": "1.4.0",
386+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
387+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
388+ "dev": true,
389+ "dependencies": {
390+ "wrappy": "1"
391+ }
392+ },
393+ "node_modules/p-limit": {
394+ "version": "3.1.0",
395+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
396+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
397+ "dev": true,
398+ "dependencies": {
399+ "yocto-queue": "^0.1.0"
400+ },
401+ "engines": {
402+ "node": ">=10"
403+ },
404+ "funding": {
405+ "url": "https://github.com/sponsors/sindresorhus"
406+ }
407+ },
408+ "node_modules/p-locate": {
409+ "version": "5.0.0",
410+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
411+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
412+ "dev": true,
413+ "dependencies": {
414+ "p-limit": "^3.0.2"
415+ },
416+ "engines": {
417+ "node": ">=10"
418+ },
419+ "funding": {
420+ "url": "https://github.com/sponsors/sindresorhus"
421+ }
422+ },
423+ "node_modules/path-exists": {
424+ "version": "4.0.0",
425+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
426+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
427+ "dev": true,
428+ "engines": {
429+ "node": ">=8"
430+ }
431+ },
432+ "node_modules/path-is-absolute": {
433+ "version": "1.0.1",
434+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
435+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
436+ "dev": true,
437+ "engines": {
438+ "node": ">=0.10.0"
439+ }
440+ },
441+ "node_modules/path-key": {
442+ "version": "3.1.1",
443+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
444+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
445+ "dev": true,
446+ "engines": {
447+ "node": ">=8"
448+ }
449+ },
450+ "node_modules/require-directory": {
451+ "version": "2.1.1",
452+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
453+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
454+ "dev": true,
455+ "engines": {
456+ "node": ">=0.10.0"
457+ }
458+ },
459+ "node_modules/rimraf": {
460+ "version": "3.0.2",
461+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
462+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
463+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
464+ "dev": true,
465+ "license": "ISC",
466+ "dependencies": {
467+ "glob": "^7.1.3"
468+ },
469+ "bin": {
470+ "rimraf": "bin.js"
471+ },
472+ "funding": {
473+ "url": "https://github.com/sponsors/isaacs"
474+ }
475+ },
476+ "node_modules/semver": {
477+ "version": "6.3.1",
478+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
479+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
480+ "dev": true,
481+ "license": "ISC",
482+ "bin": {
483+ "semver": "bin/semver.js"
484+ }
485+ },
486+ "node_modules/shebang-command": {
487+ "version": "2.0.0",
488+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
489+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
490+ "dev": true,
491+ "dependencies": {
492+ "shebang-regex": "^3.0.0"
493+ },
494+ "engines": {
495+ "node": ">=8"
496+ }
497+ },
498+ "node_modules/shebang-regex": {
499+ "version": "3.0.0",
500+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
501+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
502+ "dev": true,
503+ "engines": {
504+ "node": ">=8"
505+ }
506+ },
507+ "node_modules/signal-exit": {
508+ "version": "3.0.7",
509+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
510+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
511+ "dev": true
512+ },
513+ "node_modules/string-width": {
514+ "version": "4.2.3",
515+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
516+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
517+ "dev": true,
518+ "dependencies": {
519+ "emoji-regex": "^8.0.0",
520+ "is-fullwidth-code-point": "^3.0.0",
521+ "strip-ansi": "^6.0.1"
522+ },
523+ "engines": {
524+ "node": ">=8"
525+ }
526+ },
527+ "node_modules/strip-ansi": {
528+ "version": "6.0.1",
529+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
530+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
531+ "dev": true,
532+ "dependencies": {
533+ "ansi-regex": "^5.0.1"
534+ },
535+ "engines": {
536+ "node": ">=8"
537+ }
538+ },
539+ "node_modules/supports-color": {
540+ "version": "7.2.0",
541+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
542+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
543+ "dev": true,
544+ "dependencies": {
545+ "has-flag": "^4.0.0"
546+ },
547+ "engines": {
548+ "node": ">=8"
549+ }
550+ },
551+ "node_modules/test-exclude": {
552+ "version": "6.0.0",
553+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
554+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
555+ "dev": true,
556+ "dependencies": {
557+ "@istanbuljs/schema": "^0.1.2",
558+ "glob": "^7.1.4",
559+ "minimatch": "^3.0.4"
560+ },
561+ "engines": {
562+ "node": ">=8"
563+ }
564+ },
565+ "node_modules/v8-to-istanbul": {
566+ "version": "9.0.1",
567+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
568+ "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
569+ "dev": true,
570+ "dependencies": {
571+ "@jridgewell/trace-mapping": "^0.3.12",
572+ "@types/istanbul-lib-coverage": "^2.0.1",
573+ "convert-source-map": "^1.6.0"
574+ },
575+ "engines": {
576+ "node": ">=10.12.0"
577+ }
578+ },
579+ "node_modules/which": {
580+ "version": "2.0.2",
581+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
582+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
583+ "dev": true,
584+ "dependencies": {
585+ "isexe": "^2.0.0"
586+ },
587+ "bin": {
588+ "node-which": "bin/node-which"
589+ },
590+ "engines": {
591+ "node": ">= 8"
592+ }
593+ },
594+ "node_modules/wrap-ansi": {
595+ "version": "7.0.0",
596+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
597+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
598+ "dev": true,
599+ "dependencies": {
600+ "ansi-styles": "^4.0.0",
601+ "string-width": "^4.1.0",
602+ "strip-ansi": "^6.0.0"
603+ },
604+ "engines": {
605+ "node": ">=10"
606+ },
607+ "funding": {
608+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
609+ }
610+ },
611+ "node_modules/wrappy": {
612+ "version": "1.0.2",
613+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
614+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
615+ "dev": true
616+ },
617+ "node_modules/y18n": {
618+ "version": "5.0.8",
619+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
620+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
621+ "dev": true,
622+ "engines": {
623+ "node": ">=10"
624+ }
625+ },
626+ "node_modules/yargs": {
627+ "version": "16.2.0",
628+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
629+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
630+ "dev": true,
631+ "dependencies": {
632+ "cliui": "^7.0.2",
633+ "escalade": "^3.1.1",
634+ "get-caller-file": "^2.0.5",
635+ "require-directory": "^2.1.1",
636+ "string-width": "^4.2.0",
637+ "y18n": "^5.0.5",
638+ "yargs-parser": "^20.2.2"
639+ },
640+ "engines": {
641+ "node": ">=10"
642+ }
643+ },
644+ "node_modules/yargs-parser": {
645+ "version": "20.2.9",
646+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
647+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
648+ "dev": true,
649+ "engines": {
650+ "node": ">=10"
651+ }
652+ },
653+ "node_modules/yocto-queue": {
654+ "version": "0.1.0",
655+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
656+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
657+ "dev": true,
658+ "engines": {
659+ "node": ">=10"
660+ },
661+ "funding": {
662+ "url": "https://github.com/sponsors/sindresorhus"
663+ }
664+ }
665+ },
666+ "dependencies": {
667+ "@bcoe/v8-coverage": {
668+ "version": "0.2.3",
669+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
670+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
671+ "dev": true
672+ },
673+ "@istanbuljs/schema": {
674+ "version": "0.1.3",
675+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
676+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
677+ "dev": true
678+ },
679+ "@jridgewell/resolve-uri": {
680+ "version": "3.1.0",
681+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
682+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
683+ "dev": true
684+ },
685+ "@jridgewell/sourcemap-codec": {
686+ "version": "1.4.14",
687+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
688+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
689+ "dev": true
690+ },
691+ "@jridgewell/trace-mapping": {
692+ "version": "0.3.17",
693+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
694+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
695+ "dev": true,
696+ "requires": {
697+ "@jridgewell/resolve-uri": "3.1.0",
698+ "@jridgewell/sourcemap-codec": "1.4.14"
699+ }
700+ },
701+ "@types/istanbul-lib-coverage": {
702+ "version": "2.0.4",
703+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
704+ "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
705+ "dev": true
706+ },
707+ "ansi-regex": {
708+ "version": "5.0.1",
709+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
710+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
711+ "dev": true
712+ },
713+ "ansi-styles": {
714+ "version": "4.3.0",
715+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
716+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
717+ "dev": true,
718+ "requires": {
719+ "color-convert": "^2.0.1"
720+ }
721+ },
722+ "balanced-match": {
723+ "version": "1.0.2",
724+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
725+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
726+ "dev": true
727+ },
728+ "brace-expansion": {
729+ "version": "1.1.11",
730+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
731+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
732+ "dev": true,
733+ "requires": {
734+ "balanced-match": "^1.0.0",
735+ "concat-map": "0.0.1"
736+ }
737+ },
738+ "c8": {
739+ "version": "7.12.0",
740+ "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz",
741+ "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==",
742+ "dev": true,
743+ "requires": {
744+ "@bcoe/v8-coverage": "^0.2.3",
745+ "@istanbuljs/schema": "^0.1.3",
746+ "find-up": "^5.0.0",
747+ "foreground-child": "^2.0.0",
748+ "istanbul-lib-coverage": "^3.2.0",
749+ "istanbul-lib-report": "^3.0.0",
750+ "istanbul-reports": "^3.1.4",
751+ "rimraf": "^3.0.2",
752+ "test-exclude": "^6.0.0",
753+ "v8-to-istanbul": "^9.0.0",
754+ "yargs": "^16.2.0",
755+ "yargs-parser": "^20.2.9"
756+ }
757+ },
758+ "cliui": {
759+ "version": "7.0.4",
760+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
761+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
762+ "dev": true,
763+ "requires": {
764+ "string-width": "^4.2.0",
765+ "strip-ansi": "^6.0.0",
766+ "wrap-ansi": "^7.0.0"
767+ }
768+ },
769+ "color-convert": {
770+ "version": "2.0.1",
771+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
772+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
773+ "dev": true,
774+ "requires": {
775+ "color-name": "~1.1.4"
776+ }
777+ },
778+ "color-name": {
779+ "version": "1.1.4",
780+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
781+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
782+ "dev": true
783+ },
784+ "concat-map": {
785+ "version": "0.0.1",
786+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
787+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
788+ "dev": true
789+ },
790+ "convert-source-map": {
791+ "version": "1.9.0",
792+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
793+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
794+ "dev": true
795+ },
796+ "cross-spawn": {
797+ "version": "7.0.6",
798+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
799+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
800+ "dev": true,
801+ "requires": {
802+ "path-key": "^3.1.0",
803+ "shebang-command": "^2.0.0",
804+ "which": "^2.0.1"
805+ }
806+ },
807+ "emoji-regex": {
808+ "version": "8.0.0",
809+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
810+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
811+ "dev": true
812+ },
813+ "escalade": {
814+ "version": "3.1.1",
815+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
816+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
817+ "dev": true
818+ },
819+ "find-up": {
820+ "version": "5.0.0",
821+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
822+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
823+ "dev": true,
824+ "requires": {
825+ "locate-path": "^6.0.0",
826+ "path-exists": "^4.0.0"
827+ }
828+ },
829+ "foreground-child": {
830+ "version": "2.0.0",
831+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
832+ "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
833+ "dev": true,
834+ "requires": {
835+ "cross-spawn": "^7.0.0",
836+ "signal-exit": "^3.0.2"
837+ }
838+ },
839+ "fs.realpath": {
840+ "version": "1.0.0",
841+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
842+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
843+ "dev": true
844+ },
845+ "get-caller-file": {
846+ "version": "2.0.5",
847+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
848+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
849+ "dev": true
850+ },
851+ "glob": {
852+ "version": "7.2.3",
853+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
854+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
855+ "dev": true,
856+ "requires": {
857+ "fs.realpath": "^1.0.0",
858+ "inflight": "^1.0.4",
859+ "inherits": "2",
860+ "minimatch": "^3.1.1",
861+ "once": "^1.3.0",
862+ "path-is-absolute": "^1.0.0"
863+ }
864+ },
865+ "has-flag": {
866+ "version": "4.0.0",
867+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
868+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
869+ "dev": true
870+ },
871+ "html-escaper": {
872+ "version": "2.0.2",
873+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
874+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
875+ "dev": true
876+ },
877+ "inflight": {
878+ "version": "1.0.6",
879+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
880+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
881+ "dev": true,
882+ "requires": {
883+ "once": "^1.3.0",
884+ "wrappy": "1"
885+ }
886+ },
887+ "inherits": {
888+ "version": "2.0.4",
889+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
890+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
891+ "dev": true
892+ },
893+ "is-fullwidth-code-point": {
894+ "version": "3.0.0",
895+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
896+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
897+ "dev": true
898+ },
899+ "isexe": {
900+ "version": "2.0.0",
901+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
902+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
903+ "dev": true
904+ },
905+ "istanbul-lib-coverage": {
906+ "version": "3.2.0",
907+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
908+ "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
909+ "dev": true
910+ },
911+ "istanbul-lib-report": {
912+ "version": "3.0.0",
913+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
914+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
915+ "dev": true,
916+ "requires": {
917+ "istanbul-lib-coverage": "^3.0.0",
918+ "make-dir": "^3.0.0",
919+ "supports-color": "^7.1.0"
920+ }
921+ },
922+ "istanbul-reports": {
923+ "version": "3.1.5",
924+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
925+ "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
926+ "dev": true,
927+ "requires": {
928+ "html-escaper": "^2.0.0",
929+ "istanbul-lib-report": "^3.0.0"
930+ }
931+ },
932+ "locate-path": {
933+ "version": "6.0.0",
934+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
935+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
936+ "dev": true,
937+ "requires": {
938+ "p-locate": "^5.0.0"
939+ }
940+ },
941+ "make-dir": {
942+ "version": "3.1.0",
943+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
944+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
945+ "dev": true,
946+ "requires": {
947+ "semver": "^6.0.0"
948+ }
949+ },
950+ "minimatch": {
951+ "version": "3.1.2",
952+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
953+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
954+ "dev": true,
955+ "requires": {
956+ "brace-expansion": "^1.1.7"
957+ }
958+ },
959+ "once": {
960+ "version": "1.4.0",
961+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
962+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
963+ "dev": true,
964+ "requires": {
965+ "wrappy": "1"
966+ }
967+ },
968+ "p-limit": {
969+ "version": "3.1.0",
970+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
971+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
972+ "dev": true,
973+ "requires": {
974+ "yocto-queue": "^0.1.0"
975+ }
976+ },
977+ "p-locate": {
978+ "version": "5.0.0",
979+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
980+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
981+ "dev": true,
982+ "requires": {
983+ "p-limit": "^3.0.2"
984+ }
985+ },
986+ "path-exists": {
987+ "version": "4.0.0",
988+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
989+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
990+ "dev": true
991+ },
992+ "path-is-absolute": {
993+ "version": "1.0.1",
994+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
995+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
996+ "dev": true
997+ },
998+ "path-key": {
999+ "version": "3.1.1",
1000+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
1001+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
1002+ "dev": true
1003+ },
1004+ "require-directory": {
1005+ "version": "2.1.1",
1006+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
1007+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
1008+ "dev": true
1009+ },
1010+ "rimraf": {
1011+ "version": "3.0.2",
1012+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1013+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1014+ "dev": true,
1015+ "requires": {
1016+ "glob": "^7.1.3"
1017+ }
1018+ },
1019+ "semver": {
1020+ "version": "6.3.1",
1021+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
1022+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
1023+ "dev": true
1024+ },
1025+ "shebang-command": {
1026+ "version": "2.0.0",
1027+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1028+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1029+ "dev": true,
1030+ "requires": {
1031+ "shebang-regex": "^3.0.0"
1032+ }
1033+ },
1034+ "shebang-regex": {
1035+ "version": "3.0.0",
1036+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1037+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1038+ "dev": true
1039+ },
1040+ "signal-exit": {
1041+ "version": "3.0.7",
1042+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
1043+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
1044+ "dev": true
1045+ },
1046+ "string-width": {
1047+ "version": "4.2.3",
1048+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1049+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1050+ "dev": true,
1051+ "requires": {
1052+ "emoji-regex": "^8.0.0",
1053+ "is-fullwidth-code-point": "^3.0.0",
1054+ "strip-ansi": "^6.0.1"
1055+ }
1056+ },
1057+ "strip-ansi": {
1058+ "version": "6.0.1",
1059+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1060+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1061+ "dev": true,
1062+ "requires": {
1063+ "ansi-regex": "^5.0.1"
1064+ }
1065+ },
1066+ "supports-color": {
1067+ "version": "7.2.0",
1068+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1069+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1070+ "dev": true,
1071+ "requires": {
1072+ "has-flag": "^4.0.0"
1073+ }
1074+ },
1075+ "test-exclude": {
1076+ "version": "6.0.0",
1077+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
1078+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
1079+ "dev": true,
1080+ "requires": {
1081+ "@istanbuljs/schema": "^0.1.2",
1082+ "glob": "^7.1.4",
1083+ "minimatch": "^3.0.4"
1084+ }
1085+ },
1086+ "v8-to-istanbul": {
1087+ "version": "9.0.1",
1088+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
1089+ "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
1090+ "dev": true,
1091+ "requires": {
1092+ "@jridgewell/trace-mapping": "^0.3.12",
1093+ "@types/istanbul-lib-coverage": "^2.0.1",
1094+ "convert-source-map": "^1.6.0"
1095+ }
1096+ },
1097+ "which": {
1098+ "version": "2.0.2",
1099+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1100+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1101+ "dev": true,
1102+ "requires": {
1103+ "isexe": "^2.0.0"
1104+ }
1105+ },
1106+ "wrap-ansi": {
1107+ "version": "7.0.0",
1108+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1109+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1110+ "dev": true,
1111+ "requires": {
1112+ "ansi-styles": "^4.0.0",
1113+ "string-width": "^4.1.0",
1114+ "strip-ansi": "^6.0.0"
1115+ }
1116+ },
1117+ "wrappy": {
1118+ "version": "1.0.2",
1119+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1120+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1121+ "dev": true
1122+ },
1123+ "y18n": {
1124+ "version": "5.0.8",
1125+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
1126+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
1127+ "dev": true
1128+ },
1129+ "yargs": {
1130+ "version": "16.2.0",
1131+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
1132+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
1133+ "dev": true,
1134+ "requires": {
1135+ "cliui": "^7.0.2",
1136+ "escalade": "^3.1.1",
1137+ "get-caller-file": "^2.0.5",
1138+ "require-directory": "^2.1.1",
1139+ "string-width": "^4.2.0",
1140+ "y18n": "^5.0.5",
1141+ "yargs-parser": "^20.2.2"
1142+ }
1143+ },
1144+ "yargs-parser": {
1145+ "version": "20.2.9",
1146+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
1147+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
1148+ "dev": true
1149+ },
1150+ "yocto-queue": {
1151+ "version": "0.1.0",
1152+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
1153+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
1154+ "dev": true
1155+ }
1156+ }
1157+}
package.jsonnew file+11
@@ -0,0 +1,11 @@
1+{
2+ "scripts": {
3+ "test": "spago test",
4+ "precoverage": "npm run test",
5+ "coverage": "c8 --lines=99 --branches=75 --statements=99 npm run test"
6+ },
7+ "type": "module",
8+ "devDependencies": {
9+ "c8": "^7.12.0"
10+ }
11+}
packages.dhalldeleted−5
@@ -1,5 +0,0 @@
1−let upstream =
2− https://github.com/purescript/package-sets/releases/download/psc-0.15.0-20220509/packages.dhall
3− sha256:d4c1a03606efdbb7bb7745a9d3aa908cb1ba5611921373659a4c7bf1c41c106c
4−
5−in upstream
spago.dhalldeleted−27
@@ -1,27 +0,0 @@
1−{ name = "purescript-json"
2−, dependencies =
3− [ "arrays"
4− , "bifunctors"
5− , "console"
6− , "control"
7− , "effect"
8− , "either"
9− , "exceptions"
10− , "foldable-traversable"
11− , "foreign"
12− , "foreign-object"
13− , "identity"
14− , "lists"
15− , "maybe"
16− , "nonempty"
17− , "nullable"
18− , "partial"
19− , "prelude"
20− , "record"
21− , "transformers"
22− , "typelevel-prelude"
23− , "variant"
24− ]
25−, packages = ./packages.dhall
26−, sources = [ "src/**/*.purs" ]
27−}
spago.locknew file+1747
@@ -0,0 +1,1747 @@
1+{
2+ "workspace": {
3+ "packages": {
4+ "yoga-json": {
5+ "path": "./",
6+ "core": {
7+ "dependencies": [
8+ {
9+ "arrays": ">=7.3.0 <8.0.0"
10+ },
11+ {
12+ "bifunctors": ">=6.0.0 <7.0.0"
13+ },
14+ {
15+ "control": ">=6.0.0 <7.0.0"
16+ },
17+ {
18+ "datetime": ">=6.1.0 <7.0.0"
19+ },
20+ {
21+ "effect": ">=4.0.0 <5.0.0"
22+ },
23+ {
24+ "either": ">=6.1.0 <7.0.0"
25+ },
26+ {
27+ "exceptions": ">=6.1.0 <7.0.0"
28+ },
29+ {
30+ "foldable-traversable": ">=6.0.0 <7.0.0"
31+ },
32+ {
33+ "foreign": ">=7.0.0 <8.0.0"
34+ },
35+ {
36+ "foreign-object": ">=4.1.0 <5.0.0"
37+ },
38+ {
39+ "free": ">=7.1.0 <8.0.0"
40+ },
41+ {
42+ "identity": ">=6.0.0 <7.0.0"
43+ },
44+ {
45+ "integers": ">=6.0.0 <7.0.0"
46+ },
47+ {
48+ "js-bigints": ">=2.2.1 <3.0.0"
49+ },
50+ {
51+ "js-date": ">=8.0.0 <9.0.0"
52+ },
53+ {
54+ "lists": ">=7.0.0 <8.0.0"
55+ },
56+ {
57+ "maybe": ">=6.0.0 <7.0.0"
58+ },
59+ {
60+ "newtype": ">=5.0.0 <6.0.0"
61+ },
62+ {
63+ "nullable": ">=6.0.0 <7.0.0"
64+ },
65+ {
66+ "numbers": ">=9.0.1 <10.0.0"
67+ },
68+ {
69+ "ordered-collections": ">=3.2.0 <4.0.0"
70+ },
71+ {
72+ "partial": ">=4.0.0 <5.0.0"
73+ },
74+ {
75+ "prelude": ">=6.0.2 <7.0.0"
76+ },
77+ {
78+ "record": ">=4.0.0 <5.0.0"
79+ },
80+ {
81+ "safe-coerce": ">=2.0.0 <3.0.0"
82+ },
83+ {
84+ "strings": ">=6.0.1 <7.0.0"
85+ },
86+ {
87+ "transformers": ">=6.1.0 <7.0.0"
88+ },
89+ {
90+ "tuples": ">=7.0.0 <8.0.0"
91+ },
92+ {
93+ "typelevel-prelude": ">=7.0.0 <8.0.0"
94+ },
95+ {
96+ "unsafe-coerce": ">=6.0.0 <7.0.0"
97+ },
98+ {
99+ "variant": ">=8.0.0 <9.0.0"
100+ },
101+ {
102+ "yoga-tree": ">=1.0.0 <2.0.0"
103+ }
104+ ]
105+ },
106+ "test": {
107+ "dependencies": [
108+ "spec",
109+ "spec-discovery",
110+ "spec-node",
111+ "strings-extra"
112+ ]
113+ }
114+ }
115+ },
116+ "package_set": {
117+ "address": {
118+ "registry": "63.2.1"
119+ },
120+ "compiler": ">=0.15.15 <0.16.0",
121+ "content": {
122+ "abc-parser": "2.0.1",
123+ "ace": "9.1.0",
124+ "address-rfc2821": "0.1.1",
125+ "aff": "8.0.0",
126+ "aff-bus": "6.0.0",
127+ "aff-coroutines": "9.0.0",
128+ "aff-promise": "4.0.0",
129+ "aff-retry": "2.0.0",
130+ "affjax": "13.0.0",
131+ "affjax-node": "1.0.0",
132+ "affjax-web": "1.0.0",
133+ "ansi": "7.0.0",
134+ "apexcharts": "0.5.0",
135+ "applicative-phases": "1.0.0",
136+ "argonaut": "9.0.0",
137+ "argonaut-aeson-generic": "0.4.1",
138+ "argonaut-codecs": "9.1.0",
139+ "argonaut-core": "7.0.0",
140+ "argonaut-generic": "8.0.0",
141+ "argonaut-traversals": "10.0.0",
142+ "argparse-basic": "2.0.0",
143+ "array-builder": "0.1.2",
144+ "array-search": "0.6.0",
145+ "arraybuffer": "13.2.0",
146+ "arraybuffer-builder": "3.1.0",
147+ "arraybuffer-types": "3.0.2",
148+ "arrays": "7.3.0",
149+ "arrays-extra": "0.6.1",
150+ "arrays-zipper": "2.0.1",
151+ "ask": "1.0.0",
152+ "assert": "6.0.0",
153+ "assert-multiple": "0.4.0",
154+ "avar": "5.0.1",
155+ "b64": "0.0.8",
156+ "barbies": "1.0.1",
157+ "barlow-lens": "0.9.0",
158+ "bifunctors": "6.0.0",
159+ "bigints": "7.0.1",
160+ "bolson": "0.3.9",
161+ "bookhound": "0.1.7",
162+ "bower-json": "3.0.0",
163+ "call-by-name": "4.0.1",
164+ "canvas": "6.0.0",
165+ "canvas-action": "9.0.0",
166+ "cartesian": "1.0.6",
167+ "catenable-lists": "7.0.0",
168+ "cbor-stream": "1.3.0",
169+ "chameleon": "1.0.0",
170+ "chameleon-halogen": "1.0.3",
171+ "chameleon-react-basic": "1.1.0",
172+ "chameleon-styled": "2.5.0",
173+ "chameleon-transformers": "1.0.0",
174+ "channel": "1.0.0",
175+ "checked-exceptions": "3.1.1",
176+ "choku": "1.0.2",
177+ "classless": "0.1.1",
178+ "classless-arbitrary": "0.1.1",
179+ "classless-decode-json": "0.1.1",
180+ "classless-encode-json": "0.1.3",
181+ "classnames": "2.0.0",
182+ "codec": "6.1.0",
183+ "codec-argonaut": "10.0.0",
184+ "codec-json": "2.0.0",
185+ "colors": "7.0.1",
186+ "concur-core": "0.5.0",
187+ "concur-react": "0.5.0",
188+ "concurrent-queues": "3.0.0",
189+ "console": "6.1.0",
190+ "const": "6.0.0",
191+ "contravariant": "6.0.0",
192+ "control": "6.0.0",
193+ "convertable-options": "1.0.0",
194+ "coroutines": "7.0.0",
195+ "css": "6.0.0",
196+ "css-class-name-extractor": "0.0.4",
197+ "css-frameworks": "1.0.1",
198+ "csv-stream": "2.3.0",
199+ "data-mvc": "0.0.2",
200+ "datetime": "6.1.0",
201+ "datetime-parsing": "0.2.0",
202+ "debounce": "0.1.0",
203+ "debug": "6.0.2",
204+ "decimals": "7.1.0",
205+ "default-values": "1.0.1",
206+ "deku": "0.9.23",
207+ "deno": "0.0.5",
208+ "dissect": "1.0.0",
209+ "distributive": "6.0.0",
210+ "dodo-printer": "2.2.3",
211+ "dom-filereader": "7.0.0",
212+ "dom-indexed": "12.0.0",
213+ "dom-simple": "0.4.0",
214+ "dotenv": "4.0.3",
215+ "droplet": "0.6.0",
216+ "dts": "1.0.0",
217+ "dual-numbers": "1.0.3",
218+ "dynamic-buffer": "3.0.1",
219+ "echarts-simple": "0.0.1",
220+ "effect": "4.0.0",
221+ "either": "6.1.0",
222+ "elmish": "0.13.0",
223+ "elmish-enzyme": "0.1.1",
224+ "elmish-hooks": "0.10.3",
225+ "elmish-html": "0.9.0",
226+ "elmish-testing-library": "0.3.2",
227+ "email-validate": "7.0.0",
228+ "encoding": "0.0.9",
229+ "enums": "6.0.1",
230+ "env-names": "0.4.0",
231+ "error": "2.0.0",
232+ "eta-conversion": "0.3.2",
233+ "exceptions": "6.1.0",
234+ "exists": "6.0.0",
235+ "exitcodes": "4.0.0",
236+ "expect-inferred": "3.0.0",
237+ "ezfetch": "1.1.0",
238+ "fahrtwind": "2.0.0",
239+ "fallback": "0.1.0",
240+ "fast-vect": "1.2.0",
241+ "fetch": "4.1.0",
242+ "fetch-argonaut": "1.0.1",
243+ "fetch-core": "5.1.0",
244+ "fetch-yoga-json": "1.1.0",
245+ "ffi-simple": "0.5.1",
246+ "fft-js": "0.1.0",
247+ "filterable": "5.0.0",
248+ "fix-functor": "0.1.0",
249+ "fixed-points": "7.0.0",
250+ "fixed-precision": "5.0.0",
251+ "flame": "1.3.0",
252+ "float32": "2.0.0",
253+ "fmt": "0.2.1",
254+ "foldable-traversable": "6.0.0",
255+ "foldable-traversable-extra": "0.0.6",
256+ "foreign": "7.0.0",
257+ "foreign-object": "4.1.0",
258+ "foreign-readwrite": "3.4.0",
259+ "forgetmenot": "0.1.0",
260+ "fork": "6.0.0",
261+ "form-urlencoded": "7.0.0",
262+ "formatters": "7.0.0",
263+ "framer-motion": "1.0.1",
264+ "free": "7.1.0",
265+ "freeap": "7.0.0",
266+ "freer-free": "0.0.1",
267+ "freet": "7.0.0",
268+ "functions": "6.0.0",
269+ "functor1": "3.0.0",
270+ "functors": "5.0.0",
271+ "fuzzy": "0.4.0",
272+ "gen": "4.0.0",
273+ "generate-values": "1.0.1",
274+ "generic-router": "0.0.1",
275+ "geojson": "0.0.5",
276+ "geometria": "2.2.0",
277+ "gojs": "0.1.1",
278+ "grain": "3.0.0",
279+ "grain-router": "3.0.0",
280+ "grain-virtualized": "3.0.0",
281+ "graphs": "8.1.0",
282+ "group": "4.1.1",
283+ "halogen": "7.0.0",
284+ "halogen-bootstrap5": "5.3.2",
285+ "halogen-canvas": "1.0.0",
286+ "halogen-css": "10.0.0",
287+ "halogen-echarts-simple": "0.0.4",
288+ "halogen-formless": "4.0.3",
289+ "halogen-helix": "1.0.1",
290+ "halogen-hooks": "0.6.3",
291+ "halogen-hooks-extra": "0.9.0",
292+ "halogen-infinite-scroll": "1.1.0",
293+ "halogen-store": "0.5.4",
294+ "halogen-storybook": "2.0.0",
295+ "halogen-subscriptions": "2.0.0",
296+ "halogen-svg-elems": "8.0.0",
297+ "halogen-typewriter": "1.0.4",
298+ "halogen-vdom": "8.0.0",
299+ "halogen-vdom-string-renderer": "0.5.0",
300+ "halogen-xterm": "2.0.0",
301+ "heckin": "2.0.1",
302+ "heterogeneous": "0.6.0",
303+ "homogeneous": "0.4.0",
304+ "http-methods": "6.0.0",
305+ "httpurple": "4.0.0",
306+ "huffman": "0.4.0",
307+ "humdrum": "0.0.1",
308+ "hyrule": "2.3.8",
309+ "identity": "6.0.0",
310+ "identy": "4.0.1",
311+ "indexed-db": "1.0.0",
312+ "indexed-monad": "3.0.0",
313+ "int64": "3.0.0",
314+ "integers": "6.0.0",
315+ "interpolate": "5.0.2",
316+ "intersection-observer": "1.0.1",
317+ "invariant": "6.0.0",
318+ "jarilo": "1.0.1",
319+ "jelly": "0.10.0",
320+ "jelly-router": "0.3.0",
321+ "jelly-signal": "0.4.0",
322+ "jest": "1.0.0",
323+ "js-abort-controller": "1.0.0",
324+ "js-bigints": "2.2.1",
325+ "js-date": "8.0.0",
326+ "js-fetch": "0.2.1",
327+ "js-fileio": "3.0.0",
328+ "js-intl": "1.1.4",
329+ "js-iterators": "0.1.1",
330+ "js-maps": "0.1.2",
331+ "js-promise": "1.0.0",
332+ "js-promise-aff": "1.0.0",
333+ "js-timers": "6.1.0",
334+ "js-uri": "3.1.0",
335+ "jsdom": "1.0.0",
336+ "json": "1.1.0",
337+ "json-codecs": "5.0.0",
338+ "justifill": "0.5.0",
339+ "jwt": "0.0.9",
340+ "labeled-data": "0.2.0",
341+ "language-cst-parser": "0.14.1",
342+ "lazy": "6.0.0",
343+ "lazy-joe": "1.0.0",
344+ "lcg": "4.0.0",
345+ "leibniz": "5.0.0",
346+ "leveldb": "1.0.1",
347+ "liminal": "1.0.1",
348+ "linalg": "6.0.0",
349+ "lists": "7.0.0",
350+ "literals": "1.0.2",
351+ "logging": "3.0.0",
352+ "logging-journald": "0.4.0",
353+ "lumi-components": "18.0.0",
354+ "machines": "7.0.0",
355+ "maps-eager": "0.5.0",
356+ "marionette": "1.0.0",
357+ "marionette-react-basic-hooks": "0.1.1",
358+ "marked": "0.1.0",
359+ "matrices": "5.0.1",
360+ "matryoshka": "1.0.0",
361+ "maybe": "6.0.0",
362+ "media-types": "6.0.0",
363+ "meowclient": "1.0.0",
364+ "midi": "4.0.0",
365+ "milkis": "9.0.0",
366+ "minibench": "4.0.1",
367+ "mmorph": "7.0.0",
368+ "monad-control": "5.0.0",
369+ "monad-logger": "1.3.1",
370+ "monad-loops": "0.5.0",
371+ "monad-unlift": "1.0.1",
372+ "monoid-extras": "0.0.1",
373+ "monoidal": "0.16.0",
374+ "morello": "0.4.0",
375+ "mote": "3.0.0",
376+ "motsunabe": "2.0.0",
377+ "mvc": "0.0.1",
378+ "mysql": "6.0.1",
379+ "n3": "0.1.0",
380+ "nano-id": "1.1.0",
381+ "nanoid": "0.1.0",
382+ "naturals": "3.0.0",
383+ "nested-functor": "0.2.1",
384+ "newtype": "5.0.0",
385+ "nextjs": "0.1.1",
386+ "nextui": "0.2.0",
387+ "node-buffer": "9.0.0",
388+ "node-child-process": "11.1.0",
389+ "node-event-emitter": "3.0.0",
390+ "node-execa": "5.0.0",
391+ "node-fs": "9.2.0",
392+ "node-glob-basic": "2.0.0",
393+ "node-http": "9.1.0",
394+ "node-http2": "1.1.1",
395+ "node-human-signals": "1.0.0",
396+ "node-net": "5.1.0",
397+ "node-os": "5.1.0",
398+ "node-path": "5.0.1",
399+ "node-process": "11.2.0",
400+ "node-readline": "8.1.1",
401+ "node-sqlite3": "8.0.0",
402+ "node-stream-pipes": "2.1.6",
403+ "node-streams": "9.0.1",
404+ "node-tls": "0.3.1",
405+ "node-url": "7.0.1",
406+ "node-workerbees": "0.3.1",
407+ "node-zlib": "0.4.0",
408+ "nonempty": "7.0.0",
409+ "now": "6.0.0",
410+ "npm-package-json": "2.0.0",
411+ "nullable": "6.0.0",
412+ "numberfield": "0.2.2",
413+ "numbers": "9.0.1",
414+ "oak": "3.1.1",
415+ "oak-debug": "1.2.2",
416+ "object-maps": "0.3.0",
417+ "ocarina": "1.5.4",
418+ "oooooooooorrrrrrrmm-lib": "0.0.1",
419+ "open-colors-scales-and-schemes": "1.0.0",
420+ "open-folds": "6.4.0",
421+ "open-foreign-generic": "11.0.3",
422+ "open-memoize": "6.2.0",
423+ "open-mkdirp-aff": "1.2.0",
424+ "open-pairing": "6.2.0",
425+ "open-smolder": "12.0.2",
426+ "options": "7.0.0",
427+ "optparse": "5.0.1",
428+ "ordered-collections": "3.2.0",
429+ "ordered-set": "0.4.0",
430+ "orders": "6.0.0",
431+ "owoify": "1.2.0",
432+ "pairs": "9.0.1",
433+ "parallel": "7.0.0",
434+ "parsing": "10.2.0",
435+ "parsing-dataview": "3.2.4",
436+ "partial": "4.0.0",
437+ "pathy": "9.0.0",
438+ "pha": "0.13.0",
439+ "phaser": "0.7.0",
440+ "phylio": "1.1.2",
441+ "pipes": "8.0.0",
442+ "pirates-charm": "0.0.1",
443+ "pmock": "0.9.0",
444+ "point-free": "1.0.0",
445+ "pointed-list": "0.5.1",
446+ "polymorphic-vectors": "4.0.0",
447+ "posix-types": "6.0.0",
448+ "postgresql": "2.0.20",
449+ "precise": "6.0.0",
450+ "precise-datetime": "7.0.0",
451+ "prelude": "6.0.2",
452+ "prettier-printer": "3.0.0",
453+ "printf": "0.1.0",
454+ "priority-queue": "0.1.2",
455+ "profunctor": "6.0.1",
456+ "profunctor-lenses": "8.0.0",
457+ "protobuf": "4.4.0",
458+ "psa-utils": "8.0.0",
459+ "psci-support": "6.0.0",
460+ "punycode": "1.0.0",
461+ "qualified-do": "2.2.0",
462+ "quantities": "12.2.0",
463+ "quickcheck": "8.0.1",
464+ "quickcheck-combinators": "0.1.3",
465+ "quickcheck-laws": "7.0.0",
466+ "quickcheck-utf8": "0.0.0",
467+ "random": "6.0.0",
468+ "rationals": "6.0.0",
469+ "rdf": "0.1.0",
470+ "react": "11.0.0",
471+ "react-aria": "0.2.0",
472+ "react-basic": "17.0.0",
473+ "react-basic-classic": "3.0.0",
474+ "react-basic-dnd": "10.1.0",
475+ "react-basic-dom": "7.0.0",
476+ "react-basic-dom-beta": "0.1.1",
477+ "react-basic-emotion": "7.1.0",
478+ "react-basic-hooks": "8.2.0",
479+ "react-basic-storybook": "2.0.0",
480+ "react-dom": "8.0.0",
481+ "react-halo": "3.0.0",
482+ "react-icons": "1.1.5",
483+ "react-markdown": "0.1.0",
484+ "react-testing-library": "4.0.1",
485+ "react-virtuoso": "1.0.0",
486+ "reactix": "0.6.1",
487+ "read": "1.0.1",
488+ "recharts": "1.1.0",
489+ "record": "4.0.0",
490+ "record-extra": "5.0.1",
491+ "record-ptional-fields": "0.1.2",
492+ "record-studio": "1.0.4",
493+ "refs": "6.0.0",
494+ "remotedata": "5.0.1",
495+ "repr": "0.5.0",
496+ "resize-observer": "1.0.0",
497+ "resource": "2.0.1",
498+ "resourcet": "1.0.0",
499+ "result": "1.0.3",
500+ "return": "0.2.0",
501+ "ring-modules": "5.0.1",
502+ "rito": "0.3.4",
503+ "roman": "0.4.0",
504+ "rough-notation": "1.0.2",
505+ "routing": "11.0.0",
506+ "routing-duplex": "0.7.0",
507+ "run": "5.0.0",
508+ "safe-coerce": "2.0.0",
509+ "safely": "4.0.1",
510+ "school-of-music": "1.3.0",
511+ "selection-foldable": "0.2.0",
512+ "selective-functors": "1.0.1",
513+ "semirings": "7.0.0",
514+ "shuffle": "1.1.0",
515+ "signal": "13.0.0",
516+ "simple-emitter": "3.0.1",
517+ "simple-i18n": "2.0.1",
518+ "simple-json": "9.0.0",
519+ "simple-json-generics": "0.2.1",
520+ "simple-ulid": "3.0.0",
521+ "sized-matrices": "1.0.0",
522+ "sized-vectors": "5.0.2",
523+ "slug": "3.1.0",
524+ "small-ffi": "4.0.1",
525+ "soundfonts": "4.1.0",
526+ "sparse-matrices": "2.0.1",
527+ "sparse-polynomials": "3.0.1",
528+ "spec": "8.1.1",
529+ "spec-discovery": "8.4.0",
530+ "spec-mocha": "5.1.1",
531+ "spec-node": "0.0.3",
532+ "spec-quickcheck": "5.0.2",
533+ "spec-reporter-xunit": "0.7.1",
534+ "splitmix": "2.1.0",
535+ "ssrs": "1.0.0",
536+ "st": "6.2.0",
537+ "statistics": "0.3.2",
538+ "strictlypositiveint": "1.0.1",
539+ "string-parsers": "8.0.0",
540+ "strings": "6.0.1",
541+ "strings-extra": "4.0.0",
542+ "stringutils": "0.0.12",
543+ "substitute": "0.2.3",
544+ "supply": "0.2.0",
545+ "svg-parser": "3.0.0",
546+ "systemd-journald": "0.3.0",
547+ "tagged": "4.0.2",
548+ "tailrec": "6.1.0",
549+ "tanstack-query": "2.0.0",
550+ "tecton": "0.2.1",
551+ "tecton-halogen": "0.2.0",
552+ "test-unit": "17.0.0",
553+ "thermite": "6.3.1",
554+ "thermite-dom": "0.3.1",
555+ "these": "6.0.0",
556+ "threading": "0.0.3",
557+ "tidy": "0.11.1",
558+ "tidy-codegen": "4.0.1",
559+ "tldr": "0.0.0",
560+ "toestand": "0.9.0",
561+ "transformation-matrix": "1.0.1",
562+ "transformers": "6.1.0",
563+ "tree-rose": "4.0.2",
564+ "ts-bridge": "4.0.0",
565+ "tuples": "7.0.0",
566+ "two-or-more": "1.0.0",
567+ "type-equality": "4.0.1",
568+ "typedenv": "2.0.1",
569+ "typelevel": "6.0.0",
570+ "typelevel-lists": "2.1.0",
571+ "typelevel-peano": "1.0.1",
572+ "typelevel-prelude": "7.0.0",
573+ "typelevel-regex": "0.0.3",
574+ "typelevel-rows": "0.1.0",
575+ "typisch": "0.4.0",
576+ "uint": "7.0.0",
577+ "ulid": "3.0.1",
578+ "uncurried-transformers": "1.1.0",
579+ "undefined": "2.0.0",
580+ "undefined-is-not-a-problem": "1.1.0",
581+ "unfoldable": "6.0.0",
582+ "unicode": "6.0.0",
583+ "unique": "0.6.1",
584+ "unlift": "1.0.1",
585+ "unordered-collections": "3.1.0",
586+ "unsafe-coerce": "6.0.0",
587+ "unsafe-reference": "5.0.0",
588+ "untagged-to-tagged": "0.1.4",
589+ "untagged-union": "1.0.0",
590+ "uri": "9.0.0",
591+ "url-immutable": "1.0.0",
592+ "uuid": "9.0.0",
593+ "uuidv4": "1.0.0",
594+ "validation": "6.0.0",
595+ "variant": "8.0.0",
596+ "variant-encodings": "2.0.0",
597+ "vectorfield": "1.0.1",
598+ "vectors": "2.1.0",
599+ "versions": "7.0.0",
600+ "visx": "0.0.2",
601+ "vitest": "1.0.0",
602+ "web-clipboard": "6.0.0",
603+ "web-cssom": "2.0.0",
604+ "web-cssom-view": "0.1.0",
605+ "web-dom": "6.0.0",
606+ "web-dom-parser": "8.0.0",
607+ "web-dom-xpath": "3.0.0",
608+ "web-encoding": "3.0.0",
609+ "web-events": "4.0.0",
610+ "web-fetch": "4.0.1",
611+ "web-file": "4.0.0",
612+ "web-geometry": "0.1.0",
613+ "web-html": "4.1.0",
614+ "web-pointerevents": "2.0.0",
615+ "web-proletarian": "1.0.0",
616+ "web-promise": "3.2.0",
617+ "web-resize-observer": "2.1.0",
618+ "web-router": "1.0.0",
619+ "web-socket": "4.0.0",
620+ "web-storage": "5.0.0",
621+ "web-streams": "4.0.0",
622+ "web-touchevents": "4.0.0",
623+ "web-uievents": "5.0.0",
624+ "web-url": "2.0.0",
625+ "web-workers": "1.1.0",
626+ "web-xhr": "5.0.1",
627+ "webextension-polyfill": "0.1.0",
628+ "webgpu": "0.0.1",
629+ "which": "2.0.0",
630+ "whine-core": "0.0.28",
631+ "xterm": "1.0.0",
632+ "yoga-fetch": "1.0.1",
633+ "yoga-json": "5.1.0",
634+ "yoga-om": "0.1.0",
635+ "yoga-postgres": "6.0.0",
636+ "yoga-react-dom": "1.0.1",
637+ "yoga-subtlecrypto": "0.1.0",
638+ "yoga-tree": "1.0.0",
639+ "z3": "0.0.2",
640+ "zipperarray": "2.0.0"
641+ }
642+ },
643+ "extra_packages": {}
644+ },
645+ "packages": {
646+ "aff": {
647+ "type": "registry",
648+ "version": "8.0.0",
649+ "integrity": "sha256-9BRIrSdRoYybfiUmBqgKJ66cPqxYHb277bVWQMn/9sg=",
650+ "dependencies": [
651+ "control",
652+ "datetime",
653+ "effect",
654+ "either",
655+ "exceptions",
656+ "functions",
657+ "newtype",
658+ "parallel",
659+ "partial",
660+ "prelude",
661+ "st",
662+ "tailrec",
663+ "transformers",
664+ "unsafe-coerce"
665+ ]
666+ },
667+ "ansi": {
668+ "type": "registry",
669+ "version": "7.0.0",
670+ "integrity": "sha256-tOUaXJFzPSfBVAqLI8hc+Tz2M1rg16cXqyHaK/3SmFg=",
671+ "dependencies": [
672+ "foldable-traversable",
673+ "lists",
674+ "prelude"
675+ ]
676+ },
677+ "argonaut-codecs": {
678+ "type": "registry",
679+ "version": "9.1.0",
680+ "integrity": "sha256-K910SBrmYallESsm8pxJYThs7lig6hxX3M4PW33Cgew=",
681+ "dependencies": [
682+ "argonaut-core",
683+ "arrays",
684+ "bifunctors",
685+ "either",
686+ "foldable-traversable",
687+ "foreign-object",
688+ "identity",
689+ "integers",
690+ "lists",
691+ "maybe",
692+ "nonempty",
693+ "ordered-collections",
694+ "prelude",
695+ "record",
696+ "strings",
697+ "tuples"
698+ ]
699+ },
700+ "argonaut-core": {
701+ "type": "registry",
702+ "version": "7.0.0",
703+ "integrity": "sha256-gYZihtBIKthVuXXoiPphMookSf8M5aHyFYkcIWqlxTM=",
704+ "dependencies": [
705+ "arrays",
706+ "control",
707+ "either",
708+ "foreign-object",
709+ "functions",
710+ "gen",
711+ "maybe",
712+ "nonempty",
713+ "prelude",
714+ "strings",
715+ "tailrec"
716+ ]
717+ },
718+ "arraybuffer-types": {
719+ "type": "registry",
720+ "version": "3.0.2",
721+ "integrity": "sha256-p05cJnSkyeoB7VHzMyc2Eb1RwUaB7Nl0sQSqEGNEUD8=",
722+ "dependencies": []
723+ },
724+ "arrays": {
725+ "type": "registry",
726+ "version": "7.3.0",
727+ "integrity": "sha256-GD4z7LCi9wzi7FCQqbWhvs8paoUK9NO+HwgXZ+KP8Rk=",
728+ "dependencies": [
729+ "bifunctors",
730+ "control",
731+ "foldable-traversable",
732+ "functions",
733+ "maybe",
734+ "nonempty",
735+ "partial",
736+ "prelude",
737+ "safe-coerce",
738+ "st",
739+ "tailrec",
740+ "tuples",
741+ "unfoldable",
742+ "unsafe-coerce"
743+ ]
744+ },
745+ "avar": {
746+ "type": "registry",
747+ "version": "5.0.1",
748+ "integrity": "sha256-8V4SxF4TIWZ9Ik1P4lPzIRUAZeFBe8w5WA2VcCEKsIk=",
749+ "dependencies": [
750+ "aff",
751+ "effect",
752+ "either",
753+ "exceptions",
754+ "functions",
755+ "maybe",
756+ "prelude"
757+ ]
758+ },
759+ "bifunctors": {
760+ "type": "registry",
761+ "version": "6.0.0",
762+ "integrity": "sha256-tXhmlMiyVy6mbUreVZQt/2EGEsPr0T1PjJi+YCG5J7E=",
763+ "dependencies": [
764+ "const",
765+ "either",
766+ "newtype",
767+ "prelude",
768+ "tuples"
769+ ]
770+ },
771+ "catenable-lists": {
772+ "type": "registry",
773+ "version": "7.0.0",
774+ "integrity": "sha256-7+i/MHBLIRh604iCNT4ENWRWE/wuHIotER4kpdX9Ve0=",
775+ "dependencies": [
776+ "control",
777+ "foldable-traversable",
778+ "lists",
779+ "maybe",
780+ "prelude",
781+ "tuples",
782+ "unfoldable"
783+ ]
784+ },
785+ "const": {
786+ "type": "registry",
787+ "version": "6.0.0",
788+ "integrity": "sha256-S+m0lQsxnji0z1XRUmkn+3RFuWJ5CXWuIr1u3i8Bfoc=",
789+ "dependencies": [
790+ "invariant",
791+ "newtype",
792+ "prelude"
793+ ]
794+ },
795+ "contravariant": {
796+ "type": "registry",
797+ "version": "6.0.0",
798+ "integrity": "sha256-nuckEWqL80NaPmR/l9AUyrfycNh18XcvlZV9PAamwqc=",
799+ "dependencies": [
800+ "const",
801+ "either",
802+ "newtype",
803+ "prelude",
804+ "tuples"
805+ ]
806+ },
807+ "control": {
808+ "type": "registry",
809+ "version": "6.0.0",
810+ "integrity": "sha256-0vxyYh5FL+ilxgLo954w1LqCUC0RSIivNNlb9CaNUQg=",
811+ "dependencies": [
812+ "newtype",
813+ "prelude"
814+ ]
815+ },
816+ "datetime": {
817+ "type": "registry",
818+ "version": "6.1.0",
819+ "integrity": "sha256-tbv6eDXy6QOD7YSknxYSbsDF32OC2JrNbSBpzMs7Doc=",
820+ "dependencies": [
821+ "bifunctors",
822+ "control",
823+ "either",
824+ "enums",
825+ "foldable-traversable",
826+ "functions",
827+ "gen",
828+ "integers",
829+ "lists",
830+ "maybe",
831+ "newtype",
832+ "numbers",
833+ "ordered-collections",
834+ "partial",
835+ "prelude",
836+ "tuples"
837+ ]
838+ },
839+ "distributive": {
840+ "type": "registry",
841+ "version": "6.0.0",
842+ "integrity": "sha256-netyJK4B32PDYHD0tF2AenKgo3urzbI770ycM0pArAo=",
843+ "dependencies": [
844+ "identity",
845+ "newtype",
846+ "prelude",
847+ "tuples",
848+ "type-equality"
849+ ]
850+ },
851+ "effect": {
852+ "type": "registry",
853+ "version": "4.0.0",
854+ "integrity": "sha256-DdqU3bncRTjgMVPPRlAuGHVeajSPEcRaRhNuio7if6s=",
855+ "dependencies": [
856+ "prelude"
857+ ]
858+ },
859+ "either": {
860+ "type": "registry",
861+ "version": "6.1.0",
862+ "integrity": "sha256-tBHx3PgtH4GZOApZCDkcM7szRTYJinrUrVGWazQCUUg=",
863+ "dependencies": [
864+ "control",
865+ "invariant",
866+ "maybe",
867+ "prelude"
868+ ]
869+ },
870+ "enums": {
871+ "type": "registry",
872+ "version": "6.0.1",
873+ "integrity": "sha256-sdZOmLX5+5pASGpvVyT0vSD5BBYQjZiayjV5XiPutso=",
874+ "dependencies": [
875+ "control",
876+ "either",
877+ "gen",
878+ "maybe",
879+ "newtype",
880+ "nonempty",
881+ "partial",
882+ "prelude",
883+ "tuples",
884+ "unfoldable"
885+ ]
886+ },
887+ "exceptions": {
888+ "type": "registry",
889+ "version": "6.1.0",
890+ "integrity": "sha256-nRrr+N0wk0TUFOWLR7e1n1oxcXo/X345bQUtoY9lW6A=",
891+ "dependencies": [
892+ "effect",
893+ "either",
894+ "maybe",
895+ "prelude"
896+ ]
897+ },
898+ "exists": {
899+ "type": "registry",
900+ "version": "6.0.0",
901+ "integrity": "sha256-vtLbrWNaI+pzx/2fw2AQnCovoLtcosClIhjO26QKkh8=",
902+ "dependencies": [
903+ "unsafe-coerce"
904+ ]
905+ },
906+ "exitcodes": {
907+ "type": "registry",
908+ "version": "4.0.0",
909+ "integrity": "sha256-xBl4aFSEQ05Owp1ZvO6OxxvLK3LVzU35RSbj79SsePQ=",
910+ "dependencies": [
911+ "enums",
912+ "maybe",
913+ "prelude"
914+ ]
915+ },
916+ "foldable-traversable": {
917+ "type": "registry",
918+ "version": "6.0.0",
919+ "integrity": "sha256-NGGWyCio/xjce6fPP7y3wwg7CheqllID6aJudDxbWhA=",
920+ "dependencies": [
921+ "bifunctors",
922+ "const",
923+ "control",
924+ "either",
925+ "functors",
926+ "identity",
927+ "maybe",
928+ "newtype",
929+ "orders",
930+ "prelude",
931+ "tuples"
932+ ]
933+ },
934+ "foreign": {
935+ "type": "registry",
936+ "version": "7.0.0",
937+ "integrity": "sha256-jiDRMVQfovGsbbA/FzbzYf6iWk9i2b5gNrIjz+gFfsI=",
938+ "dependencies": [
939+ "either",
940+ "functions",
941+ "integers",
942+ "lists",
943+ "maybe",
944+ "prelude",
945+ "strings",
946+ "transformers",
947+ "unsafe-coerce"
948+ ]
949+ },
950+ "foreign-object": {
951+ "type": "registry",
952+ "version": "4.1.0",
953+ "integrity": "sha256-x/Q7r80z/vmHRKvPwhYmHP/DnJciPtsyGfRTMzayKIU=",
954+ "dependencies": [
955+ "arrays",
956+ "foldable-traversable",
957+ "functions",
958+ "gen",
959+ "lists",
960+ "maybe",
961+ "prelude",
962+ "st",
963+ "tailrec",
964+ "tuples",
965+ "typelevel-prelude",
966+ "unfoldable",
967+ "unsafe-coerce"
968+ ]
969+ },
970+ "fork": {
971+ "type": "registry",
972+ "version": "6.0.0",
973+ "integrity": "sha256-0keBVeZZg1eCZEy/En1CohVW829gQUqKtqBNIRa93/A=",
974+ "dependencies": [
975+ "aff",
976+ "prelude",
977+ "transformers"
978+ ]
979+ },
980+ "free": {
981+ "type": "registry",
982+ "version": "7.1.0",
983+ "integrity": "sha256-tUBInfUpRQEw4u94GWcYW7EYdmSdDHSRn88a+C0eltU=",
984+ "dependencies": [
985+ "catenable-lists",
986+ "control",
987+ "distributive",
988+ "either",
989+ "exists",
990+ "foldable-traversable",
991+ "invariant",
992+ "lazy",
993+ "maybe",
994+ "prelude",
995+ "tailrec",
996+ "transformers",
997+ "tuples",
998+ "unsafe-coerce"
999+ ]
1000+ },
1001+ "functions": {
1002+ "type": "registry",
1003+ "version": "6.0.0",
1004+ "integrity": "sha256-0jgtOr+SFO4UScKc40oA/9Vdcf2rLn3h3vZlY0KfqVo=",
1005+ "dependencies": [
1006+ "prelude"
1007+ ]
1008+ },
1009+ "functors": {
1010+ "type": "registry",
1011+ "version": "5.0.0",
1012+ "integrity": "sha256-W1o/4wcp6S3chodYL8uixlXK2mfr1L+SzM1R+whqUco=",
1013+ "dependencies": [
1014+ "bifunctors",
1015+ "const",
1016+ "contravariant",
1017+ "control",
1018+ "distributive",
1019+ "either",
1020+ "invariant",
1021+ "maybe",
1022+ "newtype",
1023+ "prelude",
1024+ "profunctor",
1025+ "tuples",
1026+ "unsafe-coerce"
1027+ ]
1028+ },
1029+ "gen": {
1030+ "type": "registry",
1031+ "version": "4.0.0",
1032+ "integrity": "sha256-kyOateeOtQa07vfTMYeSuCKdelgKE1R65fwKkZ10wsY=",
1033+ "dependencies": [
1034+ "either",
1035+ "foldable-traversable",
1036+ "identity",
1037+ "maybe",
1038+ "newtype",
1039+ "nonempty",
1040+ "prelude",
1041+ "tailrec",
1042+ "tuples",
1043+ "unfoldable"
1044+ ]
1045+ },
1046+ "identity": {
1047+ "type": "registry",
1048+ "version": "6.0.0",
1049+ "integrity": "sha256-RY/iXPpxpqvKHYfJeFVNI1J06kohB9rbtWYuha8t0LE=",
1050+ "dependencies": [
1051+ "control",
1052+ "invariant",
1053+ "newtype",
1054+ "prelude"
1055+ ]
1056+ },
1057+ "integers": {
1058+ "type": "registry",
1059+ "version": "6.0.0",
1060+ "integrity": "sha256-Y8yozC1uHRLcruobEyv5/bMKzE1BoKJ/olHv6o+bgm8=",
1061+ "dependencies": [
1062+ "maybe",
1063+ "numbers",
1064+ "prelude"
1065+ ]
1066+ },
1067+ "invariant": {
1068+ "type": "registry",
1069+ "version": "6.0.0",
1070+ "integrity": "sha256-HyoT1I5qIHRq8RSZji6zZDvqnpVjLw748utrKwZtqsw=",
1071+ "dependencies": [
1072+ "control",
1073+ "prelude"
1074+ ]
1075+ },
1076+ "js-bigints": {
1077+ "type": "registry",
1078+ "version": "2.2.1",
1079+ "integrity": "sha256-r1rE6Olv5b3JrP32lY2uKJ+eBRTsrVnC983K8VWwqe4=",
1080+ "dependencies": [
1081+ "integers",
1082+ "maybe",
1083+ "prelude"
1084+ ]
1085+ },
1086+ "js-date": {
1087+ "type": "registry",
1088+ "version": "8.0.0",
1089+ "integrity": "sha256-DNQrp4xYc8o80jtxo0aOkUeXGi6h0Xidkk2ZQ8Y4l5Y=",
1090+ "dependencies": [
1091+ "datetime",
1092+ "effect",
1093+ "enums",
1094+ "foreign",
1095+ "functions",
1096+ "integers",
1097+ "maybe",
1098+ "prelude"
1099+ ]
1100+ },
1101+ "lazy": {
1102+ "type": "registry",
1103+ "version": "6.0.0",
1104+ "integrity": "sha256-MHRC+1Pc+AjortBp4b/e1e6KpEpsDwaJBNBB7TOL+1I=",
1105+ "dependencies": [
1106+ "control",
1107+ "foldable-traversable",
1108+ "invariant",
1109+ "prelude"
1110+ ]
1111+ },
1112+ "lists": {
1113+ "type": "registry",
1114+ "version": "7.0.0",
1115+ "integrity": "sha256-/mGd7wLoU+wsTcqii7SSUByxsvwvjnu2PjwAD47yYb4=",
1116+ "dependencies": [
1117+ "bifunctors",
1118+ "control",
1119+ "foldable-traversable",
1120+ "lazy",
1121+ "maybe",
1122+ "newtype",
1123+ "nonempty",
1124+ "partial",
1125+ "prelude",
1126+ "tailrec",
1127+ "tuples",
1128+ "unfoldable"
1129+ ]
1130+ },
1131+ "maybe": {
1132+ "type": "registry",
1133+ "version": "6.0.0",
1134+ "integrity": "sha256-8X6XEgtZ5lqfkEuc1hWOofnL6mwhk8gSJTxwvbR/SbY=",
1135+ "dependencies": [
1136+ "control",
1137+ "invariant",
1138+ "newtype",
1139+ "prelude"
1140+ ]
1141+ },
1142+ "mmorph": {
1143+ "type": "registry",
1144+ "version": "7.0.0",
1145+ "integrity": "sha256-Cfltaq+tfYjuSoSBN/b8cSQZbvZTqIRs6ebQewbIkGs=",
1146+ "dependencies": [
1147+ "bifunctors",
1148+ "either",
1149+ "free",
1150+ "functors",
1151+ "identity",
1152+ "maybe",
1153+ "newtype",
1154+ "prelude",
1155+ "transformers",
1156+ "tuples"
1157+ ]
1158+ },
1159+ "newtype": {
1160+ "type": "registry",
1161+ "version": "5.0.0",
1162+ "integrity": "sha256-dt6w0cty4OS+Pjt9fsh3iU6ottqSU83mdAZkaEEvo6c=",
1163+ "dependencies": [
1164+ "prelude",
1165+ "safe-coerce"
1166+ ]
1167+ },
1168+ "node-buffer": {
1169+ "type": "registry",
1170+ "version": "9.0.0",
1171+ "integrity": "sha256-RdQjilmEHqsT4fwpCr8Mavw8KTafYrS3ZM6zeAAVAl8=",
1172+ "dependencies": [
1173+ "arraybuffer-types",
1174+ "effect",
1175+ "functions",
1176+ "maybe",
1177+ "nullable",
1178+ "partial",
1179+ "prelude",
1180+ "st",
1181+ "unsafe-coerce"
1182+ ]
1183+ },
1184+ "node-event-emitter": {
1185+ "type": "registry",
1186+ "version": "3.0.0",
1187+ "integrity": "sha256-wodx71NxJBPXOaawFn01V1ByYB2vT+I3RuV2giOVKMg=",
1188+ "dependencies": [
1189+ "effect",
1190+ "either",
1191+ "functions",
1192+ "maybe",
1193+ "nullable",
1194+ "prelude",
1195+ "unsafe-coerce"
1196+ ]
1197+ },
1198+ "node-fs": {
1199+ "type": "registry",
1200+ "version": "9.2.0",
1201+ "integrity": "sha256-fxioTSm9y47WuYs9F/7nxCh/RVDCl3Kr3Hg779J4SJA=",
1202+ "dependencies": [
1203+ "aff",
1204+ "datetime",
1205+ "effect",
1206+ "either",
1207+ "enums",
1208+ "exceptions",
1209+ "functions",
1210+ "integers",
1211+ "js-date",
1212+ "maybe",
1213+ "node-buffer",
1214+ "node-path",
1215+ "node-streams",
1216+ "nullable",
1217+ "partial",
1218+ "prelude",
1219+ "strings"
1220+ ]
1221+ },
1222+ "node-path": {
1223+ "type": "registry",
1224+ "version": "5.0.1",
1225+ "integrity": "sha256-j7n/SmpVz0FOMJl4XZop3ofJ+MeIPkMNqUEUKHEL6Us=",
1226+ "dependencies": [
1227+ "effect"
1228+ ]
1229+ },
1230+ "node-process": {
1231+ "type": "registry",
1232+ "version": "11.2.0",
1233+ "integrity": "sha256-onzKeNmaeYfN3HSDPqSFTrrP2Yl9tnVsfKKhnf2plxM=",
1234+ "dependencies": [
1235+ "effect",
1236+ "exceptions",
1237+ "foreign",
1238+ "foreign-object",
1239+ "maybe",
1240+ "node-event-emitter",
1241+ "node-streams",
1242+ "nullable",
1243+ "posix-types",
1244+ "prelude",
1245+ "strings"
1246+ ]
1247+ },
1248+ "node-streams": {
1249+ "type": "registry",
1250+ "version": "9.0.1",
1251+ "integrity": "sha256-yuVGm/R/tBr4Nphi+a1a984Z0fkmN9Q5wWtSmbmJTpA=",
1252+ "dependencies": [
1253+ "aff",
1254+ "arrays",
1255+ "effect",
1256+ "either",
1257+ "exceptions",
1258+ "maybe",
1259+ "node-buffer",
1260+ "node-event-emitter",
1261+ "nullable",
1262+ "prelude",
1263+ "refs",
1264+ "st",
1265+ "tailrec",
1266+ "unsafe-coerce"
1267+ ]
1268+ },
1269+ "nonempty": {
1270+ "type": "registry",
1271+ "version": "7.0.0",
1272+ "integrity": "sha256-Ctkq8/+KiGqCE53Y/LvibA/coy7ev9HtRZU+GYS7yfQ=",
1273+ "dependencies": [
1274+ "control",
1275+ "foldable-traversable",
1276+ "maybe",
1277+ "prelude",
1278+ "tuples",
1279+ "unfoldable"
1280+ ]
1281+ },
1282+ "now": {
1283+ "type": "registry",
1284+ "version": "6.0.0",
1285+ "integrity": "sha256-mTyG4s8tps3XIf0jjV/lME2/QlwMzrQly2wqfSSUM3o=",
1286+ "dependencies": [
1287+ "datetime",
1288+ "effect",
1289+ "prelude"
1290+ ]
1291+ },
1292+ "nullable": {
1293+ "type": "registry",
1294+ "version": "6.0.0",
1295+ "integrity": "sha256-CDAZk+L9Sc0GCFTkE8n+qdp4Ys8avvnkU+m2hVALt7M=",
1296+ "dependencies": [
1297+ "functions",
1298+ "maybe",
1299+ "prelude"
1300+ ]
1301+ },
1302+ "numbers": {
1303+ "type": "registry",
1304+ "version": "9.0.1",
1305+ "integrity": "sha256-ZydYckgwRAnRaFC7pu6fADhzdwX+UqHZrfJyet64zls=",
1306+ "dependencies": [
1307+ "functions",
1308+ "maybe",
1309+ "prelude"
1310+ ]
1311+ },
1312+ "open-memoize": {
1313+ "type": "registry",
1314+ "version": "6.2.0",
1315+ "integrity": "sha256-yJLuVYX8FocHIJ+6q7efH/Pj4S+e1Y57DZ5Dn7qf4ww=",
1316+ "dependencies": [
1317+ "either",
1318+ "integers",
1319+ "lazy",
1320+ "lists",
1321+ "maybe",
1322+ "partial",
1323+ "prelude",
1324+ "strings",
1325+ "tuples"
1326+ ]
1327+ },
1328+ "optparse": {
1329+ "type": "registry",
1330+ "version": "5.0.1",
1331+ "integrity": "sha256-2btDjHPRR0uujUQJuZAN9AzvVoXe7yG6IwnY5evERhQ=",
1332+ "dependencies": [
1333+ "arrays",
1334+ "bifunctors",
1335+ "control",
1336+ "effect",
1337+ "either",
1338+ "enums",
1339+ "exists",
1340+ "exitcodes",
1341+ "foldable-traversable",
1342+ "free",
1343+ "integers",
1344+ "lazy",
1345+ "lists",
1346+ "maybe",
1347+ "newtype",
1348+ "node-buffer",
1349+ "node-process",
1350+ "node-streams",
1351+ "nonempty",
1352+ "numbers",
1353+ "open-memoize",
1354+ "partial",
1355+ "prelude",
1356+ "strings",
1357+ "tailrec",
1358+ "transformers",
1359+ "tuples"
1360+ ]
1361+ },
1362+ "ordered-collections": {
1363+ "type": "registry",
1364+ "version": "3.2.0",
1365+ "integrity": "sha256-NaEXc2cz/7lJfxPWEja4XlZbGxuRqJwFKQJjsJf51kQ=",
1366+ "dependencies": [
1367+ "arrays",
1368+ "control",
1369+ "foldable-traversable",
1370+ "functions",
1371+ "gen",
1372+ "lists",
1373+ "maybe",
1374+ "newtype",
1375+ "partial",
1376+ "prelude",
1377+ "safe-coerce",
1378+ "tailrec",
1379+ "tuples",
1380+ "unfoldable"
1381+ ]
1382+ },
1383+ "orders": {
1384+ "type": "registry",
1385+ "version": "6.0.0",
1386+ "integrity": "sha256-nSMxZK7wxyDULkjZqvMyB71mVo6b0AyLLHosDVbv1XM=",
1387+ "dependencies": [
1388+ "newtype",
1389+ "prelude"
1390+ ]
1391+ },
1392+ "parallel": {
1393+ "type": "registry",
1394+ "version": "7.0.0",
1395+ "integrity": "sha256-bAGpVhrFz2IyHkA4MR7+tE/19FZ7dzYBdYPgK5svkqw=",
1396+ "dependencies": [
1397+ "control",
1398+ "effect",
1399+ "either",
1400+ "foldable-traversable",
1401+ "functors",
1402+ "maybe",
1403+ "newtype",
1404+ "prelude",
1405+ "profunctor",
1406+ "refs",
1407+ "transformers"
1408+ ]
1409+ },
1410+ "partial": {
1411+ "type": "registry",
1412+ "version": "4.0.0",
1413+ "integrity": "sha256-mdrlJBAgFMh79hNRW39uv7c+BwnnaOrAMmdh7+VhEhs=",
1414+ "dependencies": []
1415+ },
1416+ "pipes": {
1417+ "type": "registry",
1418+ "version": "8.0.0",
1419+ "integrity": "sha256-dtUNpG8BGVr7pu6mQZyAnUAftUHgNS7f0QH3Kw5UTpQ=",
1420+ "dependencies": [
1421+ "aff",
1422+ "control",
1423+ "effect",
1424+ "either",
1425+ "foldable-traversable",
1426+ "identity",
1427+ "lists",
1428+ "maybe",
1429+ "mmorph",
1430+ "newtype",
1431+ "prelude",
1432+ "tailrec",
1433+ "transformers",
1434+ "tuples"
1435+ ]
1436+ },
1437+ "posix-types": {
1438+ "type": "registry",
1439+ "version": "6.0.0",
1440+ "integrity": "sha256-Je5jG439F/SFO/IvVevZnWVxDIonrehlKuJkefP2lHE=",
1441+ "dependencies": [
1442+ "maybe",
1443+ "newtype",
1444+ "prelude"
1445+ ]
1446+ },
1447+ "prelude": {
1448+ "type": "registry",
1449+ "version": "6.0.2",
1450+ "integrity": "sha256-IqykrDRquGUD/LRSad7y75hZv3bUsGQ4knc8tdez8Qw=",
1451+ "dependencies": []
1452+ },
1453+ "profunctor": {
1454+ "type": "registry",
1455+ "version": "6.0.1",
1456+ "integrity": "sha256-Ow0mJC+PIIRq/a3mzCWY5vxuTgR/e+Ee68+mWeSRnWY=",
1457+ "dependencies": [
1458+ "control",
1459+ "distributive",
1460+ "either",
1461+ "exists",
1462+ "invariant",
1463+ "newtype",
1464+ "prelude",
1465+ "tuples"
1466+ ]
1467+ },
1468+ "record": {
1469+ "type": "registry",
1470+ "version": "4.0.0",
1471+ "integrity": "sha256-WQ8fqp4X1wTA70J4qUcPW4Z7DCwx6e5KJnT/EuTdWSc=",
1472+ "dependencies": [
1473+ "functions",
1474+ "prelude",
1475+ "unsafe-coerce"
1476+ ]
1477+ },
1478+ "refs": {
1479+ "type": "registry",
1480+ "version": "6.0.0",
1481+ "integrity": "sha256-KKD5G9dR2SauuDGULUJsxjqDOEi1Jqm+2Sq5U2mY8YU=",
1482+ "dependencies": [
1483+ "effect",
1484+ "prelude"
1485+ ]
1486+ },
1487+ "safe-coerce": {
1488+ "type": "registry",
1489+ "version": "2.0.0",
1490+ "integrity": "sha256-EJrxtKt5xC7TYjBZrSBO/J7Aw3DmtilYjt4olpAXWVc=",
1491+ "dependencies": [
1492+ "unsafe-coerce"
1493+ ]
1494+ },
1495+ "spec": {
1496+ "type": "registry",
1497+ "version": "8.1.1",
1498+ "integrity": "sha256-b6qjDb7lUJGLV+WEoywLu6BCXC4zGpfbN43mTL+vBeI=",
1499+ "dependencies": [
1500+ "aff",
1501+ "ansi",
1502+ "arrays",
1503+ "avar",
1504+ "bifunctors",
1505+ "control",
1506+ "datetime",
1507+ "effect",
1508+ "either",
1509+ "exceptions",
1510+ "foldable-traversable",
1511+ "fork",
1512+ "identity",
1513+ "integers",
1514+ "lists",
1515+ "maybe",
1516+ "newtype",
1517+ "now",
1518+ "ordered-collections",
1519+ "parallel",
1520+ "pipes",
1521+ "prelude",
1522+ "refs",
1523+ "strings",
1524+ "tailrec",
1525+ "transformers",
1526+ "tuples"
1527+ ]
1528+ },
1529+ "spec-discovery": {
1530+ "type": "registry",
1531+ "version": "8.4.0",
1532+ "integrity": "sha256-aFp8bllT/wrxQu8hMlDchQQY08dQAz+Xdq2hZi5z3yY=",
1533+ "dependencies": [
1534+ "aff",
1535+ "effect",
1536+ "foldable-traversable",
1537+ "prelude",
1538+ "spec",
1539+ "spec-node"
1540+ ]
1541+ },
1542+ "spec-node": {
1543+ "type": "registry",
1544+ "version": "0.0.3",
1545+ "integrity": "sha256-8/9+g0obbamV0YtqzmttbWs8HaWF7CEeW+eDtqzuAAo=",
1546+ "dependencies": [
1547+ "aff",
1548+ "argonaut-codecs",
1549+ "argonaut-core",
1550+ "arrays",
1551+ "control",
1552+ "datetime",
1553+ "effect",
1554+ "either",
1555+ "foldable-traversable",
1556+ "identity",
1557+ "integers",
1558+ "maybe",
1559+ "newtype",
1560+ "node-buffer",
1561+ "node-fs",
1562+ "node-process",
1563+ "now",
1564+ "numbers",
1565+ "optparse",
1566+ "ordered-collections",
1567+ "partial",
1568+ "prelude",
1569+ "spec",
1570+ "strings",
1571+ "tuples"
1572+ ]
1573+ },
1574+ "st": {
1575+ "type": "registry",
1576+ "version": "6.2.0",
1577+ "integrity": "sha256-WI4MEkkwUd4pnwZQ3G8VKWgX5t1RSNJludm5e9boaRo=",
1578+ "dependencies": [
1579+ "effect",
1580+ "partial",
1581+ "prelude",
1582+ "tailrec",
1583+ "unsafe-coerce"
1584+ ]
1585+ },
1586+ "strings": {
1587+ "type": "registry",
1588+ "version": "6.0.1",
1589+ "integrity": "sha256-FNto2hoNW5Da6W6crIk77YXMagBvOGHZE1kO7eZ1vLM=",
1590+ "dependencies": [
1591+ "arrays",
1592+ "control",
1593+ "either",
1594+ "enums",
1595+ "foldable-traversable",
1596+ "gen",
1597+ "integers",
1598+ "maybe",
1599+ "newtype",
1600+ "nonempty",
1601+ "partial",
1602+ "prelude",
1603+ "tailrec",
1604+ "tuples",
1605+ "unfoldable",
1606+ "unsafe-coerce"
1607+ ]
1608+ },
1609+ "strings-extra": {
1610+ "type": "registry",
1611+ "version": "4.0.0",
1612+ "integrity": "sha256-Wlsa9A4hg4PnZYa9WsE0e820xilquVwm33nn067qNIA=",
1613+ "dependencies": [
1614+ "arrays",
1615+ "foldable-traversable",
1616+ "prelude",
1617+ "strings",
1618+ "unicode"
1619+ ]
1620+ },
1621+ "tailrec": {
1622+ "type": "registry",
1623+ "version": "6.1.0",
1624+ "integrity": "sha256-xrorCfP0xV1wubs27idQCHQqdvSUuqmmL/am7Ji1wVU=",
1625+ "dependencies": [
1626+ "bifunctors",
1627+ "effect",
1628+ "either",
1629+ "identity",
1630+ "maybe",
1631+ "partial",
1632+ "prelude",
1633+ "refs"
1634+ ]
1635+ },
1636+ "transformers": {
1637+ "type": "registry",
1638+ "version": "6.1.0",
1639+ "integrity": "sha256-QJmgNT/y7ljPHSsXaW4zxF/982BFiQ90KNL1g/NtEOQ=",
1640+ "dependencies": [
1641+ "control",
1642+ "distributive",
1643+ "effect",
1644+ "either",
1645+ "exceptions",
1646+ "foldable-traversable",
1647+ "identity",
1648+ "lazy",
1649+ "maybe",
1650+ "newtype",
1651+ "prelude",
1652+ "st",
1653+ "tailrec",
1654+ "tuples",
1655+ "unfoldable"
1656+ ]
1657+ },
1658+ "tuples": {
1659+ "type": "registry",
1660+ "version": "7.0.0",
1661+ "integrity": "sha256-BKy7EfK8S1KeTCwyWqyW1wwcpSAQuh3IsczSVgS6fzY=",
1662+ "dependencies": [
1663+ "control",
1664+ "invariant",
1665+ "prelude"
1666+ ]
1667+ },
1668+ "type-equality": {
1669+ "type": "registry",
1670+ "version": "4.0.1",
1671+ "integrity": "sha256-BBqYOSnAKmayRvR5mtZoCf4SlYs2ipatD/+5nQx73aw=",
1672+ "dependencies": []
1673+ },
1674+ "typelevel-prelude": {
1675+ "type": "registry",
1676+ "version": "7.0.0",
1677+ "integrity": "sha256-+pHi14/40mTj/+lmCWqL0T7iXIXD1+NSg/KItyyoB0A=",
1678+ "dependencies": [
1679+ "prelude",
1680+ "type-equality"
1681+ ]
1682+ },
1683+ "unfoldable": {
1684+ "type": "registry",
1685+ "version": "6.0.0",
1686+ "integrity": "sha256-BK/6By1sKp/ztk+9CF3q43SV0QDTLVdsGqFerKHSmbg=",
1687+ "dependencies": [
1688+ "foldable-traversable",
1689+ "maybe",
1690+ "partial",
1691+ "prelude",
1692+ "tuples"
1693+ ]
1694+ },
1695+ "unicode": {
1696+ "type": "registry",
1697+ "version": "6.0.0",
1698+ "integrity": "sha256-5KugCNyYxscmZpnMbssOQA96XimuBN/bjHpdrtd5qaY=",
1699+ "dependencies": [
1700+ "arrays",
1701+ "enums",
1702+ "integers",
1703+ "maybe",
1704+ "partial",
1705+ "prelude",
1706+ "strings",
1707+ "unsafe-coerce"
1708+ ]
1709+ },
1710+ "unsafe-coerce": {
1711+ "type": "registry",
1712+ "version": "6.0.0",
1713+ "integrity": "sha256-0L1QsaY20OILjfU5TV72d3U/tSjhmL9hJ32WMp857Lk=",
1714+ "dependencies": []
1715+ },
1716+ "variant": {
1717+ "type": "registry",
1718+ "version": "8.0.0",
1719+ "integrity": "sha256-Ydrgl8liWEwYQOWW76PdZtg3vxKpoKgsnmFyTLgZkoU=",
1720+ "dependencies": [
1721+ "control",
1722+ "enums",
1723+ "foldable-traversable",
1724+ "lists",
1725+ "maybe",
1726+ "partial",
1727+ "prelude",
1728+ "type-equality",
1729+ "unsafe-coerce"
1730+ ]
1731+ },
1732+ "yoga-tree": {
1733+ "type": "registry",
1734+ "version": "1.0.0",
1735+ "integrity": "sha256-s8rIVEQkRi1VrMc92T9ceXcY0X6r5A4QqT6f7GgmDQI=",
1736+ "dependencies": [
1737+ "arrays",
1738+ "control",
1739+ "foldable-traversable",
1740+ "free",
1741+ "maybe",
1742+ "prelude",
1743+ "tailrec"
1744+ ]
1745+ }
1746+ }
1747+}
spago.yamlnew file+52
@@ -0,0 +1,52 @@
1+package:
2+ name: yoga-json
3+ dependencies:
4+ - arrays: ">=7.3.0 <8.0.0"
5+ - bifunctors: ">=6.0.0 <7.0.0"
6+ - control: ">=6.0.0 <7.0.0"
7+ - datetime: ">=6.1.0 <7.0.0"
8+ - effect: ">=4.0.0 <5.0.0"
9+ - either: ">=6.1.0 <7.0.0"
10+ - exceptions: ">=6.1.0 <7.0.0"
11+ - foldable-traversable: ">=6.0.0 <7.0.0"
12+ - foreign: ">=7.0.0 <8.0.0"
13+ - foreign-object: ">=4.1.0 <5.0.0"
14+ - free: ">=7.1.0 <8.0.0"
15+ - identity: ">=6.0.0 <7.0.0"
16+ - integers: ">=6.0.0 <7.0.0"
17+ - js-bigints: ">=2.2.1 <3.0.0"
18+ - js-date: ">=8.0.0 <9.0.0"
19+ - lists: ">=7.0.0 <8.0.0"
20+ - maybe: ">=6.0.0 <7.0.0"
21+ - newtype: ">=5.0.0 <6.0.0"
22+ - nullable: ">=6.0.0 <7.0.0"
23+ - numbers: ">=9.0.1 <10.0.0"
24+ - ordered-collections: ">=3.2.0 <4.0.0"
25+ - partial: ">=4.0.0 <5.0.0"
26+ - prelude: ">=6.0.2 <7.0.0"
27+ - record: ">=4.0.0 <5.0.0"
28+ - safe-coerce: ">=2.0.0 <3.0.0"
29+ - strings: ">=6.0.1 <7.0.0"
30+ - transformers: ">=6.1.0 <7.0.0"
31+ - tuples: ">=7.0.0 <8.0.0"
32+ - typelevel-prelude: ">=7.0.0 <8.0.0"
33+ - unsafe-coerce: ">=6.0.0 <7.0.0"
34+ - variant: ">=8.0.0 <9.0.0"
35+ - yoga-tree: ">=1.0.0 <2.0.0"
36+ test:
37+ main: Test.Main
38+ dependencies:
39+ - spec
40+ - spec-node
41+ - spec-discovery
42+ - strings-extra
43+
44+ publish:
45+ version: 5.2.2
46+ license: MIT
47+ location:
48+ githubOwner: rowtype-yoga
49+ githubRepo: purescript-yoga-json
50+workspace:
51+ packageSet:
52+ registry: 63.2.1
src/JSON.jsdeleted−5
@@ -1,5 +0,0 @@
1−export const _parseJSON = JSON.parse;
2−
3−export const _undefined = undefined;
4−
5−export const _unsafeStringify = JSON.stringify;
src/JSON.pursdeleted−394
@@ -1,394 +0,0 @@
1−module JSON
2−( E
3−, readJSON
4−, readJSON'
5−, readJSON_
6−, writeJSON
7−, write
8−, read
9−, read'
10−, read_
11−, parseJSON
12−, undefined
13−, unsafeStringify
14−
15−, class ReadForeign
16−, readImpl
17−, class ReadForeignFields
18−, getFields
19−, class ReadForeignVariant
20−, readVariantImpl
21−
22−, class WriteForeign
23−, writeImpl
24−, class WriteForeignFields
25−, writeImplFields
26−, class WriteForeignVariant
27−, writeVariantImpl
28−
29−) where
30−
31−import Prelude
32−
33−import Control.Alt ((<|>))
34−import Control.Monad.Except (ExceptT(..), except, runExcept, runExceptT, withExcept)
35−import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
36−import Data.Bifunctor (lmap)
37−import Data.Either (Either(..), hush, note)
38−import Data.Identity (Identity(..))
39−import Data.List.NonEmpty (singleton)
40−import Data.Maybe (Maybe(..), maybe)
41−import Data.Nullable (Nullable, toMaybe, toNullable)
42−import Data.Symbol (class IsSymbol, reflectSymbol)
43−import Data.Traversable (sequence, traverse)
44−import Data.TraversableWithIndex (traverseWithIndex)
45−import Data.Variant (Variant, inj, on)
46−import Effect.Exception (message, try)
47−import Effect.Uncurried as EU
48−import Effect.Unsafe (unsafePerformEffect)
49−import Foreign (F, Foreign, ForeignError(..), MultipleErrors, fail, isNull, isUndefined, readArray, readBoolean, readChar, readInt, readNull, readNumber, readString, tagOf, unsafeFromForeign, unsafeToForeign)
50−import Foreign.Index (readProp)
51−import Foreign.Object (Object)
52−import Foreign.Object as Object
53−import Partial.Unsafe (unsafeCrashWith)
54−import Prim.Row as Row
55−import Prim.RowList (class RowToList, Cons, Nil, RowList)
56−import Record (get)
57−import Record.Builder (Builder)
58−import Record.Builder as Builder
59−import Type.Prelude (Proxy(..))
60−
61−-- | An alias for the Either result of decoding
62−type E a = Either MultipleErrors a
63−
64−-- | Read a JSON string to a type `a` while returning a `MultipleErrors` if the
65−-- | parsing failed.
66−readJSON :: forall a
67− . ReadForeign a
68− => String
69− -> E a
70−readJSON = runExcept <<< (readImpl <=< parseJSON)
71−
72−-- | Read a JSON string to a type `a` using `F a`. Useful with record types.
73−readJSON' :: forall a
74− . ReadForeign a
75− => String
76− -> F a
77−readJSON' = readImpl <=< parseJSON
78−
79−-- | Read a JSON string to a type `a` while returning `Nothing` if the parsing
80−-- | failed.
81−readJSON_ :: forall a
82− . ReadForeign a
83− => String
84− -> Maybe a
85−readJSON_ = hush <<< readJSON
86−
87−-- | JSON.stringify
88−foreign import _unsafeStringify :: forall a. a -> String
89−
90−unsafeStringify :: forall a. a -> String
91−unsafeStringify = _unsafeStringify
92−
93−-- | Write a JSON string from a type `a`.
94−writeJSON :: forall a
95− . WriteForeign a
96− => a
97− -> String
98−writeJSON = _unsafeStringify <<< writeImpl
99−
100−write :: forall a
101− . WriteForeign a
102− => a
103− -> Foreign
104−write = writeImpl
105−
106−-- | Read a Foreign value to a type
107−read :: forall a
108− . ReadForeign a
109− => Foreign
110− -> E a
111−read = runExcept <<< readImpl
112−
113−-- | Read a value of any type as Foreign to a type
114−readAsForeign :: forall a b
115− . ReadForeign a
116− => b
117− -> E a
118−readAsForeign = read <<< unsafeToForeign
119−
120−read' :: forall a
121− . ReadForeign a
122− => Foreign
123− -> F a
124−read' = readImpl
125−
126−-- | Read a Foreign value to a type, as a Maybe of type
127−read_ :: forall a
128− . ReadForeign a
129− => Foreign
130− -> Maybe a
131−read_ = hush <<< read
132−
133−foreign import _parseJSON :: EU.EffectFn1 String Foreign
134−
135−parseJSON :: String -> F Foreign
136−parseJSON
137− = ExceptT
138− <<< Identity
139− <<< lmap (pure <<< ForeignError <<< message)
140− <<< runPure
141− <<< try
142− <<< EU.runEffectFn1 _parseJSON
143− where
144− -- Nate Faubion: "It uses unsafePerformEffect because that’s the only way to catch exceptions and still use the builtin json decoder"
145− runPure = unsafePerformEffect
146−
147−foreign import _undefined :: Foreign
148−
149−undefined :: Foreign
150−undefined = _undefined
151−
152−-- | A class for reading foreign values to a type
153−class ReadForeign a where
154− readImpl :: Foreign -> F a
155−
156−instance readForeign :: ReadForeign Foreign where
157− readImpl = pure
158−
159−instance readChar :: ReadForeign Char where
160− readImpl = readChar
161−
162−instance readNumber :: ReadForeign Number where
163− readImpl = readNumber
164−
165−instance readInt :: ReadForeign Int where
166− readImpl = readInt
167−
168−instance readString :: ReadForeign String where
169− readImpl = readString
170−
171−instance readBoolean :: ReadForeign Boolean where
172− readImpl = readBoolean
173−
174−instance readArray :: ReadForeign a => ReadForeign (Array a) where
175− readImpl = traverseWithIndex readAtIdx <=< readArray
176− where
177− readAtIdx i f = withExcept (map (ErrorAtIndex i)) (readImpl f)
178−
179−instance readMaybe :: ReadForeign a => ReadForeign (Maybe a) where
180− readImpl = readNullOrUndefined readImpl
181− where
182− readNullOrUndefined _ value | isNull value || isUndefined value = pure Nothing
183− readNullOrUndefined f value = Just <$> f value
184−
185−instance readNullable :: ReadForeign a => ReadForeign (Nullable a) where
186− readImpl o = withExcept (map reformat) $
187− map toNullable <$> traverse readImpl =<< readNull o
188− where
189− reformat error = case error of
190− TypeMismatch inner other -> TypeMismatch ("Nullable " <> inner) other
191− _ -> error
192−
193−instance readObject :: ReadForeign a => ReadForeign (Object.Object a) where
194− readImpl = sequence <<< Object.mapWithKey (const readImpl) <=< readObject'
195− where
196− readObject' :: Foreign -> F (Object Foreign)
197− readObject' value
198− | tagOf value == "Object" = pure $ unsafeFromForeign value
199− | otherwise = fail $ TypeMismatch "Object" (tagOf value)
200−
201−
202−instance readRecord ::
203− ( RowToList fields fieldList
204− , ReadForeignFields fieldList () fields
205− ) => ReadForeign (Record fields) where
206− readImpl o = flip Builder.build {} <$> getFields fieldListP o
207− where
208− fieldListP = Proxy :: Proxy fieldList
209−
210−-- | A class for reading foreign values from properties
211−class ReadForeignFields (xs :: RowList Type) (from :: Row Type) (to :: Row Type)
212− | xs -> from to where
213− getFields :: Proxy xs
214− -> Foreign
215− -> F (Builder (Record from) (Record to))
216−
217−instance readFieldsCons ::
218− ( IsSymbol name
219− , ReadForeign ty
220− , ReadForeignFields tail from from'
221− , Row.Lacks name from'
222− , Row.Cons name ty from' to
223− ) => ReadForeignFields (Cons name ty tail) from to where
224− getFields _ obj = (compose <$> first) `exceptTApply` rest
225− where
226− first = do
227− value <- withExcept' (readImpl =<< readProp name obj)
228− pure $ Builder.insert nameP value
229− rest = getFields tailP obj
230− nameP = Proxy :: Proxy name
231− tailP = Proxy :: Proxy tail
232− name = reflectSymbol nameP
233− withExcept' = withExcept <<< map $ ErrorAtProperty name
234−
235−exceptTApply :: forall a b e m. Semigroup e => Applicative m => ExceptT e m (a -> b) -> ExceptT e m a -> ExceptT e m b
236−exceptTApply fun a = ExceptT $ applyEither
237− <$> runExceptT fun
238− <*> runExceptT a
239−
240−applyEither :: forall e a b. Semigroup e => Either e (a -> b) -> Either e a -> Either e b
241−applyEither (Left e) (Right _) = Left e
242−applyEither (Left e1) (Left e2) = Left (e1 <> e2)
243−applyEither (Right _) (Left e) = Left e
244−applyEither (Right fun) (Right a) = Right (fun a)
245−
246−instance readFieldsNil ::
247− ReadForeignFields Nil () () where
248− getFields _ _ =
249− pure identity
250−
251−instance readForeignVariant ::
252− ( RowToList variants rl
253− , ReadForeignVariant rl variants
254− ) => ReadForeign (Variant variants) where
255− readImpl o = readVariantImpl (Proxy :: Proxy rl) o
256−
257−class ReadForeignVariant (xs :: RowList Type) (row :: Row Type)
258− | xs -> row where
259− readVariantImpl :: Proxy xs
260− -> Foreign
261− -> F (Variant row)
262−
263−instance readVariantNil ::
264− ReadForeignVariant Nil trash where
265− readVariantImpl _ _ = fail $ ForeignError "Unable to match any variant member."
266−
267−instance readVariantCons ::
268− ( IsSymbol name
269− , ReadForeign ty
270− , Row.Cons name ty trash row
271− , ReadForeignVariant tail row
272− ) => ReadForeignVariant (Cons name ty tail) row where
273− readVariantImpl _ o = do
274− obj :: { type :: String, value :: Foreign } <- readImpl o
275− if obj.type == name
276− then do
277− value :: ty <- readImpl obj.value
278− pure $ inj namep value
279− else
280− (fail <<< ForeignError $ "Did not match variant tag " <> name)
281− <|> readVariantImpl (Proxy :: Proxy tail) o
282− where
283− namep = Proxy :: Proxy name
284− name = reflectSymbol namep
285−
286−-- -- | A class for writing a value into JSON
287−-- -- | need to do this intelligently using Foreign probably, because of null and undefined whatever
288−class WriteForeign a where
289− writeImpl :: a -> Foreign
290−
291−instance WriteForeign Foreign where
292− writeImpl = identity
293−
294−instance WriteForeign String where
295− writeImpl = unsafeToForeign
296−
297−instance WriteForeign Int where
298− writeImpl = unsafeToForeign
299−
300−instance WriteForeign Char where
301− writeImpl = unsafeToForeign
302−
303−instance WriteForeign Number where
304− writeImpl = unsafeToForeign
305−
306−instance WriteForeign Boolean where
307− writeImpl = unsafeToForeign
308−
309−instance WriteForeign a => WriteForeign (Array a) where
310− writeImpl xs = unsafeToForeign $ writeImpl <$> xs
311−
312−instance WriteForeign a => WriteForeign (Maybe a) where
313− writeImpl = maybe undefined writeImpl
314−
315−instance WriteForeign a => WriteForeign (Nullable a) where
316− writeImpl = maybe (unsafeToForeign $ toNullable Nothing) writeImpl <<< toMaybe
317−
318−instance WriteForeign a => WriteForeign (Object.Object a) where
319− writeImpl = unsafeToForeign <<< Object.mapWithKey (const writeImpl)
320−
321−instance
322− ( RowToList row rl
323− , WriteForeignFields rl row () to
324− ) => WriteForeign (Record row) where
325− writeImpl rec = unsafeToForeign $ Builder.build steps {}
326− where
327− rlp = Proxy :: Proxy rl
328− steps = writeImplFields rlp rec
329−
330−class WriteForeignFields (rl :: RowList Type) row (from :: Row Type) (to :: Row Type)
331− | rl -> row from to where
332− writeImplFields :: forall g. g rl -> Record row -> Builder (Record from) (Record to)
333−
334−instance
335− ( IsSymbol name
336− , WriteForeign ty
337− , WriteForeignFields tail row from from'
338− , Row.Cons name ty whatever row
339− , Row.Lacks name from'
340− , Row.Cons name Foreign from' to
341− ) => WriteForeignFields (Cons name ty tail) row from to where
342− writeImplFields _ rec = result
343− where
344− namep = Proxy :: Proxy name
345− value = writeImpl $ get namep rec
346− tailp = Proxy :: Proxy tail
347− rest = writeImplFields tailp rec
348− result = Builder.insert namep value <<< rest
349−instance
350− WriteForeignFields Nil row () () where
351− writeImplFields _ _ = identity
352−
353−instance
354− ( RowToList row rl
355− , WriteForeignVariant rl row
356− ) => WriteForeign (Variant row) where
357− writeImpl variant = writeVariantImpl (Proxy :: Proxy rl) variant
358−
359−class WriteForeignVariant (rl :: RowList Type) (row :: Row Type)
360− | rl -> row where
361− writeVariantImpl :: forall g. g rl -> Variant row -> Foreign
362−
363−instance
364− WriteForeignVariant Nil () where
365− writeVariantImpl _ _ =
366− -- a PureScript-defined variant cannot reach this path, but a JavaScript FFI one could.
367− unsafeCrashWith "Variant was not able to be writen row WriteForeign."
368−
369−instance
370− ( IsSymbol name
371− , WriteForeign ty
372− , Row.Cons name ty subRow row
373− , WriteForeignVariant tail subRow
374− ) => WriteForeignVariant (Cons name ty tail) row where
375− writeVariantImpl _ variant =
376− on
377− namep
378− writeVariant
379− (writeVariantImpl (Proxy :: Proxy tail))
380− variant
381− where
382− namep = Proxy :: Proxy name
383− writeVariant value = unsafeToForeign
384− { type: reflectSymbol namep
385− , value: writeImpl value
386− }
387−
388−instance ReadForeign a => ReadForeign (NonEmptyArray a) where
389− readImpl f = do
390− raw :: Array a <- readImpl f
391− except $ note (singleton $ ForeignError "Nonempty array expected, got empty array") $ fromArray raw
392−
393−instance writeForeignNEArray :: WriteForeign a => WriteForeign (NonEmptyArray a) where
394− writeImpl a = writeImpl <<< toArray $ a
src/Yoga/JSON.jsnew file+19
@@ -0,0 +1,19 @@
1+function reviver(key, value) {
2+ if (key === "big") {
3+ return BigInt(value);
4+ }
5+ return value;
6+}
7+export const _parseJSON = (payload) => JSON.parse(payload, reviver);
8+
9+export const _undefined = undefined;
10+
11+function replacer(key, value) {
12+ if (typeof value === "bigint") {
13+ return value.toString();
14+ }
15+ return value;
16+}
17+
18+export const _unsafeStringify = (data) => JSON.stringify(data, replacer);
19+export const _unsafePrettyStringify = spaces => data => JSON.stringify(data, replacer, spaces);
src/Yoga/JSON.pursnew file+683
@@ -0,0 +1,683 @@
1+module Yoga.JSON
2+ ( E
3+ , readJSON
4+ , readJSON'
5+ , readJSON_
6+ , writeJSON
7+ , writePrettyJSON
8+ , write
9+ , read
10+ , read'
11+ , read_
12+ , parseJSON
13+ , undefined
14+ , unsafeStringify
15+ , class ReadForeign
16+ , readImpl
17+ , class ReadForeignFields
18+ , getFields
19+ , class ReadForeignVariant
20+ , readVariantImpl
21+ , class ReadTuple
22+ , readTupleImpl
23+ , tupleSize
24+ , class WriteForeign
25+ , writeImpl
26+ , class WriteForeignFields
27+ , writeImplFields
28+ , class WriteForeignVariant
29+ , writeVariantImpl
30+ ) where
31+
32+import Prelude
33+
34+import Control.Alt ((<|>))
35+import Control.Apply (lift2)
36+import Control.Comonad.Cofree as Cofree
37+import Control.Monad.Except (ExceptT(..), except, runExcept, throwError, withExcept)
38+import Data.Array as Array
39+import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
40+import Data.Bifunctor (lmap)
41+import Data.DateTime (DateTime)
42+import Data.DateTime.Instant (Instant, instant, unInstant)
43+import Data.Either (Either(..), hush, note)
44+import Data.Foldable (class Foldable, foldl)
45+import Data.FoldableWithIndex (foldrWithIndex)
46+import Data.FunctorWithIndex (mapWithIndex)
47+import Data.Identity (Identity(..))
48+import Data.Int as Int
49+import Data.JSDate (JSDate)
50+import Data.JSDate as JSDate
51+import Data.List.NonEmpty (NonEmptyList, singleton)
52+import Data.Map (Map)
53+import Data.Map as Map
54+import Data.Maybe (Maybe(..), fromMaybe, fromMaybe', maybe)
55+import Data.Newtype (class Newtype, unwrap, wrap)
56+import Data.Nullable (Nullable, toMaybe, toNullable)
57+import Data.Number as Number
58+import Data.Set (Set)
59+import Data.Set as Set
60+import Data.String.NonEmpty.Internal (NonEmptyString)
61+import Data.String.NonEmpty.Internal as NonEmptyString
62+import Data.Symbol (class IsSymbol, reflectSymbol)
63+import Data.Time.Duration (Days, Hours, Milliseconds, Minutes, Seconds)
64+import Data.Traversable (traverse)
65+import Data.Tuple (Tuple(..))
66+import Data.Variant (Variant, inj, on)
67+import Effect.Exception (message, try)
68+import Effect.Uncurried as EU
69+import Effect.Unsafe (unsafePerformEffect)
70+import Foreign (F, Foreign, ForeignError(..), MultipleErrors, fail, isNull, isUndefined, readArray, readBoolean, readChar, readInt, readNull, readNumber, readString, tagOf, unsafeFromForeign, unsafeReadTagged, unsafeToForeign)
71+import Foreign.Index (hasOwnProperty, readProp)
72+import Foreign.Object (Object)
73+import Foreign.Object as Object
74+import JS.BigInt (BigInt)
75+import JS.BigInt (fromInt, fromNumber, fromString, toString) as BigInt
76+import Partial.Unsafe (unsafeCrashWith)
77+import Prim.Row as Row
78+import Prim.RowList (class RowToList, Cons, Nil, RowList)
79+import Record (get)
80+import Record.Builder (Builder)
81+import Record.Builder as Builder
82+import Type.Prelude (Proxy(..))
83+import Unsafe.Coerce (unsafeCoerce)
84+import Yoga.Tree (Tree)
85+import Yoga.Tree as Tree
86+
87+-- | An alias for the Either result of decoding
88+type E a = Either MultipleErrors a
89+
90+-- | Read a JSON string to a type `a` while returning a `MultipleErrors` if the
91+-- | parsing failed.
92+readJSON ∷
93+ ∀ @a.
94+ ReadForeign a ⇒
95+ String →
96+ E a
97+readJSON = runExcept <<< (readImpl <=< parseJSON)
98+
99+-- | Read a JSON string to a type `a` using `F a`. Useful with record types.
100+readJSON' ∷
101+ ∀ @a.
102+ ReadForeign a ⇒
103+ String →
104+ F a
105+readJSON' = readImpl <=< parseJSON
106+
107+-- | Read a JSON string to a type `a` while returning `Nothing` if the parsing
108+-- | failed.
109+readJSON_ ∷
110+ ∀ @a.
111+ ReadForeign a ⇒
112+ String →
113+ Maybe a
114+readJSON_ = hush <<< readJSON
115+
116+-- | JSON.stringify
117+foreign import _unsafeStringify ∷ ∀ a. a → String
118+
119+-- | JSON.stringify with a number of spaces
120+foreign import _unsafePrettyStringify ∷ ∀ a. Int → a → String
121+
122+unsafeStringify ∷ ∀ a. a → String
123+unsafeStringify = _unsafeStringify
124+
125+-- | Write a JSON string from a type `a`.
126+writeJSON ∷
127+ ∀ a.
128+ WriteForeign a ⇒
129+ a →
130+ String
131+writeJSON = _unsafeStringify <<< writeImpl
132+
133+writePrettyJSON ∷
134+ ∀ a.
135+ WriteForeign a ⇒
136+ Int →
137+ a →
138+ String
139+writePrettyJSON spaces = _unsafePrettyStringify spaces <<< writeImpl
140+
141+write ∷
142+ ∀ a.
143+ WriteForeign a ⇒
144+ a →
145+ Foreign
146+write = writeImpl
147+
148+-- | Read a Foreign value to a type
149+read ∷
150+ ∀ @a.
151+ ReadForeign a ⇒
152+ Foreign →
153+ E a
154+read = runExcept <<< readImpl
155+
156+read' ∷
157+ ∀ @a.
158+ ReadForeign a ⇒
159+ Foreign →
160+ F a
161+read' = readImpl
162+
163+-- | Read a Foreign value to a type, as a Maybe of type
164+read_ ∷
165+ ∀ @a.
166+ ReadForeign a ⇒
167+ Foreign →
168+ Maybe a
169+read_ = hush <<< read
170+
171+foreign import _parseJSON ∷ EU.EffectFn1 String Foreign
172+
173+parseJSON ∷ String → F Foreign
174+parseJSON = ExceptT
175+ <<< Identity
176+ <<< lmap (pure <<< ForeignError <<< message)
177+ <<< runPure
178+ <<< try
179+ <<< EU.runEffectFn1 _parseJSON
180+ where
181+ -- Nate Faubion: "It uses unsafePerformEffect because that’s the only way to catch exceptions and still use the builtin json decoder"
182+ runPure = unsafePerformEffect
183+
184+foreign import _undefined ∷ Foreign
185+
186+undefined ∷ Foreign
187+undefined = _undefined
188+
189+-- | A class for reading foreign values to a type
190+class ReadForeign a where
191+ readImpl ∷ Foreign → F a
192+
193+instance ReadForeign Foreign where
194+ readImpl = pure
195+
196+instance ReadForeign Char where
197+ readImpl = readChar
198+
199+instance ReadForeign Number where
200+ readImpl = readNumber
201+
202+instance ReadForeign Int where
203+ readImpl = readInt
204+
205+-- | Attempt to coerce a foreign value to a `BigInt`.
206+readBigInt ∷
207+ ∀ m. Monad m ⇒ Foreign → ExceptT (NonEmptyList ForeignError) m BigInt
208+readBigInt = unsafeReadTagged "BigInt"
209+
210+instance ReadForeign BigInt where
211+ readImpl fValue = tryInt fValue <|> tryNumber fValue <|> readBigInt fValue <|> tryString fValue
212+ where
213+ tryInt f = readInt f <#> BigInt.fromInt
214+ tryNumber f = do
215+ num ← readNumber f
216+ if Number.round num == num then
217+ BigInt.fromNumber num
218+ # note (err $ "Cannot convert Number " <> show num <> " to BigInt")
219+ # except
220+ else
221+ (Left $ err $ "Cannot convert decimal Number " <> show num <> " to BigInt")
222+ # except
223+ tryString f = do
224+ bi ← readString f
225+ BigInt.fromString bi
226+ # note (err $ "Cannot convert String " <> bi <> " to BigInt")
227+ # except
228+ err = pure <<< ForeignError
229+
230+instance ReadForeign String where
231+ readImpl = readString
232+
233+instance ReadForeign NonEmptyString where
234+ readImpl = readString >=>
235+ NonEmptyString.fromString
236+ >>> note (pure $ ForeignError "String must not be empty")
237+ >>> except
238+
239+instance ReadForeign Boolean where
240+ readImpl = readBoolean
241+
242+instance ReadForeign a ⇒ ReadForeign (Array a) where
243+ readImpl = sequenceCombining <<< mapWithIndex readAtIdx <=< readArray
244+
245+instance ReadForeign a ⇒ ReadForeign (Maybe a) where
246+ readImpl = readNullOrUndefined readImpl
247+ where
248+ readNullOrUndefined _ value | isNull value || isUndefined value = pure
249+ Nothing
250+ readNullOrUndefined f value = Just <$> f value
251+
252+instance ReadForeign a ⇒ ReadForeign (Nullable a) where
253+ readImpl o = withExcept (map reformat) $
254+ map toNullable <$> traverse readImpl =<< readNull o
255+ where
256+ reformat error = case error of
257+ TypeMismatch inner other → TypeMismatch ("Nullable " <> inner) other
258+ _ → error
259+
260+instance (ReadForeign a, ReadForeign b) ⇒ ReadForeign (Either a b) where
261+ readImpl f = do
262+ { type: tpe, value } ∷ { type ∷ String, value ∷ Foreign } ← readImpl f
263+ case tpe of
264+ "left" → Left <$> readImpl value
265+ "right" → Right <$> readImpl value
266+ _ → except $ Left (pure $ ForeignError $ "Invalid Either tag " <> tpe)
267+
268+instance ReadForeign a ⇒ ReadForeign (Object.Object a) where
269+ readImpl = gatherErrors <<< Object.mapWithKey readProp <=< readObject'
270+ where
271+ gatherErrors ∷ Object (F a) → F (Object a)
272+ gatherErrors = Object.toUnfoldable
273+ >>> Array.foldl fn (Right (Object.empty))
274+ >>> except
275+ where
276+ fn ∷ _ → _ → (Either MultipleErrors (Object a))
277+ fn acc (Tuple k v) = do
278+ case acc, runExcept v of
279+ Left errs, Left errsNew → Left (errs <> errsNew)
280+ Left errs, Right _ → Left errs
281+ Right obj, Right value → Right (Object.insert k value obj)
282+ Right _, Left errs → Left errs
283+
284+ readProp key value = except $ lmap (map (ErrorAtProperty key))
285+ (readImpl value # runExcept)
286+
287+ readObject' ∷ Foreign → F (Object Foreign)
288+ readObject' value
289+ | tagOf value == "Object" = pure $ unsafeFromForeign value
290+ | otherwise = fail $ TypeMismatch "Object" (tagOf value)
291+
292+instance ReadTuple (Tuple a b) ⇒ ReadForeign (Tuple a b) where
293+ readImpl = readTupleImpl 0
294+
295+-- | A class for reading JSON arrays of lenth `n` as nested tuples of size `n`
296+class ReadTuple a where
297+ readTupleImpl ∷ Int → Foreign → F a
298+ tupleSize ∷ Proxy a → Int
299+
300+instance
301+ ( ReadForeign a
302+ , ReadTuple (Tuple b c)
303+ ) ⇒
304+ ReadTuple (Tuple a (Tuple b c)) where
305+ readTupleImpl n =
306+ readImpl
307+ >=> case _ of
308+ arr → case Array.uncons arr of
309+ Just { head, tail } →
310+ lift2 Tuple
311+ (readAtIdx n head)
312+ (readTupleImpl (n + 1) $ writeImpl tail)
313+ _ → throwError $ pure $ TypeMismatch
314+ ( "array of length " <> show
315+ (1 + n + tupleSize (Proxy ∷ Proxy (Tuple b c)))
316+ )
317+ ("array of length " <> show n)
318+ tupleSize _ = 1 + tupleSize (Proxy ∷ Proxy (Tuple b c))
319+else instance readTupleHelper ∷
320+ ( ReadForeign a
321+ , ReadForeign b
322+ ) ⇒
323+ ReadTuple (Tuple a b) where
324+ readTupleImpl n =
325+ readImpl
326+ >=> case _ of
327+ [ a, b ] →
328+ lift2 Tuple (readAtIdx n a) (readAtIdx (n + 1) b)
329+ arr → throwError $ pure $ TypeMismatch
330+ ("array of length " <> show (n + 2))
331+ ("array of length " <> show (n + Array.length arr))
332+
333+ tupleSize = const 2
334+
335+instance
336+ ( RowToList fields fieldList
337+ , ReadForeignFields fieldList () fields
338+ ) ⇒
339+ ReadForeign (Record fields) where
340+ readImpl o = flip Builder.build {} <$> getFields fieldListP o
341+ where
342+ fieldListP = Proxy ∷ Proxy fieldList
343+
344+-- | A class for reading foreign values from properties
345+class
346+ ReadForeignFields (xs ∷ RowList Type) (from ∷ Row Type) (to ∷ Row Type)
347+ | xs → from to where
348+ getFields ∷
349+ Proxy xs →
350+ Foreign →
351+ F (Builder (Record from) (Record to))
352+
353+instance
354+ ( IsSymbol name
355+ , ReadForeign ty
356+ , ReadForeignFields tail from from'
357+ , Row.Lacks name from'
358+ , Row.Cons name ty from' to
359+ ) ⇒
360+ ReadForeignFields (Cons name ty tail) from to where
361+ getFields _ obj = except
362+ case runExcept first, runExcept rest of
363+ Right f, Right r → Right (f <<< r)
364+ Left e1, Left e2 → Left (e1 <> e2)
365+ Right _, Left es → Left es
366+ Left es, Right _ → Left es
367+ where
368+ value = enrichErrorWithPropName (readImpl =<< readProp name obj)
369+ first = Builder.insert nameP <$> value
370+ rest = getFields tailP obj
371+ nameP = Proxy ∷ Proxy name
372+ tailP = Proxy ∷ Proxy tail
373+ name = reflectSymbol nameP
374+ enrichErrorWithPropName = (withExcept <<< map) (ErrorAtProperty name)
375+
376+readAtIdx ∷ ∀ a. ReadForeign a ⇒ Int → Foreign → F a
377+readAtIdx i f = withExcept (map (ErrorAtIndex i)) (readImpl f)
378+
379+instance
380+ ReadForeignFields Nil () () where
381+ getFields _ _ =
382+ pure identity
383+
384+instance
385+ ( RowToList variants rl
386+ , ReadForeignVariant rl variants
387+ ) ⇒
388+ ReadForeign (Variant variants) where
389+ readImpl o = readVariantImpl (Proxy ∷ Proxy rl) o
390+
391+class
392+ ReadForeignVariant (xs ∷ RowList Type) (row ∷ Row Type)
393+ | xs → row where
394+ readVariantImpl ∷
395+ Proxy xs →
396+ Foreign →
397+ F (Variant row)
398+
399+instance
400+ ( IsSymbol name
401+ , ReadForeign ty
402+ , Row.Cons name ty trash row
403+ , ReadForeignVariant tail row
404+ ) ⇒
405+ ReadForeignVariant (Cons name ty tail) row where
406+ readVariantImpl _ o =
407+ if hasOwnProperty @String @Identity name o then rest <|> ado
408+ value ∷ ty ← readProp name o >>= readImpl
409+ in inj namep value
410+ else rest
411+ where
412+ rest = readVariantImpl (Proxy ∷ Proxy tail) o
413+ namep = Proxy ∷ Proxy name
414+ name = reflectSymbol namep
415+
416+instance
417+ ReadForeignVariant Nil trash where
418+ readVariantImpl _ _ = fail $ ForeignError
419+ "Unable to match any variant member."
420+
421+-- -- | A class for writing a value into JSON
422+-- -- | need to do this intelligently using Foreign probably, because of null and undefined whatever
423+class WriteForeign a where
424+ writeImpl ∷ a → Foreign
425+
426+instance WriteForeign Foreign where
427+ writeImpl = identity
428+
429+instance WriteForeign String where
430+ writeImpl = unsafeToForeign
431+
432+instance WriteForeign NonEmptyString where
433+ writeImpl = unsafeToForeign
434+
435+instance WriteForeign Int where
436+ writeImpl = unsafeToForeign
437+
438+instance WriteForeign Char where
439+ writeImpl = unsafeToForeign
440+
441+instance WriteForeign Number where
442+ writeImpl = unsafeToForeign
443+
444+instance WriteForeign BigInt where
445+ writeImpl = unsafeToForeign
446+
447+instance WriteForeign Boolean where
448+ writeImpl = unsafeToForeign
449+
450+instance WriteForeign a ⇒ WriteForeign (Array a) where
451+ writeImpl xs = unsafeToForeign $ writeImpl <$> xs
452+
453+instance WriteForeign a ⇒ WriteForeign (Maybe a) where
454+ writeImpl = maybe undefined writeImpl
455+
456+instance WriteForeign a ⇒ WriteForeign (Nullable a) where
457+ writeImpl = maybe (unsafeToForeign $ toNullable Nothing) writeImpl <<< toMaybe
458+
459+instance (WriteForeign a, WriteForeign b) ⇒ WriteForeign (Either a b) where
460+ writeImpl value = case value of
461+ Left l → writeImpl { type: "left", value: writeImpl l }
462+ Right r → writeImpl { type: "right", value: writeImpl r }
463+
464+instance WriteForeign a ⇒ WriteForeign (Object.Object a) where
465+ writeImpl = unsafeToForeign <<< Object.mapWithKey (const writeImpl)
466+
467+instance
468+ ( WriteForeign a
469+ , WriteForeign (Tuple b c)
470+ ) ⇒
471+ WriteForeign (Tuple a (Tuple b c)) where
472+ writeImpl (Tuple a bc) =
473+ writeImpl bc
474+ # read_
475+ # fromMaybe []
476+ # Array.cons (writeImpl a)
477+ # writeImpl
478+else instance (WriteForeign a, WriteForeign b) ⇒ WriteForeign (Tuple a b) where
479+ writeImpl (Tuple a b) = writeImpl [ writeImpl a, writeImpl b ]
480+
481+instance
482+ ( RowToList row rl
483+ , WriteForeignFields rl row () to
484+ ) ⇒
485+ WriteForeign (Record row) where
486+ writeImpl rec = unsafeToForeign $ Builder.build steps {}
487+ where
488+ rlp = Proxy ∷ Proxy rl
489+ steps = writeImplFields rlp rec
490+
491+class
492+ WriteForeignFields (rl ∷ RowList Type) row (from ∷ Row Type) (to ∷ Row Type)
493+ | rl → row from to where
494+ writeImplFields ∷ ∀ g. g rl → Record row → Builder (Record from) (Record to)
495+
496+instance
497+ ( IsSymbol name
498+ , WriteForeign ty
499+ , WriteForeignFields tail row from from'
500+ , Row.Cons name ty whatever row
501+ , Row.Lacks name from'
502+ , Row.Cons name Foreign from' to
503+ ) ⇒
504+ WriteForeignFields (Cons name ty tail) row from to where
505+ writeImplFields _ rec = result
506+ where
507+ namep = Proxy ∷ Proxy name
508+ value = writeImpl $ get namep rec
509+ tailp = Proxy ∷ Proxy tail
510+ rest = writeImplFields tailp rec
511+ result = Builder.insert namep value <<< rest
512+
513+instance
514+ WriteForeignFields Nil row () () where
515+ writeImplFields _ _ = identity
516+
517+instance
518+ ( RowToList row rl
519+ , WriteForeignVariant rl row
520+ ) ⇒
521+ WriteForeign (Variant row) where
522+ writeImpl variant = writeVariantImpl (Proxy ∷ Proxy rl) variant
523+
524+class
525+ WriteForeignVariant (rl ∷ RowList Type) (row ∷ Row Type)
526+ | rl → row where
527+ writeVariantImpl ∷ ∀ g. g rl → Variant row → Foreign
528+
529+instance
530+ WriteForeignVariant Nil () where
531+ writeVariantImpl _ _ =
532+ -- a PureScript-defined variant cannot reach this path, but a JavaScript FFI one could.
533+ unsafeCrashWith "Attempted to write empty variant."
534+
535+instance
536+ ( IsSymbol name
537+ , WriteForeign ty
538+ , Row.Cons name ty subRow row
539+ , WriteForeignVariant tail subRow
540+ ) ⇒
541+ WriteForeignVariant (Cons name ty tail) row where
542+ writeVariantImpl _ variant =
543+ on
544+ namep
545+ writeVariant
546+ (writeVariantImpl (Proxy ∷ Proxy tail))
547+ variant
548+ where
549+ namep = Proxy ∷ Proxy name
550+ name = reflectSymbol namep
551+ writeVariant value = writeImpl $ Object.singleton name (writeImpl value)
552+
553+instance ReadForeign a ⇒ ReadForeign (NonEmptyArray a) where
554+ readImpl f = do
555+ raw ∷ Array a ← readImpl f
556+ except
557+ $ note
558+ (singleton $ ForeignError "Nonempty array expected, got empty array")
559+ $ fromArray raw
560+
561+instance writeForeignNEArray ∷ WriteForeign a ⇒ WriteForeign (NonEmptyArray a) where
562+ writeImpl a = writeImpl <<< toArray $ a
563+
564+-- Map instances
565+instance (WriteForeign a) ⇒ WriteForeign (Map String a) where
566+ writeImpl = foldrWithIndex Object.insert Object.empty >>> writeImpl
567+else instance (WriteForeign a) ⇒ WriteForeign (Map Int a) where
568+ writeImpl = foldrWithIndex (show >>> Object.insert) Object.empty >>> writeImpl
569+else instance (WriteForeign a) ⇒ WriteForeign (Map BigInt a) where
570+ writeImpl = foldrWithIndex (BigInt.toString >>> Object.insert) Object.empty >>> writeImpl
571+else instance (Newtype nt key, WriteForeign (Map key value)) ⇒ WriteForeign (Map nt value) where
572+ writeImpl = (unsafeCoerce ∷ (_ → Map key value)) >>> writeImpl
573+
574+instance (ReadForeign a) ⇒ ReadForeign (Map String a) where
575+ readImpl = (readImpl ∷ (_ → _ (Object a))) >>> map (foldrWithIndex Map.insert Map.empty)
576+else instance (ReadForeign a) ⇒ ReadForeign (Map Int a) where
577+ readImpl = (readImpl ∷ (_ → _ (Object a))) >>> map (foldrWithIndex (unsafeStringToInt >>> Map.insert) Map.empty)
578+else instance (ReadForeign a) ⇒ ReadForeign (Map BigInt a) where
579+ readImpl = (readImpl ∷ (_ → _ (Object a))) >>> map (foldrWithIndex (unsafeStringToBigInt >>> Map.insert) Map.empty)
580+else instance (Newtype nt key, ReadForeign (Map key value)) ⇒ ReadForeign (Map nt value) where
581+ readImpl = (readImpl ∷ (_ → _ (Map key value))) >>> map (unsafeCoerce ∷ (Map key value → Map nt value))
582+
583+-- Set instances
584+instance (WriteForeign a) ⇒ WriteForeign (Set a) where
585+ writeImpl set = writeImpl (Set.toUnfoldable set ∷ Array a)
586+
587+instance (Ord a, ReadForeign a) ⇒ ReadForeign (Set a) where
588+ readImpl f = Set.fromFoldable <$> (readImpl f ∷ F (Array a))
589+
590+-- Date instances
591+instance WriteForeign JSDate where
592+ writeImpl = JSDate.toISOString >>> unsafePerformEffect >>> writeImpl
593+
594+instance ReadForeign JSDate where
595+ readImpl = readImpl >>> map (JSDate.parse >>> unsafePerformEffect)
596+
597+instance WriteForeign DateTime where
598+ writeImpl = JSDate.fromDateTime >>> writeImpl
599+
600+instance ReadForeign DateTime where
601+ readImpl = readImpl >=>
602+ JSDate.toDateTime
603+ >>> note (pure $ ForeignError "Invalid date time")
604+ >>> except
605+
606+instance WriteForeign Instant where
607+ writeImpl = unInstant >>> writeImpl
608+
609+instance ReadForeign Instant where
610+ readImpl f = do
611+ millis ← readImpl f
612+ case instant millis of
613+ Nothing → except $ Left (pure $ ForeignError "Invalid instant")
614+ Just ins → pure ins
615+
616+instance WriteForeign Milliseconds where
617+ writeImpl = unwrap >>> writeImpl
618+
619+instance ReadForeign Milliseconds where
620+ readImpl = readImpl >>> map wrap
621+
622+instance WriteForeign Seconds where
623+ writeImpl = unwrap >>> writeImpl
624+
625+instance ReadForeign Seconds where
626+ readImpl = readImpl >>> map wrap
627+
628+instance WriteForeign Minutes where
629+ writeImpl = unwrap >>> writeImpl
630+
631+instance ReadForeign Minutes where
632+ readImpl = readImpl >>> map wrap
633+
634+instance WriteForeign Hours where
635+ writeImpl = unwrap >>> writeImpl
636+
637+instance ReadForeign Hours where
638+ readImpl = readImpl >>> map wrap
639+
640+instance WriteForeign Days where
641+ writeImpl = unwrap >>> writeImpl
642+
643+instance ReadForeign Days where
644+ readImpl = readImpl >>> map wrap
645+
646+unsafeStringToInt ∷ String → Int
647+unsafeStringToInt = Int.fromString >>>
648+ (fromMaybe' \_ → unsafeCrashWith "impossible")
649+
650+unsafeStringToBigInt ∷ String → BigInt
651+unsafeStringToBigInt = BigInt.fromString >>>
652+ (fromMaybe' \_ → unsafeCrashWith "impossible")
653+
654+sequenceCombining ∷
655+ ∀ f a.
656+ Monoid (f a) ⇒
657+ Foldable f ⇒
658+ Applicative f ⇒
659+ f (F a) →
660+ F (f a)
661+sequenceCombining = foldl fn (Right mempty) >>> except
662+ where
663+ fn ∷ _ → _ → (Either MultipleErrors (f a))
664+ fn acc elem = do
665+ case acc, runExcept elem of
666+ Left errs, Left errsNew → Left (errs <> errsNew)
667+ Left errs, Right _ → Left errs
668+ Right values, Right value → Right (values <> pure value)
669+ Right _, Left errs → Left errs
670+
671+instance WriteForeign a ⇒ WriteForeign (Tree a) where
672+ writeImpl ∷ Tree a → Foreign
673+ writeImpl t = write { value: Cofree.head t, children }
674+ where
675+ tail = Cofree.tail t
676+ children = if Array.null tail then Nothing else Just (writeImpl <$> tail)
677+
678+instance ReadForeign a ⇒ ReadForeign (Tree a) where
679+ readImpl f = do
680+ { value, children } ∷ { value ∷ a, children ∷ Maybe (Array Foreign) } ← readImpl f
681+ case children of
682+ Nothing → pure (Tree.leaf value)
683+ Just cs → traverse readImpl cs <#> Tree.mkTree value
src/Yoga/JSON/Derive.pursnew file+13
@@ -0,0 +1,13 @@
1+module Yoga.JSON.Derive where
2+
3+import Prelude
4+
5+import Foreign (Foreign, F)
6+import Safe.Coerce (class Coercible, coerce)
7+import Yoga.JSON (class ReadForeign, class WriteForeign, readImpl, writeImpl)
8+
9+writeVia ∷ ∀ @via a. (Coercible a via) ⇒ WriteForeign via ⇒ a → Foreign
10+writeVia = writeImpl <<< (coerce ∷ _ → via)
11+
12+readVia ∷ ∀ @via a. (Coercible a via) ⇒ ReadForeign via ⇒ Foreign → F a
13+readVia fgn = readImpl fgn # map (coerce ∷ via → _)
src/Yoga/JSON/Error.pursnew file+56
@@ -0,0 +1,56 @@
1+module Yoga.JSON.Error where
2+
3+import Prelude
4+
5+import Foreign (ForeignError(..))
6+import Data.Semigroup.Foldable (intercalateMap)
7+import Data.Bifunctor (lmap)
8+import Yoga.JSON (E)
9+import Data.Either (Either)
10+
11+toJSONPath ∷ ForeignError → String
12+toJSONPath fe = "$" <> path
13+ where
14+ path = go fe
15+ go = case _ of
16+ ForeignError _ → ""
17+ TypeMismatch _ _ → ""
18+ ErrorAtIndex i e → "[" <> show i <> "]" <> go e
19+ ErrorAtProperty _ (TypeMismatch _ "undefined") → ""
20+ ErrorAtProperty prop e → "." <> prop <> go e
21+
22+renderHumanError ∷ ForeignError → String
23+renderHumanError = errorToJSON >>> toHuman
24+ where
25+ toHuman { message, path } = message <> " at " <> path
26+
27+withStringErrors :: forall a. E a -> Either String a
28+withStringErrors = lmap (intercalateMap "\n" renderHumanError)
29+
30+errorToJSON ∷
31+ ForeignError →
32+ { message ∷ String
33+ , path ∷ String
34+ }
35+errorToJSON err = go err
36+ where
37+ path = toJSONPath err
38+ go = case _ of
39+ ForeignError s →
40+ { path
41+ , message: s
42+ }
43+ TypeMismatch exp "Undefined" →
44+ { path
45+ , message: "Must provide a value of type '" <> exp <> "'"
46+ }
47+ TypeMismatch exp "undefined" →
48+ { path
49+ , message: "Must provide a value of type '" <> exp <> "'"
50+ }
51+ TypeMismatch exp act →
52+ { path
53+ , message: "Must provide a value of type '" <> exp <> "' instead of '" <> act <> "'"
54+ }
55+ ErrorAtIndex _ e → go e
56+ ErrorAtProperty _ e → go e
src/Yoga/JSON/Generics.pursnew file+8
@@ -0,0 +1,8 @@
1+module Yoga.JSON.Generics
2+ ( module Exported
3+ ) where
4+
5+import Yoga.JSON.Generics.TaggedSumRep (class ReadGenericTaggedSumRep, class WriteGenericTaggedSumRep, Options, defaultOptions, genericReadForeignTaggedSum, genericReadForeignTaggedSumRep, genericWriteForeignTaggedSum, genericWriteForeignTaggedSumRep) as Exported
6+import Yoga.JSON.Generics.UntaggedSumRep (class ReadGenericUntaggedSumRep, class WriteGenericUntaggedSumRep, genericReadForeignUntaggedSum, genericReadForeignUntaggedSumRep, genericWriteForeignUntaggedSum, genericWriteForeignUntaggedSumRep) as Exported
7+import Yoga.JSON.Generics.EnumSumRep (class GenericEnumSumRep, genericEnumReadForeign, genericEnumWriteForeign, genericReadForeignEnum, genericWriteForeignEnum) as Exported
8+import Yoga.JSON.Generics.UntaggedProductRep (class ReadGenericUntaggedProduct, class WriteGenericUntaggedProduct, Offset, genericReadForeignUntaggedProduct, genericReadForeignUntaggedProductRep, genericWriteForeignUntaggedProduct, genericWriteForeignUntaggedProductRep) as Exported
src/Yoga/JSON/Generics/EnumSumRep.pursnew file+65
@@ -0,0 +1,65 @@
1+module Yoga.JSON.Generics.EnumSumRep where
2+
3+import Prelude
4+
5+import Control.Alt ((<|>))
6+import Data.Generic.Rep as GR
7+import Foreign (Foreign, fail)
8+import Foreign as Foreign
9+import Yoga.JSON as JSON
10+import Type.Prelude (class IsSymbol, Proxy(..), reflectSymbol)
11+
12+type Options =
13+ { toConstructorName ∷ String → String }
14+
15+defaultOptions ∷ Options
16+defaultOptions = { toConstructorName: identity }
17+
18+genericReadForeignEnum ∷
19+ ∀ a rep.
20+ GR.Generic a rep ⇒
21+ GenericEnumSumRep rep ⇒
22+ Options →
23+ Foreign →
24+ Foreign.F a
25+genericReadForeignEnum options f =
26+ GR.to <$> genericEnumReadForeign options f
27+
28+genericWriteForeignEnum ∷
29+ ∀ a rep.
30+ GR.Generic a rep ⇒
31+ GenericEnumSumRep rep ⇒
32+ Options →
33+ a →
34+ Foreign
35+genericWriteForeignEnum options a = genericEnumWriteForeign options (GR.from a)
36+
37+-- | Generic Enum Sum Representations, with constructor names as strings
38+class GenericEnumSumRep rep where
39+ genericEnumReadForeign ∷ Options → Foreign → Foreign.F rep
40+ genericEnumWriteForeign ∷ Options → rep → Foreign
41+
42+instance
43+ ( GenericEnumSumRep a
44+ , GenericEnumSumRep b
45+ ) ⇒
46+ GenericEnumSumRep (GR.Sum a b) where
47+ genericEnumReadForeign options f = GR.Inl <$> genericEnumReadForeign options f
48+ <|> GR.Inr <$> genericEnumReadForeign options f
49+ genericEnumWriteForeign options = case _ of
50+ (GR.Inl a) → genericEnumWriteForeign options a
51+ (GR.Inr a) → genericEnumWriteForeign options a
52+
53+instance
54+ ( IsSymbol name
55+ ) ⇒
56+ GenericEnumSumRep (GR.Constructor name GR.NoArguments) where
57+ genericEnumReadForeign options f = do
58+ s ← JSON.readImpl f
59+ if s == options.toConstructorName name then pure $ GR.Constructor GR.NoArguments
60+ else fail <<< Foreign.ForeignError $
61+ "Enum string " <> s <> " did not match expected string " <> options.toConstructorName name
62+ where
63+ name = reflectSymbol (Proxy ∷ Proxy name)
64+ genericEnumWriteForeign options (GR.Constructor GR.NoArguments) =
65+ JSON.writeImpl $ options.toConstructorName (reflectSymbol (Proxy ∷ Proxy name))
src/Yoga/JSON/Generics/TaggedSumRep.pursnew file+131
@@ -0,0 +1,131 @@
1+module Yoga.JSON.Generics.TaggedSumRep where
2+
3+import Prelude
4+
5+import Control.Alt ((<|>))
6+import Control.Monad.Except (withExcept)
7+import Data.Generic.Rep (NoArguments)
8+import Data.Generic.Rep as GR
9+import Data.Maybe (maybe)
10+import Data.Tuple.Nested ((/\))
11+import Foreign (Foreign, ForeignError(..), fail)
12+import Foreign as Foreign
13+import Foreign.Object (Object)
14+import Foreign.Object as Object
15+import Type.Prelude (class IsSymbol, Proxy(..), reflectSymbol)
16+import Yoga.JSON (undefined)
17+import Yoga.JSON as JSON
18+
19+type Options =
20+ { typeTag ∷ String, valueTag ∷ String, toConstructorName ∷ String → String }
21+
22+defaultOptions ∷ Options
23+defaultOptions = { typeTag: "type", valueTag: "value", toConstructorName: identity }
24+
25+genericReadForeignTaggedSum ∷
26+ ∀ a rep.
27+ GR.Generic a rep ⇒
28+ ReadGenericTaggedSumRep rep ⇒
29+ Options →
30+ Foreign →
31+ Foreign.F a
32+genericReadForeignTaggedSum options f =
33+ GR.to <$> genericReadForeignTaggedSumRep options f
34+
35+-- | Generic Tagged Sum Representations, tagged with a "type" field
36+class ReadGenericTaggedSumRep rep where
37+ genericReadForeignTaggedSumRep ∷ Options → Foreign → Foreign.F rep
38+
39+instance
40+ ( ReadGenericTaggedSumRep a
41+ , ReadGenericTaggedSumRep b
42+ ) ⇒
43+ ReadGenericTaggedSumRep (GR.Sum a b) where
44+ genericReadForeignTaggedSumRep options f = GR.Inl <$> genericReadForeignTaggedSumRep options f
45+ <|> GR.Inr <$> genericReadForeignTaggedSumRep options f
46+
47+else instance
48+ ( IsSymbol name
49+ ) ⇒
50+ ReadGenericTaggedSumRep (GR.Constructor name NoArguments) where
51+ genericReadForeignTaggedSumRep { typeTag, toConstructorName } f = do
52+ o ∷ Object Foreign ← JSON.read' f
53+ typeFgn ← maybe (fail ((ErrorAtProperty typeTag) (ForeignError ("Missing type tag: " <> typeTag)))) pure (Object.lookup typeTag o)
54+ typeStr ← JSON.read' typeFgn
55+ if typeStr == name then withExcept (map $ ErrorAtProperty name) $
56+ pure (GR.Constructor GR.NoArguments)
57+ else
58+ fail $ ForeignError $ "Wrong type tag " <> typeStr <> " where " <> typeTag
59+ <> " was expected."
60+ where
61+ nameP = Proxy ∷ Proxy name
62+ name = toConstructorName (reflectSymbol nameP)
63+else instance
64+ ( ReadGenericTaggedSumRep a
65+ , IsSymbol name
66+ ) ⇒
67+ ReadGenericTaggedSumRep (GR.Constructor name a) where
68+ genericReadForeignTaggedSumRep options@{ typeTag, valueTag, toConstructorName } f = do
69+ o ∷ Object Foreign ← JSON.read' f
70+ typeFgn ← maybe (fail ((ErrorAtProperty typeTag) (ForeignError ("Missing type tag: " <> typeTag)))) pure (Object.lookup typeTag o)
71+ typeStr ← JSON.read' typeFgn
72+ value ← maybe (fail ((ErrorAtProperty valueTag) (ForeignError ("Missing value tag: " <> valueTag)))) pure (Object.lookup valueTag o)
73+ if typeStr == name then withExcept (map $ ErrorAtProperty name) $
74+ GR.Constructor <$> genericReadForeignTaggedSumRep options value
75+ else
76+ fail $ ForeignError $ "Wrong constructor name tag " <> typeStr <> " where " <> name
77+ <> " was expected."
78+ where
79+ nameP = Proxy ∷ Proxy name
80+ name = toConstructorName (reflectSymbol nameP)
81+
82+instance (JSON.ReadForeign a) ⇒ ReadGenericTaggedSumRep (GR.Argument a) where
83+ genericReadForeignTaggedSumRep _ f = GR.Argument <$> JSON.readImpl f
84+
85+-- Write
86+
87+genericWriteForeignTaggedSum ∷
88+ ∀ a rep.
89+ GR.Generic a rep ⇒
90+ WriteGenericTaggedSumRep rep ⇒
91+ Options →
92+ a →
93+ Foreign
94+genericWriteForeignTaggedSum options r =
95+ genericWriteForeignTaggedSumRep options (GR.from r)
96+
97+-- | Generic Tagged Sum Representations, tagged with a "type" field
98+class WriteGenericTaggedSumRep rep where
99+ genericWriteForeignTaggedSumRep ∷ Options → rep → Foreign
100+
101+instance
102+ ( WriteGenericTaggedSumRep a
103+ , WriteGenericTaggedSumRep b
104+ ) ⇒
105+ WriteGenericTaggedSumRep (GR.Sum a b) where
106+ genericWriteForeignTaggedSumRep options = case _ of
107+ GR.Inl a → genericWriteForeignTaggedSumRep options a
108+ GR.Inr b → genericWriteForeignTaggedSumRep options b
109+
110+instance
111+ ( WriteGenericTaggedSumRep a
112+ , IsSymbol name
113+ ) ⇒
114+ WriteGenericTaggedSumRep (GR.Constructor name a) where
115+ genericWriteForeignTaggedSumRep options@{ typeTag, valueTag, toConstructorName } (GR.Constructor a) = do
116+ JSON.write
117+ ( Object.fromFoldable
118+ [ typeTag /\ JSON.write name
119+ , valueTag /\ genericWriteForeignTaggedSumRep options a
120+ ]
121+ )
122+ where
123+ nameP = Proxy ∷ Proxy name
124+ name = toConstructorName (reflectSymbol nameP)
125+
126+instance (JSON.WriteForeign a) ⇒ WriteGenericTaggedSumRep (GR.Argument a) where
127+ genericWriteForeignTaggedSumRep _ (GR.Argument a) = JSON.writeImpl a
128+
129+instance
130+ WriteGenericTaggedSumRep GR.NoArguments where
131+ genericWriteForeignTaggedSumRep _ GR.NoArguments = undefined
src/Yoga/JSON/Generics/UntaggedProductRep.pursnew file+86
@@ -0,0 +1,86 @@
1+module Yoga.JSON.Generics.UntaggedProductRep where
2+
3+import Prelude
4+
5+import Data.Array as Array
6+import Data.Generic.Rep as GR
7+import Foreign (Foreign)
8+import Foreign as Foreign
9+import Foreign.Index (readIndex)
10+import Yoga.JSON as JSON
11+
12+genericReadForeignUntaggedProduct ∷
13+ ∀ a rep.
14+ GR.Generic a rep ⇒
15+ ReadGenericUntaggedProduct rep ⇒
16+ Foreign →
17+ Foreign.F a
18+genericReadForeignUntaggedProduct f = GR.to <$> genericReadForeignUntaggedProductRep 0 f
19+
20+type Offset = Int
21+
22+-- | Generic Untagged Product Representations, as a heterogeneous fixed-length array
23+-- | You should consider using records instead in almost any usage.
24+class ReadGenericUntaggedProduct rep where
25+ genericReadForeignUntaggedProductRep ∷ Offset → Foreign → Foreign.F rep
26+
27+instance
28+ ( ReadGenericUntaggedProduct a
29+ ) ⇒
30+ ReadGenericUntaggedProduct (GR.Constructor name a) where
31+ genericReadForeignUntaggedProductRep i f = GR.Constructor <$> genericReadForeignUntaggedProductRep i
32+ f
33+
34+instance
35+ ( JSON.ReadForeign a
36+ ) ⇒
37+ ReadGenericUntaggedProduct (GR.Argument a) where
38+ genericReadForeignUntaggedProductRep i f = do
39+ x ← JSON.readImpl =<< readIndex i f
40+ pure (GR.Argument x)
41+
42+instance
43+ ( ReadGenericUntaggedProduct a
44+ , ReadGenericUntaggedProduct b
45+ ) ⇒
46+ ReadGenericUntaggedProduct (GR.Product a b) where
47+ genericReadForeignUntaggedProductRep i f =
48+ GR.Product
49+ <$> genericReadForeignUntaggedProductRep i f
50+ <*> genericReadForeignUntaggedProductRep (i + 1) f
51+
52+genericWriteForeignUntaggedProduct ∷
53+ ∀ a rep.
54+ GR.Generic a rep ⇒
55+ WriteGenericUntaggedProduct rep ⇒
56+ a →
57+ Foreign
58+genericWriteForeignUntaggedProduct a =
59+ JSON.write (genericWriteForeignUntaggedProductRep [] (GR.from a))
60+
61+-- | Generic Untagged Product Representations, as a heterogeneous fixed-length array
62+-- | You should consider using records instead in almost any usage.
63+class WriteGenericUntaggedProduct rep where
64+ genericWriteForeignUntaggedProductRep ∷ Array Foreign → rep → Array Foreign
65+
66+instance
67+ ( WriteGenericUntaggedProduct a
68+ ) ⇒
69+ WriteGenericUntaggedProduct (GR.Constructor name a) where
70+ genericWriteForeignUntaggedProductRep arr (GR.Constructor a) =
71+ genericWriteForeignUntaggedProductRep arr a
72+
73+instance
74+ ( JSON.WriteForeign a
75+ ) ⇒
76+ WriteGenericUntaggedProduct (GR.Argument a) where
77+ genericWriteForeignUntaggedProductRep arr (GR.Argument a) =
78+ Array.snoc arr (JSON.write a)
79+
80+instance
81+ ( WriteGenericUntaggedProduct a
82+ , WriteGenericUntaggedProduct b
83+ ) ⇒
84+ WriteGenericUntaggedProduct (GR.Product a b) where
85+ genericWriteForeignUntaggedProductRep arr (GR.Product a b) =
86+ genericWriteForeignUntaggedProductRep (genericWriteForeignUntaggedProductRep arr a) b
src/Yoga/JSON/Generics/UntaggedSumRep.pursnew file+76
@@ -0,0 +1,76 @@
1+module Yoga.JSON.Generics.UntaggedSumRep where
2+
3+import Prelude
4+
5+import Control.Alt ((<|>))
6+import Data.Generic.Rep as GR
7+import Foreign (Foreign)
8+import Foreign as Foreign
9+import Yoga.JSON as JSON
10+
11+genericReadForeignUntaggedSum ∷
12+ ∀ a rep.
13+ GR.Generic a rep ⇒
14+ ReadGenericUntaggedSumRep rep ⇒
15+ Foreign →
16+ Foreign.F a
17+genericReadForeignUntaggedSum f = GR.to <$> genericReadForeignUntaggedSumRep f
18+
19+-- | Generic Untagged Sum Representations
20+-- | Note that because the members are untagged, you should verify your members are not the same type
21+class ReadGenericUntaggedSumRep rep where
22+ genericReadForeignUntaggedSumRep ∷ Foreign → Foreign.F rep
23+
24+instance
25+ ( ReadGenericUntaggedSumRep a
26+ , ReadGenericUntaggedSumRep b
27+ ) ⇒
28+ ReadGenericUntaggedSumRep (GR.Sum a b) where
29+ genericReadForeignUntaggedSumRep f = GR.Inl <$> genericReadForeignUntaggedSumRep f
30+ <|> GR.Inr <$> genericReadForeignUntaggedSumRep f
31+
32+instance
33+ ( ReadGenericUntaggedSumRep a
34+ ) ⇒
35+ ReadGenericUntaggedSumRep (GR.Constructor name a) where
36+ genericReadForeignUntaggedSumRep f = GR.Constructor <$> genericReadForeignUntaggedSumRep f
37+
38+instance
39+ ( JSON.ReadForeign a
40+ ) ⇒
41+ ReadGenericUntaggedSumRep (GR.Argument a) where
42+ genericReadForeignUntaggedSumRep f = GR.Argument <$> JSON.readImpl f
43+
44+genericWriteForeignUntaggedSum ∷
45+ ∀ a rep.
46+ GR.Generic a rep ⇒
47+ WriteGenericUntaggedSumRep rep ⇒
48+ a →
49+ Foreign
50+genericWriteForeignUntaggedSum a = GR.from a # genericWriteForeignUntaggedSumRep
51+
52+-- | Generic Untagged Sum Representations
53+-- | Note that because the members are untagged, you should verify your members are not the same type
54+class WriteGenericUntaggedSumRep rep where
55+ genericWriteForeignUntaggedSumRep ∷ rep → Foreign
56+
57+instance
58+ ( WriteGenericUntaggedSumRep a
59+ , WriteGenericUntaggedSumRep b
60+ ) ⇒
61+ WriteGenericUntaggedSumRep (GR.Sum a b) where
62+ genericWriteForeignUntaggedSumRep = case _ of
63+ GR.Inl a → genericWriteForeignUntaggedSumRep a
64+ GR.Inr a → genericWriteForeignUntaggedSumRep a
65+
66+instance
67+ ( WriteGenericUntaggedSumRep a
68+ ) ⇒
69+ WriteGenericUntaggedSumRep (GR.Constructor name a) where
70+ genericWriteForeignUntaggedSumRep (GR.Constructor a) = genericWriteForeignUntaggedSumRep a
71+
72+instance
73+ ( JSON.WriteForeign a
74+ ) ⇒
75+ WriteGenericUntaggedSumRep (GR.Argument a) where
76+ genericWriteForeignUntaggedSumRep (GR.Argument a) = JSON.write a
src/Yoga/JSON/Variant.pursnew file+197
@@ -0,0 +1,197 @@
1+module Yoga.JSON.Variant where
2+
3+import Prelude
4+
5+import Control.Alt ((<|>))
6+import Data.Newtype (class Newtype)
7+import Data.Symbol (class IsSymbol, reflectSymbol)
8+import Data.Tuple.Nested ((/\))
9+import Data.Variant (Variant, inj, on)
10+import Foreign (F, Foreign, ForeignError(..), fail)
11+import Foreign.Index (readProp)
12+import Foreign.Object as Object
13+import Partial.Unsafe (unsafeCrashWith)
14+import Prim.Row as Row
15+import Prim.RowList (class RowToList, Cons, Nil, RowList)
16+import Type.Proxy (Proxy(..))
17+import Yoga.JSON (class ReadForeign, class WriteForeign, readImpl, writeImpl)
18+
19+newtype TaggedVariant ∷ Symbol → Symbol → Row Type → Type
20+newtype TaggedVariant tt vt v = TaggedVariant (Variant v)
21+
22+instance 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)
25+
26+instance
27+ ( RowToList row rl
28+ , WriteForeignTaggedVariant rl row
29+ , IsSymbol typeTag
30+ , IsSymbol valueTag
31+ ) ⇒
32+ WriteForeign (TaggedVariant typeTag valueTag row) where
33+ writeImpl (TaggedVariant variant) =
34+ writeVariantImpl
35+ (reflectSymbol (Proxy ∷ Proxy typeTag))
36+ (reflectSymbol (Proxy ∷ Proxy valueTag))
37+ (Proxy ∷ Proxy rl)
38+ variant
39+
40+class
41+ WriteForeignTaggedVariant (rl ∷ RowList Type) (row ∷ Row Type)
42+ | rl → row where
43+ writeVariantImpl ∷ ∀ g. String → String → g rl → Variant row → Foreign
44+
45+instance
46+ WriteForeignTaggedVariant Nil () where
47+ writeVariantImpl _ _ _ _ =
48+ -- a PureScript-defined variant cannot reach this path, but a JavaScript FFI one could.
49+ unsafeCrashWith "Attempted to write empty Variant"
50+
51+instance
52+ ( IsSymbol name
53+ , WriteForeign ty
54+ , Row.Cons name ty subRow row
55+ , WriteForeignTaggedVariant tail subRow
56+ ) ⇒
57+ WriteForeignTaggedVariant (Cons name ty tail) row where
58+ writeVariantImpl typeTag valueTag _ variant =
59+ on
60+ namep
61+ writeVariant
62+ (writeVariantImpl typeTag valueTag (Proxy ∷ Proxy tail))
63+ variant
64+ where
65+ namep = Proxy ∷ Proxy name
66+ name = reflectSymbol namep
67+ writeVariant value = writeImpl $
68+ Object.fromFoldable
69+ [ valueTag /\ (writeImpl value)
70+ , typeTag /\ (writeImpl name)
71+ ]
72+
73+instance
74+ ( RowToList variants rl
75+ , ReadForeignTaggedVariant typeTag valueTag rl variants
76+ , IsSymbol typeTag
77+ , IsSymbol valueTag
78+ ) ⇒
79+ ReadForeign (TaggedVariant typeTag valueTag variants) where
80+ readImpl o = readVariantImpl (Proxy ∷ Proxy rl) o
81+
82+class
83+ ReadForeignTaggedVariant typeTag valueTag (xs ∷ RowList Type) (row ∷ Row Type)
84+ | xs → row where
85+ readVariantImpl ∷
86+ Proxy xs →
87+ Foreign →
88+ F (TaggedVariant typeTag valueTag row)
89+
90+instance
91+ ReadForeignTaggedVariant typeTag valueTag Nil trash where
92+ readVariantImpl __ _ = fail $ ForeignError
93+ "Unable to match any variant member."
94+
95+instance
96+ ( IsSymbol name
97+ , IsSymbol typeTag
98+ , IsSymbol valueTag
99+ , ReadForeign ty
100+ , Row.Cons name ty trash row
101+ , ReadForeignTaggedVariant typeTag valueTag tail row
102+ ) ⇒
103+ ReadForeignTaggedVariant typeTag valueTag (Cons name ty tail) row where
104+ readVariantImpl _ o = readVariantImpl (Proxy ∷ Proxy tail) o <|> do
105+ type_ ← readProp typeTag o >>= readImpl
106+ if type_ == name then do
107+ value ∷ ty ← readProp valueTag o >>= readImpl
108+ pure $ TaggedVariant (inj namep value)
109+ else
110+ (fail <<< ForeignError $ "Did not match variant tag " <> name)
111+
112+ where
113+ typeTag = reflectSymbol (Proxy ∷ Proxy typeTag)
114+ valueTag = reflectSymbol (Proxy ∷ Proxy valueTag)
115+ namep = Proxy ∷ Proxy name
116+ name = reflectSymbol namep
117+
118+-- Untagged Variant
119+
120+newtype UntaggedVariant ∷ Row Type → Type
121+newtype UntaggedVariant v = UntaggedVariant (Variant v)
122+
123+instance 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)
126+
127+instance
128+ ( RowToList row rl
129+ , WriteForeignUntaggedVariant rl row
130+ ) ⇒
131+ WriteForeign (UntaggedVariant row) where
132+ writeImpl (UntaggedVariant variant) =
133+ writeUntaggedVariantImpl
134+ (Proxy ∷ Proxy rl)
135+ variant
136+
137+class
138+ WriteForeignUntaggedVariant (rl ∷ RowList Type) (row ∷ Row Type)
139+ | rl → row where
140+ writeUntaggedVariantImpl ∷ ∀ g. g rl → Variant row → Foreign
141+
142+instance
143+ WriteForeignUntaggedVariant Nil () where
144+ writeUntaggedVariantImpl _ _ =
145+ -- a PureScript-defined variant cannot reach this path, but a JavaScript FFI one could.
146+ unsafeCrashWith "Attempted to write empty Variant"
147+
148+instance
149+ ( IsSymbol name
150+ , WriteForeign ty
151+ , Row.Cons name ty subRow row
152+ , WriteForeignUntaggedVariant tail subRow
153+ ) ⇒
154+ WriteForeignUntaggedVariant (Cons name ty tail) row where
155+ writeUntaggedVariantImpl _ variant =
156+ on
157+ namep
158+ writeImpl
159+ (writeUntaggedVariantImpl (Proxy ∷ Proxy tail))
160+ variant
161+ where
162+ namep = Proxy ∷ Proxy name
163+
164+instance
165+ ( RowToList variants rl
166+ , ReadForeignUntaggedVariant rl variants
167+ ) ⇒
168+ ReadForeign (UntaggedVariant variants) where
169+ readImpl o = readUntaggedVariantImpl (Proxy ∷ Proxy rl) o
170+
171+class
172+ ReadForeignUntaggedVariant (xs ∷ RowList Type) (row ∷ Row Type)
173+ | xs → row where
174+ readUntaggedVariantImpl ∷
175+ Proxy xs →
176+ Foreign →
177+ F (UntaggedVariant row)
178+
179+instance
180+ ReadForeignUntaggedVariant Nil trash where
181+ readUntaggedVariantImpl _ _ = fail $ ForeignError
182+ "Unable to match any variant member."
183+
184+instance
185+ ( IsSymbol name
186+ , ReadForeign ty
187+ , Row.Cons name ty trash row
188+ , ReadForeignUntaggedVariant tail row
189+ ) ⇒
190+ ReadForeignUntaggedVariant (Cons name ty tail) row where
191+ readUntaggedVariantImpl _ o =
192+ readUntaggedVariantImpl (Proxy ∷ Proxy tail) o <|> ado
193+ v ← readImpl o
194+ in UntaggedVariant (inj namep v)
195+
196+ where
197+ namep = Proxy ∷ Proxy name
test.dhalldeleted−9
@@ -1,9 +0,0 @@
1−let conf = ./spago.dhall
2−
3−in conf
4− // { sources = conf.sources # [ "test/**/*.purs" ]
5− , dependencies =
6− conf.dependencies
7− # [ "assert"
8− ]
9− }
test/BasicsSpec.pursnew file+257
@@ -0,0 +1,257 @@
1+module Test.BasicsSpec where
2+
3+import Prelude
4+
5+import Data.Array.NonEmpty as NEA
6+import Data.Either (Either(..), isLeft)
7+import Data.Foldable (traverse_)
8+import Data.JSDate as JSDate
9+import Data.List as List
10+import Data.List.Lazy as LazyList
11+import Data.Map as Map
12+import Data.Maybe (Maybe(..), fromJust, fromMaybe')
13+import Data.Newtype (class Newtype, un)
14+import Data.Nullable as Nullable
15+import Data.Set as Set
16+import Data.String.NonEmpty (NonEmptyString, nes)
17+import Data.Time.Duration (Days(..), Hours(..), Milliseconds(..), Minutes(..), Seconds(..))
18+import Data.Tuple (Tuple(..))
19+import Data.Tuple.Nested ((/\))
20+import Data.Variant (Variant, inj)
21+import Effect.Class (liftEffect)
22+import Effect.Now (nowDateTime)
23+import Foreign (ForeignError(..))
24+import Foreign.Object as Object
25+import JS.BigInt (BigInt)
26+import JS.BigInt as BigInt
27+import Partial.Unsafe (unsafeCrashWith, unsafePartial)
28+import Test.Spec (Spec, describe, it)
29+import Test.Spec.Assertions (shouldEqual)
30+import Test.Util (roundtrips)
31+import Type.Proxy (Proxy(..))
32+import Yoga.JSON (class ReadForeign, class WriteForeign, readJSON, writeJSON)
33+import Yoga.JSON.Variant (TaggedVariant(..), UntaggedVariant(..))
34+import Yoga.Tree (Tree, mkLeaf, mkTree, showTree)
35+
36+spec ∷ Spec Unit
37+spec = describe "En- and decoding" do
38+
39+ describe "works on primitive types" do
40+ it "roundtrips Number" $ roundtrips 3.1414
41+ it "roundtrips Int" $ roundtrips (-200)
42+ it "roundtrips Char" $ roundtrips 'a'
43+ it "roundtrips String" $ roundtrips "A"
44+
45+ describe "works on containers types" do
46+ it "roundtrips Maybe" do
47+ roundtrips (Just 3)
48+ -- just roundtrips Nothing doesn't work when rendering the JSON
49+ roundtrips { empty: Nothing ∷ Maybe Int }
50+ it "roundtrips Nullable" $ traverse_ roundtrips [ Nullable.notNull 3, Nullable.null ]
51+ it "roundtrips Either" do
52+ roundtrips ((Left 3) ∷ Either Int Int)
53+ roundtrips ((Right 3) ∷ Either String Int)
54+ writeJSON (Right 3 ∷ Either Int Int) `shouldEqual` """{"value":3,"type":"right"}"""
55+ writeJSON (Left true ∷ Either Boolean Int) `shouldEqual` """{"value":true,"type":"left"}"""
56+
57+ it "roundtrips Tuple" do
58+ roundtrips (Tuple 3 4)
59+ roundtrips ("4" /\ 8 /\ Just 4)
60+ it "roundtrips Array" $ traverse_ roundtrips [ [ "A", "B" ], [] ]
61+ it "roundtrips LazyList" $ traverse_ roundtrips (LazyList.fromFoldable [ [ "A", "B" ], [] ])
62+ it "roundtrips List" $ traverse_ roundtrips (List.fromFoldable [ [ "A", "B" ], [] ])
63+ it "roundtrips NonEmptyArray" $ roundtrips (NEA.cons' "A" [ "B" ])
64+ it "roundtrips Object" $ roundtrips (Object.fromHomogeneous { a: 12, b: 54 })
65+ it "roundtrips String Map" $ roundtrips (Map.fromFoldable [ ("A" /\ 8), ("C" /\ 7) ])
66+ it "roundtrips Int Map" $ roundtrips (Map.fromFoldable [ (4 /\ "B"), (8 /\ "D") ])
67+ it "roundtrips Map with String newtype keys"
68+ $ roundtrips (Map.fromFoldable [ (Stringy "A" /\ "B"), (Stringy "C" /\ "D") ])
69+ it "roundtrips Map with Int newtype keys"
70+ $ roundtrips (Map.fromFoldable [ (Inty 4 /\ "B"), (Inty 8 /\ "D") ])
71+ it "roundtrips Map with BigInt newtype keys"
72+ $ roundtrips (Map.fromFoldable [ (BigInty (BigInt.fromInt 5) /\ "B"), (BigInty big /\ "D") ])
73+ it "roundtrips Set String" $ roundtrips (Set.fromFoldable [ "A", "B", "C" ])
74+ it "roundtrips BigInt" do
75+ let
76+ inputStr = """{ "number":1, "big": 18014398509481982, "mediumBig": 1652955871799, "smallBig": 10 }"""
77+ expected = """{"smallBig":"10","number":1,"mediumBig":"1652955871799","big":"18014398509481982"}"""
78+
79+ parsed ∷ _ ({ number ∷ Int, mediumBig ∷ BigInt, big ∷ BigInt, smallBig ∷ BigInt })
80+ parsed = readJSON inputStr
81+ stringified = parsed <#> writeJSON
82+ stringified `shouldEqual` (Right expected)
83+
84+ it "roundtrips BigInt (2)" do
85+ let
86+ smallBig = BigInt.fromInt 10
87+
88+ expected = { big, smallBig }
89+ json = writeJSON expected
90+
91+ parsed ∷ _ ({ big ∷ BigInt, smallBig ∷ BigInt })
92+ parsed = readJSON json
93+ parsed `shouldEqual` (Right expected)
94+
95+ describe "works with JSDate" do
96+ it "roundtrips" do
97+ now ← JSDate.now # liftEffect
98+ roundtrips now
99+ someDate ← JSDate.parse "2022-01-01:00:00:00Z" # liftEffect
100+ let result = writeJSON someDate
101+ let expected = show "2022-01-01T00:00:00.000Z"
102+ result `shouldEqual` expected
103+
104+ describe "works with DateTime" do
105+ it "roundtrips" do
106+ now ← nowDateTime # liftEffect
107+ roundtrips now
108+ someDate ← JSDate.parse "2022-01-01:00:00:00Z" <#> (JSDate.toDateTime >>> fromMaybe' \_ → unsafeCrashWith "nope") # liftEffect
109+ let result = writeJSON someDate
110+ let expected = show "2022-01-01T00:00:00.000Z"
111+ result `shouldEqual` expected
112+
113+ describe "works with Durations" do
114+ it "roundtrips" do
115+ let millis = Milliseconds 16.67
116+ roundtrips millis
117+ writeJSON millis `shouldEqual` "16.67"
118+
119+ let seconds = Seconds 60.0
120+ roundtrips seconds
121+ writeJSON seconds `shouldEqual` "60"
122+
123+ let minutes = Minutes 10.0
124+ roundtrips minutes
125+ writeJSON minutes `shouldEqual` "10"
126+
127+ let hours = Hours 24.0
128+ roundtrips hours
129+ writeJSON hours `shouldEqual` "24"
130+
131+ let days = Days 365.0
132+ roundtrips days
133+ writeJSON days `shouldEqual` "365"
134+
135+ describe "works on record types" do
136+ it "roundtrips" do
137+ roundtrips { a: 12, b: "54" }
138+ roundtrips { a: 12, b: { c: "54" } }
139+ roundtrips {}
140+
141+ describe "works on newtypes" do
142+ it "roundtrips" do
143+ roundtrips (Stringy "A string is here")
144+
145+ describe "works on variant types" do
146+ it "roundtrips" do
147+ let input = inj (Proxy ∷ _ "a") {} ∷ Variant (a ∷ {}, b ∷ {})
148+ let asJSON = writeJSON input
149+ readJSON asJSON `shouldEqual` Right input
150+
151+ let input2 = inj (Proxy ∷ _ "b") {} ∷ Variant (a ∷ {}, b ∷ {})
152+ let asJSON2 = writeJSON input2
153+ readJSON asJSON2 `shouldEqual` Right input2
154+
155+ roundtrips (inj (Proxy ∷ _ "erwin") "e" ∷ Variant (erwin ∷ String))
156+ roundtrips (inj (Proxy ∷ _ "jackie") 7 ∷ Variant ExampleVariant)
157+
158+ it "does not select an absent optional branch" do
159+ let expected = inj (Proxy ∷ _ "a") 42 ∷ Variant (a ∷ Int, b ∷ Maybe Int)
160+ readJSON """{"a":42}""" `shouldEqual` Right expected
161+
162+ it "accepts an explicitly null optional branch" do
163+ let expected = inj (Proxy ∷ _ "b") Nothing ∷ Variant (a ∷ Int, b ∷ Maybe Int)
164+ readJSON """{"b":null}""" `shouldEqual` Right expected
165+
166+ it "rejects objects without a matching variant key" do
167+ traverse_
168+ (\json → isLeft (readJSON json ∷ _ (Variant (a ∷ {}, b ∷ {}))) `shouldEqual` true)
169+ [ "{}", """{"unknown":{}}""" ]
170+
171+ describe "works on tagged variant types" do
172+ it "roundtrips" do
173+ roundtrips (TaggedVariant (erwin "e") ∷ TaggedVariant "super" "hans" (Erwin ()))
174+ let bareVariant = erwin "e"
175+ let res = writeJSON (TaggedVariant bareVariant ∷ TaggedVariant "type" "value" ExampleVariant)
176+ let expected = """{"value":"e","type":"erwin"}"""
177+ res `shouldEqual` expected
178+ let
179+ parsed ∷ _ (TaggedVariant "type" "value" ExampleVariant)
180+ parsed = readJSON expected
181+ (un TaggedVariant <$> parsed) `shouldEqual` Right bareVariant
182+
183+ describe "works on untagged variant types" do
184+ it "roundtrips" do
185+ roundtrips (UntaggedVariant (erwin "e") ∷ UntaggedVariant (Erwin ()))
186+ let bareVariant = erwin "e"
187+ let res = writeJSON (UntaggedVariant bareVariant ∷ UntaggedVariant ExampleVariant)
188+ let expected = "\"e\""
189+ res `shouldEqual` expected
190+ let
191+ parsed ∷ _ (UntaggedVariant ExampleVariant)
192+ parsed = readJSON expected
193+ (un UntaggedVariant <$> parsed) `shouldEqual` Right bareVariant
194+
195+ describe "works on non empty strings" do
196+ it "roundtrips NonEmptyString" do
197+ roundtrips (nes (Proxy ∷ Proxy "Non-Empty"))
198+ it "fails to decode empty strings" do
199+ let (result ∷ (Either _ NonEmptyString)) = readJSON (show "")
200+ result `shouldEqual` Left (pure $ ForeignError "String must not be empty")
201+
202+ describe "works on trees" do
203+ it "roundtrips" do
204+ let t = mkTree "a" [ mkTree "b" [ mkLeaf "c", mkLeaf "d" ] ]
205+ roundtrips (ShowTree t)
206+
207+ it "encodes as expected" do
208+ let t = mkTree "a" [ mkTree "b" [ mkLeaf "c", mkLeaf "d" ] ]
209+ writeJSON (ShowTree t) `shouldEqual`
210+ """{"value":"a","children":[{"value":"b","children":[{"value":"c"},{"value":"d"}]}]}"""
211+
212+newtype ShowTree = ShowTree (Tree String)
213+
214+instance Show ShowTree where
215+ show (ShowTree t) = showTree t
216+
217+derive newtype instance WriteForeign ShowTree
218+derive newtype instance ReadForeign ShowTree
219+derive newtype instance Eq ShowTree
220+
221+type ExampleVariant = ("erwin" ∷ String, "jackie" ∷ Int)
222+type ExampleTaggedVariant t v = TaggedVariant t v ExampleVariant
223+
224+erwin ∷ ∀ a r. a → Variant (erwin ∷ a | r)
225+erwin = inj (Proxy ∷ Proxy "erwin")
226+
227+type Erwin r = (erwin ∷ String | r)
228+
229+newtype Stringy = Stringy String
230+
231+derive instance Newtype Stringy _
232+derive newtype instance Show Stringy
233+derive newtype instance Eq Stringy
234+derive newtype instance Ord Stringy
235+derive newtype instance WriteForeign Stringy
236+derive newtype instance ReadForeign Stringy
237+
238+newtype Inty = Inty Int
239+
240+derive instance Newtype Inty _
241+derive newtype instance Show Inty
242+derive newtype instance Eq Inty
243+derive newtype instance Ord Inty
244+derive newtype instance WriteForeign Inty
245+derive newtype instance ReadForeign Inty
246+
247+newtype BigInty = BigInty BigInt
248+
249+derive instance Newtype BigInty _
250+derive newtype instance Show BigInty
251+derive newtype instance Eq BigInty
252+derive newtype instance Ord BigInty
253+derive newtype instance WriteForeign BigInty
254+derive newtype instance ReadForeign BigInty
255+
256+big ∷ BigInt
257+big = unsafePartial $ fromJust $ BigInt.fromString "18014398509481982"
test/EnumSumGeneric.pursdeleted−66
@@ -1,66 +0,0 @@
1−module Test.EnumSumGeneric where
2−
3−import Prelude
4−
5−import Control.Alt ((<|>))
6−import Control.Monad.Except (throwError)
7−import Data.Either (Either, isRight)
8−import Data.Generic.Rep (class Generic, Constructor(..), NoArguments(..), Sum(..), to)
9−import Data.Show.Generic (genericShow)
10−import Effect (Effect)
11−import Foreign (Foreign)
12−import Foreign as Foreign
13−import JSON as JSON
14−import Test.Assert (assert)
15−import Type.Prelude (class IsSymbol, Proxy(..), reflectSymbol)
16−
17−enumReadForeign :: forall a rep
18− . Generic a rep
19− => EnumReadForeign rep
20− => Foreign
21− -> Foreign.F a
22−enumReadForeign f =
23− to <$> enumReadForeignImpl f
24−
25−-- type class for "enums", or nullary sum types
26−class EnumReadForeign rep where
27− enumReadForeignImpl :: Foreign -> Foreign.F rep
28−
29−instance
30− ( EnumReadForeign a
31− , EnumReadForeign b
32− ) => EnumReadForeign (Sum a b) where
33− enumReadForeignImpl f
34− = Inl <$> enumReadForeignImpl f
35− <|> Inr <$> enumReadForeignImpl f
36−
37−instance
38− ( IsSymbol name
39− ) => EnumReadForeign (Constructor name NoArguments) where
40− enumReadForeignImpl f = do
41− s <- JSON.readImpl f
42− if s == name
43− then pure $ Constructor NoArguments
44− else throwError <<< pure <<< Foreign.ForeignError $
45− "Enum string " <> s <> " did not match expected string " <> name
46− where
47− name = reflectSymbol (Proxy :: Proxy name)
48−
49−data Fruit
50− = Abogado
51− | Boat
52− | Candy
53−derive instance Generic Fruit _
54−instance JSON.ReadForeign Fruit where
55− readImpl = enumReadForeign
56−instance Show Fruit where
57− show = genericShow
58−
59−readFruit :: String -> Either Foreign.MultipleErrors Fruit
60−readFruit = JSON.readJSON
61−
62−main :: Effect Unit
63−main = do
64− assert <<< isRight $ readFruit "\"Abogado\""
65− assert <<< isRight $ readFruit "\"Boat\""
66− assert <<< isRight $ readFruit "\"Candy\""
test/ErrorsSpec.pursnew file+84
@@ -0,0 +1,84 @@
1+module Test.ErrorsSpec where
2+
3+import Prelude
4+
5+import Data.Array as Array
6+import Data.Bifunctor (lmap)
7+import Data.Either (Either(..), blush)
8+import Data.Maybe (Maybe(..))
9+import Foreign (ForeignError(..))
10+import Foreign.Object (Object)
11+import Test.Spec (Spec, describe, it)
12+import Test.Spec.Assertions (shouldEqual)
13+import Type.Proxy (Proxy(..))
14+import Yoga.JSON (class ReadForeign, E, readJSON)
15+import Yoga.JSON as JSON
16+import Yoga.JSON.Error (renderHumanError, toJSONPath)
17+
18+spec ∷ Spec Unit
19+spec = describe "Errors" do
20+ describe "are returned at once" do
21+ it "returns multiple errors for object" do
22+ let
23+ res ∷ E (Object Int)
24+ res = JSON.readJSON """{ "something": "no", "else": true }"""
25+ e1 = ErrorAtProperty "something" (TypeMismatch "Int" "String")
26+ e2 = ErrorAtProperty "else" (TypeMismatch "Int" "Boolean")
27+ res `shouldEqual` (Left (pure e1 <> pure e2))
28+
29+ it "returns multiple errors for record" do
30+ let
31+ res ∷ E { a ∷ Int, b ∷ String }
32+ res = JSON.readJSON """{ "b": true }"""
33+ e1 = ErrorAtProperty "a" (TypeMismatch "Int" "Undefined")
34+ e2 = ErrorAtProperty "b" (TypeMismatch "String" "Boolean")
35+ res `shouldEqual` (Left (pure e1 <> pure e2))
36+
37+ it "returns multiple errors for array" do
38+ let
39+ res ∷ E (Array Int)
40+ res = JSON.readJSON """[1,"a",2,true]"""
41+ e1 = ErrorAtIndex 1 (TypeMismatch "Int" "String")
42+ e2 = ErrorAtIndex 3 (TypeMismatch "Int" "Boolean")
43+ res `shouldEqual` (Left (pure e1 <> pure e2))
44+
45+ describe "produces human-friendly errors" do
46+ it "For some object" do
47+ let
48+ res ∷ E (Object Int)
49+ res = JSON.readJSON """{ "something": "no", "else": true }"""
50+ e1 = "Must provide a value of type 'Int' instead of 'String' at $.something"
51+ e2 = "Must provide a value of type 'Int' instead of 'Boolean' at $.else"
52+ (res # lmap (map renderHumanError >>> Array.fromFoldable))
53+ `shouldEqual` (Left [ e1, e2 ])
54+
55+ it "For deeply nested keys" do
56+ let
57+ res ∷ E { a ∷ { b ∷ { c ∷ { d ∷ String } } } }
58+ res = JSON.readJSON """{ "a": { "b": { "c": { }}}}"""
59+ e = "Must provide a value of type 'String' at $.a.b.c.d"
60+ (res # lmap (map renderHumanError >>> Array.fromFoldable))
61+ `shouldEqual` (Left [ e ])
62+
63+ describe "have the correct JSON path" do
64+ it "empty json" do
65+ (getErrorPath (Proxy ∷ _ {}) "") `shouldEqual` Just [ "$" ]
66+ it "nested json json" do
67+ let
68+ xo =
69+ """
70+ { "deeply": { "nested": { "array":
71+ [ { "of": { "values": "hello" } }
72+ , 8
73+ ]
74+ } } }"""
75+ ( getErrorPath (Proxy ∷ _ { deeply ∷ { nested ∷ { array ∷ Array { of ∷ { values ∷ String } } } } })
76+ xo
77+ ) `shouldEqual`
78+ -- [FIXME] I'm not sure about this
79+ Just [ "$.deeply.nested.array[1].of" ]
80+
81+getErrorPath ∷ ∀ a. ReadForeign a ⇒ Proxy a → String → Maybe (Array String)
82+getErrorPath _ x = do
83+ let e = (readJSON x ∷ _ a) # blush
84+ (e <#> map toJSONPath <#> Array.fromFoldable)
test/Generic.pursdeleted−69
@@ -1,69 +0,0 @@
1−module Test.Generic where
2−
3−import Prelude
4−
5−import Control.Alt ((<|>))
6−import Data.Either (Either, isRight)
7−import Data.Generic.Rep as GR
8−import Data.Show.Generic (genericShow)
9−import Effect (Effect)
10−import Foreign (Foreign)
11−import Foreign as Foreign
12−import JSON as JSON
13−import Test.Assert (assert)
14−
15−data IntOrBoolean
16− = Int Int
17− | Boolean Boolean
18−instance readForeign :: JSON.ReadForeign IntOrBoolean where
19− readImpl f
20− = Int <$> Foreign.readInt f
21− <|> Boolean <$> Foreign.readBoolean f
22−instance showIntOrBoolean :: Show IntOrBoolean where
23− show (Int i) = "(Int " <> show i <> ")"
24− show (Boolean i) = "(Boolean " <> show i <> ")"
25−
26−decodeToIntOrBoolean :: String -> Either Foreign.MultipleErrors IntOrBoolean
27−decodeToIntOrBoolean = JSON.readJSON
28−
29−data IntOrBoolean2
30− = Int2 Int
31− | Boolean2 Boolean
32−
33−derive instance genericIntOrBoolean2 :: GR.Generic IntOrBoolean2 _
34−
35−instance showIntOrBoolean2 :: Show IntOrBoolean2 where
36− show = genericShow
37−instance readForeignIntOrBoolean2 :: JSON.ReadForeign IntOrBoolean2 where
38− readImpl f = GR.to <$> untaggedSumRep f
39−
40−class UntaggedSumRep rep where
41− untaggedSumRep :: Foreign -> Foreign.F rep
42−
43−instance untaggedSumRepSum ::
44− ( UntaggedSumRep a
45− , UntaggedSumRep b
46− ) => UntaggedSumRep (GR.Sum a b) where
47− untaggedSumRep f
48− = GR.Inl <$> untaggedSumRep f
49− <|> GR.Inr <$> untaggedSumRep f
50−
51−instance untaggedSumRepConstructor ::
52− ( UntaggedSumRep a
53− ) => UntaggedSumRep (GR.Constructor name a) where
54− untaggedSumRep f = GR.Constructor <$> untaggedSumRep f
55−
56−instance untaggedSumRepArgument ::
57− ( JSON.ReadForeign a
58− ) => UntaggedSumRep (GR.Argument a) where
59− untaggedSumRep f = GR.Argument <$> JSON.readImpl f
60−
61−decodeToIntOrBoolean2 :: String -> Either Foreign.MultipleErrors IntOrBoolean2
62−decodeToIntOrBoolean2 = JSON.readJSON
63−
64−main :: Effect Unit
65−main = do
66− assert <<< isRight $ decodeToIntOrBoolean "1" -- (Right (Int 1))
67− assert <<< isRight $ decodeToIntOrBoolean "true" -- (Right (Boolean true))
68− assert <<< isRight $ decodeToIntOrBoolean2 "1" -- (Right (Int2 1))
69− assert <<< isRight $ decodeToIntOrBoolean2 "true" -- (Right (Boolean2 true))
test/GenericsSpec.pursnew file+149
@@ -0,0 +1,149 @@
1+module Test.GenericsSpec where
2+
3+import Prelude
4+
5+import Data.Generic.Rep (class Generic)
6+import Data.Show.Generic (genericShow)
7+import Data.String.Extra (snakeCase)
8+import Test.Spec (Spec, describe, it)
9+import Test.Spec.Assertions (shouldEqual)
10+import Test.Util (roundtrips)
11+import Yoga.JSON (class ReadForeign, class WriteForeign, writeJSON)
12+import Yoga.JSON.Generics (defaultOptions, genericReadForeignEnum, genericReadForeignTaggedSum, genericReadForeignUntaggedProduct, genericReadForeignUntaggedSum, genericWriteForeignEnum, genericWriteForeignTaggedSum, genericWriteForeignUntaggedProduct, genericWriteForeignUntaggedSum)
13+import Yoga.JSON.Generics as GenericTaggedSum
14+import Yoga.JSON.Generics.EnumSumRep as Enum
15+
16+spec ∷ Spec Unit
17+spec = describe "Generics" do
18+
19+ describe "Enum" do
20+ describe "MyEnum = Enum1 | Enum2 | Enum3" do
21+ it "roundtrips" do
22+ roundtrips (Enum1)
23+ roundtrips (Enum3)
24+
25+ describe "works with custom constructor names" do
26+ it "roundtrips" do
27+ roundtrips (SomeOtherEnum2)
28+ writeJSON (SomeThirdEnum3) `shouldEqual` "\"some_third_enum_3\""
29+
30+ describe "Untagged" do
31+
32+ describe "IntOrString = AnInt Int | AString String" do
33+ it "roundtrips" do
34+ roundtrips (AnInt 1)
35+ roundtrips (AString "Abc")
36+ it "serialises without tags" do
37+ writeJSON (AnInt 1) `shouldEqual` "1"
38+ writeJSON (AString "Abc") `shouldEqual` "\"Abc\""
39+
40+ describe "data DoubleTrouble = IntAndString Int String" do
41+ it "roundtrips" do
42+ roundtrips (IntAndString 1 "Freddy")
43+ it "serialises without tags" do
44+ writeJSON (IntAndString 1 "Freddy") `shouldEqual` "[1,\"Freddy\"]"
45+
46+ describe "Tagged" do
47+
48+ describe "IntOrStringTagged = ATaggedInt Int | ATaggedString String" do
49+ it "roundtrips" do
50+ roundtrips (ATaggedInt 1)
51+ roundtrips (ATaggedString "HOHOHOHO")
52+
53+ it "serialises with tags" do
54+ writeJSON (ATaggedInt 1) `shouldEqual` """{"type":"ATaggedInt","value":1}"""
55+ writeJSON (ATaggedString "Abc") `shouldEqual` """{"type":"ATaggedString","value":"Abc"}"""
56+
57+ describe "data HalfEnum = NotEnum Int | IsEnum" do
58+ it "roundtrips" do
59+ roundtrips (NotEnum 1)
60+ roundtrips (IsEnum)
61+
62+ it "serialises with tags" do
63+ writeJSON (NotEnum 1) `shouldEqual` """{"kind":"not_enum","data":1}"""
64+ writeJSON (IsEnum) `shouldEqual` """{"kind":"is_enum"}"""
65+
66+data HalfEnum = NotEnum Int | IsEnum
67+
68+derive instance Generic HalfEnum _
69+derive instance Eq HalfEnum
70+instance Show HalfEnum where
71+ show = genericShow
72+
73+halfEnumOptions ∷ GenericTaggedSum.Options
74+halfEnumOptions = { typeTag: "kind", valueTag: "data", toConstructorName: snakeCase }
75+
76+instance ReadForeign HalfEnum where
77+ readImpl = genericReadForeignTaggedSum halfEnumOptions
78+
79+instance WriteForeign HalfEnum where
80+ writeImpl = genericWriteForeignTaggedSum halfEnumOptions
81+
82+data MyEnum = Enum1 | Enum2 | Enum3
83+
84+derive instance Generic MyEnum _
85+derive instance Eq MyEnum
86+instance Show MyEnum where
87+ show = genericShow
88+
89+instance ReadForeign MyEnum
90+ where
91+ readImpl = genericReadForeignEnum Enum.defaultOptions
92+
93+instance WriteForeign MyEnum
94+ where
95+ writeImpl = genericWriteForeignEnum Enum.defaultOptions
96+
97+data MyEnum2 = SomeEnum2 | SomeOtherEnum2 | SomeThirdEnum3
98+
99+derive instance Generic MyEnum2 _
100+derive instance Eq MyEnum2
101+instance Show MyEnum2 where
102+ show = genericShow
103+
104+instance ReadForeign MyEnum2
105+ where
106+ readImpl = genericReadForeignEnum { toConstructorName: snakeCase }
107+
108+instance WriteForeign MyEnum2
109+ where
110+ writeImpl = genericWriteForeignEnum { toConstructorName: snakeCase }
111+
112+data IntOrString = AnInt Int | AString String
113+
114+derive instance Generic IntOrString _
115+derive instance Eq IntOrString
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
124+
125+data DoubleTrouble = IntAndString Int String
126+
127+derive instance Generic DoubleTrouble _
128+derive instance Eq DoubleTrouble
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
137+
138+data IntOrStringTagged = ATaggedInt Int | ATaggedString String
139+
140+derive instance Generic IntOrStringTagged _
141+derive instance Eq IntOrStringTagged
142+instance Show IntOrStringTagged where
143+ show = genericShow
144+
145+instance ReadForeign IntOrStringTagged where
146+ readImpl = genericReadForeignTaggedSum defaultOptions
147+
148+instance WriteForeign IntOrStringTagged where
149+ writeImpl = genericWriteForeignTaggedSum defaultOptions
test/Inferred.pursdeleted−52
@@ -1,52 +0,0 @@
1−module Test.Inferred where
2−
3−import Prelude
4−
5−import Control.Alt ((<|>))
6−import Control.Monad.Except (runExcept)
7−import Data.Either (Either(..), isRight)
8−import Effect (Effect)
9−import Foreign (Foreign)
10−import Foreign as Foreign
11−import Record as Record
12−import JSON as JSON
13−import Test.Assert (assert)
14−import Type.Prelude (Proxy(..))
15−
16−type RecordWithEither =
17− { apple :: Int
18− , banana :: Either Int String
19− }
20−
21−readEitherImpl
22− :: forall a b
23− . JSON.ReadForeign a
24− => JSON.ReadForeign b
25− => Foreign
26− -> Foreign.F (Either a b)
27−readEitherImpl f
28− = Left <$> JSON.readImpl f
29− <|> Right <$> JSON.readImpl f
30−
31−readRecordWithEitherJSON :: String -> Either Foreign.MultipleErrors RecordWithEither
32−readRecordWithEitherJSON s = runExcept do
33− inter <- JSON.readJSON' s
34− banana <- readEitherImpl inter.banana
35− pure $ inter { banana = banana }
36−
37−type RecordMisnamedField =
38− { cherry :: Int
39− }
40−
41−readRecordMisnamedField :: String -> Either Foreign.MultipleErrors RecordMisnamedField
42−readRecordMisnamedField s = do
43− inter <- JSON.readJSON s
44− pure $ Record.rename grapeP cherryP inter
45− where
46− grapeP = Proxy :: Proxy "grape"
47− cherryP = Proxy :: Proxy "cherry"
48−
49−main :: Effect Unit
50−main = do
51− assert <<< isRight $ readRecordWithEitherJSON """{"apple": 1, "banana": 1}"""
52− assert <<< isRight $ readRecordWithEitherJSON """{"apple": 1, "banana": "yellow"}"""
test/Main.purs+10−151
@@ -2,155 +2,14 @@ module Test.Main where
22
33import Prelude
44
5−import Control.Monad.Except (runExcept)
6−import Data.Bifunctor (lmap)
7−import Data.Either (Either(..), either, isRight)
8−import Data.List (List(..), (:))
9−import Data.List.NonEmpty (NonEmptyList(..))
10−import Data.Maybe (Maybe)
11−import Data.NonEmpty (NonEmpty(..))
12−import Data.Nullable (Nullable)
13−import Data.Variant (Variant)
145import Effect (Effect)
15−import Effect.Exception (throw)
16−import Foreign (Foreign, ForeignError(..), MultipleErrors)
17−import Foreign.Object (Object)
18−import JSON (class ReadForeign, class WriteForeign, parseJSON, readJSON, writeJSON)
19−import Test.Assert (assertEqual)
20−import Test.EnumSumGeneric as Test.EnumSumGeneric
21−import Test.Generic as Test.Generic
22−import Test.Inferred as Test.Inferred
23−import Test.Quickstart as Test.Quickstart
24−import Type.Proxy (Proxy(..))
25−
26−type E a = Either MultipleErrors a
27−
28−type MyTest =
29− { a :: Int
30− , b :: String
31− , c :: Boolean
32− , d :: Array String
33− }
34−
35−type MyTestNull =
36− { a :: Int
37− , b :: String
38− , c :: Boolean
39− , d :: Array String
40− , e :: Maybe (Array String)
41− }
42−
43−type MyTestStrMap =
44− { a :: Int
45− , b :: Object Int
46− }
47−
48−type MyTestMaybe =
49− { a :: Maybe String
50− }
51−
52−type MyTestManyMaybe =
53− { a :: Maybe String
54− , aNull :: Maybe String
55− , b :: Maybe Int
56− , bNull :: Maybe Int
57− , c :: Maybe Boolean
58− , cNull :: Maybe Boolean
59− , d :: Maybe Number
60− , dNull :: Maybe Number
61− , e :: Maybe (Array (Maybe String))
62− , eNull :: Maybe (Array (Maybe String))
63− }
64−
65−type MyTestNullable =
66− { a :: Nullable String
67− , b :: Nullable String
68− }
69−
70−type MyTestVariant = Variant
71− ( a :: String
72− , b :: Int
73− )
74−
75−roundtrips :: forall a. ReadForeign a => WriteForeign a => Proxy a -> String -> Effect Unit
76−roundtrips _ enc0 = do
77− let parseJSON' = lmap show <<< runExcept <<< parseJSON
78− dec0 :: E a
79− dec0 = readJSON enc0
80− enc1 = either (const "bad1") writeJSON dec0
81− json0 :: Either String Foreign
82− json0 = parseJSON' enc0
83− json1 :: Either String Foreign
84− json1 = parseJSON' enc1
85− dec1 :: E a
86− dec1 = readJSON enc1
87− enc2 = either (const "bad2") writeJSON dec1
88− when (enc1 /= enc2) $ throw enc0
89−
90−shouldEqual :: forall a . Eq a => Show a => a -> a -> Effect Unit
91−shouldEqual a b =
92− assertEqual { actual: a, expected: b}
93−
94−main :: Effect Unit
95−main = do
96− shouldEqual 1 1
97−
98− -- "fails with invalid JSON"
99− let r1 = readJSON """{ "c": 1, "d": 2}"""
100− r1 `shouldEqual`
101− (Left (NonEmptyList (NonEmpty (ErrorAtProperty "a" (TypeMismatch "Int" "Undefined")) ((ErrorAtProperty "b" (TypeMismatch "String" "Undefined")) : (ErrorAtProperty "c" (TypeMismatch "Boolean" "Number")) : (ErrorAtProperty "d" (TypeMismatch "array" "Number")) : Nil))))
102− isRight (r1 :: E MyTest) `shouldEqual` false
103−
104− -- "works with missing Maybe fields by setting them to Nothing"
105− let r2 = readJSON "{}"
106− (writeJSON <$> (r2 :: E MyTestMaybe)) `shouldEqual` (Right """{}""")
107−
108− -- "fails with undefined for null with correct error message"
109− let r3 = readJSON """
110− { "a": "asdf" }
111− """
112− r3 `shouldEqual`
113− (Left (NonEmptyList (NonEmpty (ErrorAtProperty "b" (TypeMismatch "Nullable String" "Undefined")) Nil)))
114− (isRight (r3 :: E MyTestNullable)) `shouldEqual` false
115−
116− -- roundtrips
117− -- "works with proper JSON"
118− roundtrips (Proxy :: Proxy MyTest) """
119− { "a": 1, "b": "asdf", "c": true, "d": ["A", "B"]}
120− """
121−
122− -- "works with JSON lacking Maybe field"
123− roundtrips (Proxy :: Proxy MyTestNull) """
124− { "a": 1, "b": "asdf", "c": true, "d": ["A", "B"]}
125− """
126−
127− -- "works with JSON containing Maybe field"
128− roundtrips (Proxy :: Proxy MyTestNull) """
129− { "a": 1, "b": "asdf", "c": true, "d": ["A", "B"], "e": ["C", "D"]}
130− """
131−
132− -- -- "works with JSON containing Object field"
133− roundtrips (Proxy :: Proxy MyTestStrMap) """
134− { "a": 1, "b": {"asdf": 1, "c": 2} }
135− """
136−
137− -- "works with Maybe field and existing value"
138− roundtrips (Proxy :: Proxy MyTestMaybe) """
139− { "a": "foo" }
140− """
141−
142− -- "works with Nullable"
143− roundtrips (Proxy :: Proxy MyTestNullable) """
144− { "a": null, "b": "a" }
145− """
146−
147− -- "works with Variant"
148− roundtrips (Proxy :: Proxy MyTestVariant) """
149− { "type": "b", "value": 123 }
150− """
151−
152− -- run examples
153− Test.Generic.main
154− Test.EnumSumGeneric.main
155− Test.Inferred.main
156− Test.Quickstart.main
6+import Effect.Aff (launchAff_)
7+import Effect.Class (liftEffect)
8+import Test.Spec.Discovery (discover)
9+import Test.Spec.Reporter (consoleReporter)
10+import Test.Spec.Runner.Node (runSpecAndExitProcess)
11+
12+main ∷ Effect Unit
13+main = launchAff_ $
14+ discover """\..*Spec"""
15+ >>= runSpecAndExitProcess [ consoleReporter ] >>> liftEffect
test/QuickStart.pursdeleted−130
@@ -1,130 +0,0 @@
1−module Test.Quickstart where
2−
3−import Prelude
4−
5−import Data.Array as Array
6−import Data.Either (Either(..))
7−import Data.Maybe (Maybe(..))
8−import Data.Nullable (Nullable, toNullable)
9−import Effect (Effect)
10−import Effect.Class.Console (log)
11−import Foreign (ForeignError(..))
12−import JSON as JSON
13−import Test.Assert (assertEqual)
14−
15−type MyRecordAlias =
16− { apple :: String
17− , banana :: Array Int
18− }
19−
20−testJSON1 :: String
21−testJSON1 = """
22−{ "apple": "Hello"
23−, "banana": [ 1, 2, 3 ]
24−}
25−"""
26−
27−testJSON2 :: String
28−testJSON2 = """
29−{ "apple": false
30−, "banana": [ 1, 2, 3 ]
31−}
32−"""
33−
34−type WithMaybe =
35− { cherry :: Maybe Boolean
36− }
37−
38−testJSON3 :: String
39−testJSON3 = """
40−{ "cherry": true
41−}
42−"""
43−
44−testJSON4 :: String
45−testJSON4 = """
46−{}
47−"""
48−
49−type WithNullable =
50− { cherry :: Nullable Boolean
51− }
52−
53−newtype FancyInt = FancyInt Int
54−derive newtype instance eqFancyInt :: Eq FancyInt
55−derive newtype instance showFancyInt :: Show FancyInt
56−derive newtype instance readForeignFancyInt :: JSON.ReadForeign FancyInt
57−derive newtype instance writeForeignFancyInt :: JSON.WriteForeign FancyInt
58−
59−main :: Effect Unit
60−main = do
61− case JSON.readJSON testJSON1 of
62− Right (r :: MyRecordAlias) -> do
63− assertEqual { expected: r.apple, actual: "Hello"}
64− assertEqual { expected: r.banana, actual: [ 1, 2, 3 ] }
65− Left e -> do
66− assertEqual { expected: "failed", actual: show e }
67−
68− case JSON.readJSON testJSON2 of
69− Right (r :: MyRecordAlias) -> do
70− assertEqual { expected: "failed", actual: show r }
71− Left e -> do
72− let errors = Array.fromFoldable e
73− assertEqual { expected: [ErrorAtProperty "apple" (TypeMismatch "String" "Boolean")], actual: errors }
74−
75− let
76− myValue =
77− { apple: "Hi"
78− , banana: [ 1, 2, 3 ]
79− } :: MyRecordAlias
80−
81− log (JSON.writeJSON myValue) -- {"banana":[1,2,3],"apple":"Hi"}
82−
83− case JSON.readJSON testJSON3 of
84− Right (r :: WithMaybe) -> do
85− assertEqual { expected: Just true, actual: r.cherry }
86− Left e -> do
87− assertEqual { expected: "failed", actual: show e }
88−
89− case JSON.readJSON testJSON4 of
90− Right (r :: WithMaybe) -> do
91− assertEqual { expected: Nothing, actual: r.cherry }
92− Left e -> do
93− assertEqual { expected: "failed", actual: show e }
94−
95− let
96− withJust =
97− { cherry: Just true
98− } :: WithMaybe
99− withNothing =
100− { cherry: Nothing
101− } :: WithMaybe
102−
103− log (JSON.writeJSON withJust) -- {"cherry":true}
104− log (JSON.writeJSON withNothing) -- {}
105−
106− case JSON.readJSON testJSON3 of
107− Right (r :: WithNullable) -> do
108− assertEqual { expected: toNullable (Just true), actual: r.cherry }
109− Left e -> do
110− assertEqual { expected: "failed", actual: show e }
111−
112− case JSON.readJSON testJSON4 of
113− Right (r :: WithNullable) -> do
114− assertEqual { expected: "failed", actual: show r }
115− Left e -> do
116− let errors = Array.fromFoldable e
117− assertEqual { expected: [ErrorAtProperty "cherry" (TypeMismatch "Nullable Boolean" "Undefined")], actual: errors }
118−
119− let
120− withNullable =
121− { cherry: toNullable Nothing
122− } :: WithNullable
123− log (JSON.writeJSON withNullable) -- {"cherry":null}
124−
125− case JSON.readJSON "1" of
126− Right fancyInt@(FancyInt i) -> do
127− assertEqual { expected: FancyInt 1, actual: fancyInt }
128− assertEqual { expected: 1, actual: i }
129− Left e -> do
130− assertEqual { expected: "failed", actual: show e }
test/Util.purs+20−29
@@ -2,35 +2,26 @@ module Test.Util where
22
33import Prelude
44
5−import Prim.Row as Row
6−import Prim.RowList (class RowToList, Cons, Nil, RowList)
7−import Record (get)
8−import Type.Prelude (class IsSymbol, Proxy(..))
5+import Data.Either (Either(..))
6+import Data.Semigroup.Foldable (intercalateMap)
7+import Effect.Aff (Aff)
8+import Foreign (Foreign)
9+import Test.Spec.Assertions (fail)
10+import Type.Proxy (Proxy(..))
11+import Yoga.JSON (class ReadForeign, class WriteForeign, read, readJSON, write, writeJSON)
12+import Yoga.JSON.Error (renderHumanError, toJSONPath)
913
10−-- | Check two records of the same type for equality.
11−equal
12− :: forall r rs
13− . RowToList r rs
14− => EqualFields rs r
15− => Record r
16− -> Record r
17− -> Boolean
18−equal a b = equalFields (Proxy :: Proxy rs) a b
14+roundtrips ∷ ∀ a. Show a ⇒ Eq a ⇒ ReadForeign a ⇒ WriteForeign a ⇒ a → Aff Unit
15+roundtrips x = do
16+ x # write # shouldRead (Proxy ∷ _ a)
17+ x # writeJSON # shouldReadJSON (Proxy ∷ _ a)
1918
20−class EqualFields (rs :: RowList Type) (row :: Row Type) | rs -> row where
21− equalFields :: Proxy rs -> Record row -> Record row -> Boolean
19+shouldRead ∷ ∀ a. ReadForeign a ⇒ Proxy a → Foreign → Aff Unit
20+shouldRead _ = read >>> case _ of
21+ Left e → fail (intercalateMap "\n" renderHumanError e <> "\n" <> intercalateMap "\n" toJSONPath e)
22+ Right (_ ∷ a) → pure unit
2223
23−instance equalFieldsCons
24− ::
25− ( IsSymbol name
26− , Eq ty
27− , Row.Cons name ty tailRow row
28− , EqualFields tail row
29− ) => EqualFields (Cons name ty tail) row where
30− equalFields _ a b = get' a == get' b && rest
31− where
32− get' = get (Proxy :: Proxy name)
33− rest = equalFields (Proxy :: Proxy tail) a b
34−
35−instance equalFieldsNil :: EqualFields Nil row where
36− equalFields _ _ _ = true
24+shouldReadJSON ∷ ∀ a. ReadForeign a ⇒ Proxy a → String → Aff Unit
25+shouldReadJSON _ = readJSON >>> case _ of
26+ Left e → fail (intercalateMap "\n" renderHumanError e <> "\n" <> intercalateMap "\n" toJSONPath e)
27+ Right (_ ∷ a) → pure unit
test/WriteViaSpec.pursnew file+42
@@ -0,0 +1,42 @@
1+module Test.WriteViaSpec where
2+
3+import Prelude
4+
5+import Data.Either (Either(..))
6+import Test.Spec (Spec, describe, it)
7+import Test.Spec.Assertions (shouldEqual)
8+import Yoga.JSON (class ReadForeign, class WriteForeign)
9+import Yoga.JSON as JSON
10+import Yoga.JSON.Derive (readVia, writeVia)
11+
12+spec ∷ Spec Unit
13+spec = describe "En- and decoding with Coercibles" do
14+ let referenceJSON = """{"myString":"A","myInt":3}"""
15+ it "writing works" do
16+ let myRecord = MyRecord { myInt: MyInt 3, myString: MyString "A" }
17+ JSON.writeJSON myRecord `shouldEqual` referenceJSON
18+ it "reading works" do
19+ JSON.readJSON referenceJSON `shouldEqual` Right (MyRecord { myInt: MyInt 3, myString: MyString "A" })
20+
21+newtype MyInt = MyInt Int
22+newtype MyString = MyString String
23+
24+newtype MyRecord = MyRecord
25+ { myInt ∷ MyInt
26+ , myString ∷ MyString
27+ }
28+
29+instance WriteForeign MyRecord where
30+ writeImpl = writeVia @{ myInt ∷ Int, myString ∷ String }
31+
32+instance ReadForeign MyRecord where
33+ readImpl = readVia @{ myInt ∷ Int, myString ∷ String }
34+
35+-- Below instances are just necessary for the tests to compile
36+
37+instance Show MyRecord where
38+ show = JSON.writeJSON
39+
40+derive instance Eq MyRecord
41+derive instance Eq MyInt
42+derive instance Eq MyString