diff --git a/.envrc b/.envrc index 3550a30f..22e250e0 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,3 @@ +watch_file flake.lock +watch_file flake.nix use flake diff --git a/.github/workflows/haskell-and-purescript.yml b/.github/workflows/haskell-and-purescript.yml new file mode 100644 index 00000000..0a61c1d9 --- /dev/null +++ b/.github/workflows/haskell-and-purescript.yml @@ -0,0 +1,76 @@ +# modified from https://github.com/jgm/pandoc/blob/master/.github/workflows/ci.yml +name: Haskell library and example + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - '**' + paths-ignore: [] + pull_request: + paths-ignore: [] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + ghc: ['9.6.7','9.8.4','9.10.1'] + cabal: ['3.14.2.0'] + os: [ubuntu-latest] + name: Haskell GHC ${{ matrix.ghc }} sample + steps: + - uses: actions/checkout@v4 + - uses: haskell/ghcup-setup@v1.2.2 + with: + ghc: ${{ matrix.ghc }} + cabal: ${{ matrix.cabal }} + config: | + # don't cache metadata files based on last access time + meta-cache: 0 + # see https://github.com/haskell/ghcup-hs/blob/master/data/config.yaml + # for full documentation + url-source: + - GHCupURL + - prereleases + - name: Cabal Update + run: | + cabal update + + - name: Build Haskell + run: | + cabal build all --enable-tests + + - uses: purescript-contrib/setup-purescript@main + with: + spago: "unstable" + + - name: Cache PureScript dependencies + uses: actions/cache@v4.2.3 + with: + key: ${{ runner.os }}-spago-${{ hashFiles('**/spago.yaml') }} + path: | + .spago + output + test/RoundTripArgonautAesonGeneric/app/output + test/RoundTripJsonHelpers/app/output + + - name: Build PureScript + run: | + spago build + cd test/RoundTripArgonautAesonGeneric/app + spago build + cd ../../../ + cd test/RoundTripJsonHelpers/app + spago build + + - name: Haskell Tests + run: | + cabal test all --disable-optimization + + - name: Spago Tests + run: | + spago test diff --git a/.github/workflows/haskell.yml b/.github/workflows/haskell.yml deleted file mode 100644 index 4e341f00..00000000 --- a/.github/workflows/haskell.yml +++ /dev/null @@ -1,70 +0,0 @@ -# modified from https://github.com/jgm/pandoc/blob/master/.github/workflows/ci.yml -name: Haskell library and example - -on: - push: - branches: - - '**' - paths-ignore: [] - pull_request: - paths-ignore: [] - -jobs: - linux: - - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - versions: - - ghc: '8.6.5' - cabal: '3.6' - - ghc: '8.8.4' - cabal: '3.6' - - ghc: '8.10.4' - cabal: '3.6' - - ghc: '9.0.2' - cabal: '3.6' - - ghc: '9.2.4' - cabal: '3.6' - steps: - - uses: actions/checkout@v2 - - # need to install older cabal/ghc versions from ppa repository - - - name: Install recent cabal/ghc - uses: haskell/actions/setup@v1 - with: - ghc-version: ${{ matrix.versions.ghc }} - cabal-version: ${{ matrix.versions.cabal }} - - # declare/restore cached things - # caching doesn't work for scheduled runs yet - # https://github.com/actions/cache/issues/63 - - - name: Cache cabal global package db - id: cabal-global - uses: actions/cache@v2 - with: - path: | - ~/.cabal - key: ${{ runner.os }}-${{ matrix.versions.ghc }}-${{ matrix.versions.cabal }}-cabal-global-${{ hashFiles('cabal.project') }} - - - name: Cache cabal work - id: cabal-local - uses: actions/cache@v2 - with: - path: | - dist-newstyle - key: ${{ runner.os }}-${{ matrix.versions.ghc }}-${{ matrix.versions.cabal }}-cabal-local - - - name: Install dependencies - run: | - cabal update - cabal build all --dependencies-only --enable-tests --disable-optimization - - name: Build - run: | - cabal build all --enable-tests --disable-optimization 2>&1 | tee build.log - - name: Test - run: | - cabal test all --disable-optimization diff --git a/.github/workflows/nix-flake.yml b/.github/workflows/nix-flake.yml index d09c9898..308e7013 100644 --- a/.github/workflows/nix-flake.yml +++ b/.github/workflows/nix-flake.yml @@ -1,4 +1,9 @@ name: "Nix Flake" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: pull_request: push: @@ -6,7 +11,35 @@ jobs: tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v20 - - run: nix build - # - run: nix flake check + - uses: actions/checkout@v4 + + - uses: nixbuild/nix-quick-install-action@v30 + with: + nix_conf: | + keep-env-derivations = true + keep-outputs = true + + - name: Restore and save Nix store + uses: nix-community/cache-nix-action@v6 + with: + primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} + restore-prefixes-first-match: nix-${{ runner.os }}- + gc-max-store-size-linux: 1G + purge: true + purge-prefixes: nix-${{ runner.os }}- + purge-created: 0 + purge-last-accessed: 0 + purge-primary-key: never + + - name: "Check `nix develop` shell" + run: nix develop --check + - name: "Check `nix develop` shell can run command" + run: nix develop --command echo + - run: nix build + - run: nix flake check + - name: "Run all Haskell tests in the `nix develop` shell" + run: | + nix develop --command cabal update + nix develop --command cabal test + - name: "Run all PureScript tests in the `nix develop` shell" + run: nix develop --command spago test diff --git a/.github/workflows/purescript.yml b/.github/workflows/purescript.yml deleted file mode 100644 index 551e38bb..00000000 --- a/.github/workflows/purescript.yml +++ /dev/null @@ -1,47 +0,0 @@ -# adapted from https://github.com/purescript-contrib/purescript-argonaut-generic/blob/d211820cfec5c7cf2caa20dc6dc293671949b55c/.github/workflows/ci.yml -name: Purescript example - -on: - push: - branches: - - '**' - paths-ignore: [] - pull_request: - paths-ignore: [] - -jobs: - build: - runs-on: ubuntu-20.04 - defaults: - run: - working-directory: ./example - - steps: - - uses: actions/checkout@v2 - - - name: Set up a PureScript toolchain - uses: purescript-contrib/setup-purescript@main - with: # https://github.com/purescript-contrib/setup-purescript#specify-versions - purescript: "0.15.4" - - - name: Cache PureScript dependencies - uses: actions/cache@v2 - with: - key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }} - path: | - .spago - output - - - name: Install dependencies - run: | - npm install -g esbuild - spago install - - - name: Build source - run: spago build --no-install - - - name: Bundle app - run: spago bundle-app --to static/index.js - - - name: Run tests - run: spago test --no-install diff --git a/.github/workflows/stack.yml b/.github/workflows/stack.yml new file mode 100644 index 00000000..cb1c9bd8 --- /dev/null +++ b/.github/workflows/stack.yml @@ -0,0 +1,57 @@ +name: Haskell Stack + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - '**' + paths-ignore: [] + pull_request: + paths-ignore: [] + +jobs: + stack-build: + runs-on: ubuntu-latest + name: Haskell Stack + steps: + - uses: actions/checkout@v4 + - uses: haskell-actions/setup@v2 + with: + enable-stack: true + stack-version: 'latest' + + - uses: freckle/stack-cache-action@v2 + + - name: Build Haskell with Stack + run: | + stack build + + - uses: purescript-contrib/setup-purescript@main + with: + spago: "unstable" + + - name: Cache PureScript dependencies + uses: actions/cache@v4.2.3 + with: + key: ${{ runner.os }}-spago-${{ hashFiles('**/spago.yaml') }} + path: | + .spago + output + test/RoundTripArgonautAesonGeneric/app/output + test/RoundTripJsonHelpers/app/output + + - name: Build PureScript + run: | + spago build + cd test/RoundTripArgonautAesonGeneric/app + spago build + cd ../../../ + cd test/RoundTripJsonHelpers/app + spago build + + - name: Haskell Tests with Stack + run: | + stack test diff --git a/.gitignore b/.gitignore index 9e7215ab..d5b93e03 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,6 @@ cabal.sandbox.config dist dist-* shell.nix -stack.yaml .dir-locals.el .psc-ide-port diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..8c7a8bb7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog for purescript-bridge + +## 0.16.0.0 (unreleased) +* merge https://github.com/input-output-hk/purescript-bridge +* support https://github.com/input-output-hk/purescript-bridge-json-helpers +* `CodeGenSwitches` no longer used +* `Proxy` no longer used +* `Printer` uses `Leijen.Text` instead of `Text` +* `genericShow` PureScript instance from IOHK + * I think the same as https://github.com/eskimor/purescript-bridge/pull/85 + * PR 85 has been replaced with IOHK's implementation +* some unit tests replaced with IOHK's tests +* all printer imports are combined into one function `instanceToImportLines` instead of being divided between two modules +* excellent `RoundTrip` tests implemented by IOHK + * greatly improves test coverage for both Argonaut and `json-helpers` and exposes issues diff --git a/README.md b/README.md index 2ceb6eb5..a35b3143 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,103 @@ # purescript-bridge - - -[](https://github.com/eskimor/purescript-bridge/actions/workflows/haskell.yml) [](https://github.com/eskimor/purescript-bridge/actions/workflows/purescript.yml) [](https://github.com/eskimor/purescript-bridge/actions/workflows/nix-flake.yml) - - +[](https://github.com/eskimor/purescript-bridge/actions/workflows/haskell-and-purescript.yml) +[](https://github.com/eskimor/purescript-bridge/actions/workflows/stack.yml) +[](https://github.com/eskimor/purescript-bridge/actions/workflows/nix-flake.yml) Translate your Haskell types to PureScript types. It should in theory work for almost all Haskell types, including type constructors! You just have to instantiate it with dummy parameters from e.g. "Language.PureScript.Bridge.TypeParameters". Data type translation is fully and easily customizable by providing your own `BridgePart` instances! -The latest version of this project requires **Purescript 0.15**. +The latest version of this project requires **PureScript 0.15**. ## JSON encoding / decoding +### Haskell +Use [`aeson`](http://hackage.haskell.org/package/aeson)'s generic encoding/decoding with default options + +### PureScript +There are three PureScript libraries which can interface with Aeson through PureScript bridge. The second, `purescript-argonaut-aeson-generic`, has issues. + +#### [`input-output-hk/purescript-bridge-json-helpers`](https://github.com/input-output-hk/purescript-bridge-json-helpers.git) + +Enable this on the Haskell side with `Language.PureScript.Bridge.SumType.jsonHelpers`. + + +* this library is demonstrated by the `example`; see `./example/readme.md`. +* see `./test/RoundTripJsonHelpers` for an additional example +* sample Dhall config (for [spago-legacy](https://github.com/purescript/spago-legacy)): +``` +, json-helpers = + { dependencies = + [ "aff" + , "argonaut-codecs" + , "argonaut-core" + , "arrays" + , "bifunctors" + , "contravariant" + , "control" + , "effect" + , "either" + , "enums" + , "foldable-traversable" + , "foreign-object" + , "maybe" + , "newtype" + , "ordered-collections" + , "prelude" + , "profunctor" + , "psci-support" + , "quickcheck" + , "record" + , "spec" + , "spec-quickcheck" + , "transformers" + , "tuples" + , "typelevel-prelude" + ] + , repo = + "https://github.com/input-output-hk/purescript-bridge-json-helpers.git" + , version = "486db9ee62882baa42cca24f556848c5f6bec565" + } +``` +#### [`purescript-argonaut-aeson-generic >=0.4.1`](https://pursuit.purescript.org/packages/purescript-argonaut-aeson-generic/0.4.1) ([GitHub](https://github.com/coot/purescript-argonaut-aeson-generic)) + +Enable this on the Haskell side with `Language.PureScript.Bridge.SumType.argonautAesonGeneric`. + +**TODO**: [resolve incompatibility between Argonaut and Aeson](https://github.com/purescript-contrib/purescript-argonaut-codecs/issues/115) + +**Additional requirement**: [`peterbecich/purescript-argonaut-codecs`](https://github.com/peterbecich/purescript-argonaut-codecs.git) +* commit `04abb3eb24a4deafe125be0eb23e2786c642e66b` +* this library is demonstrated by the `example`; see `./example/readme.md`. +* see `./test/RoundTripArgonautAesonGeneric` for additional example + * note that some types have been disabled from the `RoundTripArgonautAesonGeneric` test + * `RoundTripJsonHelpers` tests more types + * the types tested can be expanded when the incompatibility issue is resolved +* sample Dhall config: +``` + , argonaut-codecs = + { dependencies = [ "console" ] + , repo = "https://github.com/peterbecich/purescript-argonaut-codecs.git" + , version = "04abb3eb24a4deafe125be0eb23e2786c642e66b" + } +``` +* forked from [`purescript-contrib/purescript-argonaut-codecs`](https://github.com/purescript-contrib/purescript-argonaut-codecs) + +#### [`paf31/purescript-foreign-generic`](https://github.com/paf31/purescript-foreign-generic) + +See `ForeignObject` in `Language.PureScript.Bridge.SumType`. -For compatible JSON representations: +This may need to be fixed. -* On Haskell side: - * Use [`aeson`](http://hackage.haskell.org/package/aeson)'s generic encoding/decoding with default options -* On Purescript side: - * Use [`purescript-argonaut-aeson-generic >=0.4.1`](https://pursuit.purescript.org/packages/purescript-argonaut-aeson-generic/0.4.1) ([GitHub](https://github.com/coot/purescript-argonaut-aeson-generic)) - * Or use [`purescript-foreign-generic`](https://pursuit.purescript.org/packages/purescript-foreign-generic). - * [This branch](https://github.com/paf31/purescript-foreign-generic/pull/76) is updated for Purescript 0.15. +The test coverage is less than the other two libraries. ## Documentation Usage of this library is documented in `Language.Purescript.Bridge`, with `writePSTypes` you should have everything to get started. Documentation can be found [here](https://www.stackage.org/nightly/package/purescript-bridge). +There is an example; see `./example/readme.md`. + +Also see `./development.md`. + ## Status It works for my use case and is used in production. PRs for more `PSType`s definitions and bridges are very welcome! diff --git a/cabal.project b/cabal.project index 13f1d515..be700cd3 100644 --- a/cabal.project +++ b/cabal.project @@ -1,3 +1,5 @@ packages: . example/. + +tests: true diff --git a/development.md b/development.md new file mode 100644 index 00000000..5f2175d9 --- /dev/null +++ b/development.md @@ -0,0 +1,24 @@ +# Development + +## Example +See `example/readme.md` + +## Spago +All PureScript code can be built from the root of the repository. +*Required*: Spago 0.93.44+ + +## Integration tests + +Run `cabal test` in the root of the repository. + +This includes: +* unit tests +* Round Trip integration tests for two libraries + * json-helpers + * argonaut-aeson-generic + +## Nix Flake + +*All requirements* (including Spago, Cabal, GHC) to build and test the library are provided in the Nix Flake. + +Enter the development shell via `nix develop`. diff --git a/example/app/GeneratePurescript.hs b/example/app/GeneratePurescript.hs index c86d2b22..a4e7e5a3 100644 --- a/example/app/GeneratePurescript.hs +++ b/example/app/GeneratePurescript.hs @@ -3,21 +3,22 @@ module Main where import Control.Lens import Data.Text (pack) import Language.PureScript.Bridge -import Language.PureScript.Bridge.CodeGenSwitches (ForeignOptions (ForeignOptions), - genForeign, - useGenRep) +import ArgonautTypes +import JsonHelpersTypes import qualified MyLib -import Types - -frontEndRoot :: String -frontEndRoot = "src" +import Types (myBridge) -- https://discourse.purescript.org/t/latest-and-greatest-haskell-purescript-serialization/1640/6 main :: IO () main = do - writePSTypesWith - (useGenRep <> genForeign (ForeignOptions False False)) - frontEndRoot + writePSTypesWithNamespace + (Just . PackageName $ pack "Argonaut") + "src" + (buildBridge myBridge) + myArgonautTypes + writePSTypesWithNamespace + (Just . PackageName $ pack "JsonHelpers") + "src" (buildBridge myBridge) - myTypes + myJsonHelpersTypes diff --git a/example/app/Main.hs b/example/app/Main.hs index 76b06e88..c538f02f 100644 --- a/example/app/Main.hs +++ b/example/app/Main.hs @@ -1,8 +1,25 @@ module Main where +import ArgonautTypes +import Control.Lens +import Data.Text (pack) +import JsonHelpersTypes +import Language.PureScript.Bridge import qualified MyLib (main) +import Types main :: IO () main = do - putStrLn "Hello, Haskell!" + -- generate PureScript before server starts + writePSTypesWithNamespace + (Just . PackageName $ pack "Argonaut") + "src" + (buildBridge myBridge) + myArgonautTypes + writePSTypesWithNamespace + (Just . PackageName $ pack "JsonHelpers") + "src" + (buildBridge myBridge) + myJsonHelpersTypes + MyLib.main diff --git a/example/example.cabal b/example/example.cabal index 61cd2406..07fe3e8e 100644 --- a/example/example.cabal +++ b/example/example.cabal @@ -9,7 +9,7 @@ build-type: Simple extra-source-files: CHANGELOG.md library - exposed-modules: MyLib, Types + exposed-modules: MyLib, Types, ArgonautTypes, JsonHelpersTypes hs-source-dirs: src build-depends: base >=4.8 && <5 , aeson >= 1.5.5.0 @@ -23,12 +23,18 @@ library , text , warp , purescript-bridge + , QuickCheck + , ghc-prim default-language: Haskell2010 executable example main-is: Main.hs hs-source-dirs: app - build-depends: base >=4.8 && <5, example + build-depends: base >=4.8 && <5 + , example + , purescript-bridge + , text + , lens default-language: Haskell2010 executable generate-purescript diff --git a/example/packages.dhall b/example/packages.dhall deleted file mode 100644 index 90bb1736..00000000 --- a/example/packages.dhall +++ /dev/null @@ -1,35 +0,0 @@ -let upstream = - https://github.com/purescript/package-sets/releases/download/psc-0.15.4-20220901/packages.dhall - sha256:f1531b29c21ac437ffe5666c1b6cc76f0a9c29d3c9d107ff047aa2567744994f - -let additions = - { argonaut-aeson-generic = - { dependencies = - [ "argonaut" - , "argonaut-codecs" - , "argonaut-generic" - , "console" - , "effect" - , "foreign-object" - , "test-unit" - ] - , repo = - "https://github.com/coot/purescript-argonaut-aeson-generic.git" - , version = "v0.4.1" - } - , foreign-generic = - { dependencies = - [ "effect" - , "foreign" - , "foreign-object" - , "ordered-collections" - , "exceptions" - , "record" - , "identity" - ] - , repo = "https://github.com/jsparkes/purescript-foreign-generic.git" - , version = "844f2ababa2c7a0482bf871e1e6bf970b7e51313" - } - } - -in upstream // additions diff --git a/example/readme.md b/example/readme.md index c4eb963a..c4a64fb4 100644 --- a/example/readme.md +++ b/example/readme.md @@ -1,23 +1,41 @@ -# Purescript Bridge example +# PureScript Bridge example -This project demonstrates the libraries Purescript Bridge and [`purescript-argonaut-aeson-generic`](https://pursuit.purescript.org/packages/purescript-argonaut-aeson-generic) ([GitHub](https://github.com/coot/purescript-argonaut-aeson-generic)). +This project demonstrates: +- PureScript Bridge +- [`purescript-argonaut-aeson-generic`](https://pursuit.purescript.org/packages/purescript-argonaut-aeson-generic) ([GitHub](https://github.com/coot/purescript-argonaut-aeson-generic)) +- [`input-output-hk/purescript-bridge-json-helpers`](https://github.com/input-output-hk/purescript-bridge-json-helpers.git) -It needs Purescript 0.15. +The Haskell type `Foo`, in `src/Types.hs`, is generated for PureScript by PureScript Bridge. Some of values in `Foo` are randomly generated every time the page is loaded. -The Haskell type `Foo`, in `src/Types.hs`, is generated for Purescript by Purescript Bridge. Purescript Argonaut Aeson Generic is used to decode and encode this type, client-side. +On page load, the client: +- requests a `Foo` from the server +- decodes this value using `purescript-argonaut-aeson-generic` +- modifies some of the values +- encodes this with `purescript-argonaut-aeson-generic`, and sends it back to the server +- repeats these steps, encoding and decoding instead with `json-helpers` -In this directory: +# Dependencies +## Nix +The `nix develop` shell will provide PureScript 0.15 and Spago. +## Without Nix +You must install PureScript 0.15 and [spago-next](https://github.com/purescript/spago). -- Generate the Javascript bundle: +# Running the example +- Enter the `example` directory -```spago bundle-app --to static/index.js``` +- With Nix: +``` +nix run +``` -- `cabal run example` +- Or without Nix: +``` +cabal run example +``` - Open [http://localhost:8080/index.html](http://localhost:8080/index.html) - Open the browser's developer console and look for the message received: - ``` Foo message: Hello Foo number: 123 Foo list length: 11 ``` @@ -28,10 +46,20 @@ Foo message: Hello Foo number: 123 Foo list length: 11 Foo message: Hola Foo number: 124 Foo list length: 22 ``` ----------------- +# Updating the PureScript Bridge +- Enter the `example` directory + +- Regenerate the PureScript Bridge types: +``` +cabal run generate-purescript +``` + +- Generate the Javascript bundle: +``` +spago bundle --bundle-type app --module ExampleMain --outfile static/index.js +``` -Regenerate the Purescript for the bridge type `Foo` with `cabal run generate-purescript`. +- Restart the server ----------------- -This Purescript Discourse thread assisted me: https://discourse.purescript.org/t/latest-and-greatest-haskell-purescript-serialization/1640 +More discussion: https://discourse.purescript.org/t/latest-and-greatest-haskell-purescript-serialization/1640 diff --git a/example/spago.dhall b/example/spago.dhall deleted file mode 100644 index 0a650982..00000000 --- a/example/spago.dhall +++ /dev/null @@ -1,23 +0,0 @@ -{ name = "purescript-bridge-example" -, dependencies = - [ "console" - , "effect" - , "foreign-generic" - , "profunctor-lenses" - , "aff" - , "affjax" - , "affjax-web" - , "argonaut-aeson-generic" - , "ordered-collections" - , "argonaut-codecs" - , "argonaut-generic" - , "either" - , "foldable-traversable" - , "foreign-object" - , "maybe" - , "newtype" - , "prelude" - ] -, packages = ./packages.dhall -, sources = [ "src/**/*.purs", "test/**/*.purs" ] -} diff --git a/example/spago.lock b/example/spago.lock new file mode 100644 index 00000000..78d376f4 --- /dev/null +++ b/example/spago.lock @@ -0,0 +1,1627 @@ +workspace: + packages: + bridge-example: + path: ./ + dependencies: + - aff + - affjax + - affjax-web + - argonaut + - argonaut-aeson-generic + - argonaut-codecs + - argonaut-generic + - console + - control + - effect + - either + - foldable-traversable + - foreign-generic + - foreign-object + - json-helpers + - maybe + - newtype + - ordered-collections + - prelude + - profunctor-lenses + - tuples + test_dependencies: [] + build_plan: + - aff + - affjax + - affjax-web + - ansi + - argonaut + - argonaut-aeson-generic + - argonaut-codecs + - argonaut-core + - argonaut-generic + - argonaut-traversals + - arraybuffer-types + - arrays + - avar + - bifunctors + - catenable-lists + - console + - const + - contravariant + - control + - datetime + - distributive + - effect + - either + - enums + - exceptions + - exists + - foldable-traversable + - foreign + - foreign-generic + - foreign-object + - fork + - form-urlencoded + - free + - functions + - functors + - gen + - http-methods + - identity + - integers + - invariant + - js-date + - js-timers + - js-uri + - json-helpers + - lazy + - lcg + - lists + - maybe + - media-types + - mmorph + - newtype + - nonempty + - now + - nullable + - numbers + - ordered-collections + - orders + - parallel + - partial + - pipes + - prelude + - profunctor + - profunctor-lenses + - psci-support + - quickcheck + - random + - record + - refs + - safe-coerce + - spec + - spec-quickcheck + - st + - strings + - tailrec + - test-unit + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unsafe-coerce + - web-dom + - web-events + - web-file + - web-html + - web-storage + - web-xhr + package_set: + address: + registry: 50.1.0 + compiler: ">=0.15.14 <0.16.0" + content: + abc-parser: 2.0.1 + ace: 9.1.0 + aff: 7.1.0 + aff-bus: 6.0.0 + aff-coroutines: 9.0.0 + aff-promise: 4.0.0 + aff-retry: 2.0.0 + affjax: 13.0.0 + affjax-node: 1.0.0 + affjax-web: 1.0.0 + ansi: 7.0.0 + applicative-phases: 1.0.0 + argonaut: 9.0.0 + argonaut-aeson-generic: 0.4.1 + argonaut-codecs: 9.1.0 + argonaut-core: 7.0.0 + argonaut-generic: 8.0.0 + argonaut-traversals: 10.0.0 + argparse-basic: 2.0.0 + array-builder: 0.1.2 + array-search: 0.5.6 + arraybuffer: 13.2.0 + arraybuffer-builder: 3.1.0 + arraybuffer-types: 3.0.2 + arrays: 7.3.0 + arrays-extra: 0.6.1 + arrays-zipper: 2.0.1 + ask: 1.0.0 + assert: 6.0.0 + assert-multiple: 0.3.4 + avar: 5.0.0 + b64: 0.0.8 + barbies: 1.0.1 + barlow-lens: 0.9.0 + bifunctors: 6.0.0 + bigints: 7.0.1 + bolson: 0.3.9 + bookhound: 0.1.7 + bower-json: 3.0.0 + call-by-name: 4.0.1 + canvas: 6.0.0 + canvas-action: 9.0.0 + cartesian: 1.0.6 + catenable-lists: 7.0.0 + chameleon: 1.0.0 + chameleon-halogen: 1.0.3 + chameleon-react-basic: 1.1.0 + chameleon-styled: 2.5.0 + chameleon-transformers: 1.0.0 + channel: 1.0.0 + checked-exceptions: 3.1.1 + choku: 1.0.1 + classless: 0.1.1 + classless-arbitrary: 0.1.1 + classless-decode-json: 0.1.1 + classless-encode-json: 0.1.3 + classnames: 2.0.0 + codec: 6.1.0 + codec-argonaut: 10.0.0 + codec-json: 1.1.0 + colors: 7.0.1 + concur-core: 0.5.0 + concur-react: 0.5.0 + concurrent-queues: 3.0.0 + console: 6.1.0 + const: 6.0.0 + contravariant: 6.0.0 + control: 6.0.0 + convertable-options: 1.0.0 + coroutines: 7.0.0 + css: 6.0.0 + css-frameworks: 1.0.1 + data-mvc: 0.0.2 + datetime: 6.1.0 + datetime-parsing: 0.2.0 + debug: 6.0.2 + decimals: 7.1.0 + default-values: 1.0.1 + deku: 0.9.23 + deno: 0.0.5 + dissect: 1.0.0 + distributive: 6.0.0 + dom-filereader: 7.0.0 + dom-indexed: 12.0.0 + dotenv: 4.0.3 + droplet: 0.6.0 + dts: 1.0.0 + dual-numbers: 1.0.2 + dynamic-buffer: 3.0.1 + echarts-simple: 0.0.1 + effect: 4.0.0 + either: 6.1.0 + elmish: 0.11.3 + elmish-enzyme: 0.1.1 + elmish-hooks: 0.10.0 + elmish-html: 0.8.2 + elmish-testing-library: 0.3.2 + email-validate: 7.0.0 + encoding: 0.0.9 + enums: 6.0.1 + env-names: 0.3.4 + error: 2.0.0 + eta-conversion: 0.3.2 + exceptions: 6.0.0 + exists: 6.0.0 + exitcodes: 4.0.0 + expect-inferred: 3.0.0 + fahrtwind: 2.0.0 + fallback: 0.1.0 + fast-vect: 1.2.0 + fetch: 4.1.0 + fetch-argonaut: 1.0.1 + fetch-core: 5.1.0 + fetch-yoga-json: 1.1.0 + fft-js: 0.1.0 + filterable: 5.0.0 + fix-functor: 0.1.0 + fixed-points: 7.0.0 + fixed-precision: 5.0.0 + flame: 1.3.0 + float32: 2.0.0 + fmt: 0.2.1 + foldable-traversable: 6.0.0 + foldable-traversable-extra: 0.0.6 + foreign: 7.0.0 + foreign-object: 4.1.0 + foreign-readwrite: 3.4.0 + forgetmenot: 0.1.0 + fork: 6.0.0 + form-urlencoded: 7.0.0 + formatters: 7.0.0 + framer-motion: 1.0.1 + free: 7.1.0 + freeap: 7.0.0 + freer-free: 0.0.1 + freet: 7.0.0 + functions: 6.0.0 + functor1: 3.0.0 + functors: 5.0.0 + fuzzy: 0.4.0 + gen: 4.0.0 + generate-values: 1.0.1 + generic-router: 0.0.1 + geojson: 0.0.5 + geometry-plane: 1.0.3 + gojs: 0.1.1 + grain: 3.0.0 + grain-router: 3.0.0 + grain-virtualized: 3.0.0 + graphs: 8.1.0 + group: 4.1.1 + halogen: 7.0.0 + halogen-bootstrap5: 5.3.2 + halogen-canvas: 1.0.0 + halogen-css: 10.0.0 + halogen-echarts-simple: 0.0.4 + halogen-formless: 4.0.3 + halogen-helix: 1.0.0 + halogen-hooks: 0.6.3 + halogen-hooks-extra: 0.9.0 + halogen-infinite-scroll: 1.1.0 + halogen-store: 0.5.4 + halogen-storybook: 2.0.0 + halogen-subscriptions: 2.0.0 + halogen-svg-elems: 8.0.0 + halogen-typewriter: 1.0.4 + halogen-vdom: 8.0.0 + halogen-vdom-string-renderer: 0.5.0 + halogen-xterm: 2.0.0 + heckin: 2.0.1 + heterogeneous: 0.6.0 + homogeneous: 0.4.0 + http-methods: 6.0.0 + httpurple: 4.0.0 + humdrum: 0.0.1 + hyrule: 2.3.8 + identity: 6.0.0 + identy: 4.0.1 + indexed-db: 1.0.0 + indexed-monad: 3.0.0 + int64: 3.0.0 + integers: 6.0.0 + interpolate: 5.0.2 + intersection-observer: 1.0.1 + invariant: 6.0.0 + jarilo: 1.0.1 + jelly: 0.10.0 + jelly-router: 0.3.0 + jelly-signal: 0.4.0 + jest: 1.0.0 + js-abort-controller: 1.0.0 + js-bigints: 2.2.1 + js-date: 8.0.0 + js-fetch: 0.2.1 + js-fileio: 3.0.0 + js-intl: 1.0.4 + js-iterators: 0.1.1 + js-maps: 0.1.2 + js-promise: 1.0.0 + js-promise-aff: 1.0.0 + js-timers: 6.1.0 + js-uri: 3.1.0 + json: 1.0.0 + json-codecs: 5.0.0 + justifill: 0.5.0 + jwt: 0.0.9 + labeled-data: 0.2.0 + lazy: 6.0.0 + lazy-joe: 1.0.0 + lcg: 4.0.0 + leibniz: 5.0.0 + leveldb: 1.0.1 + liminal: 1.0.1 + linalg: 6.0.0 + lists: 7.0.0 + literals: 1.0.2 + logging: 3.0.0 + logging-journald: 0.4.0 + lumi-components: 18.0.0 + machines: 7.0.0 + maps-eager: 0.4.1 + marionette: 1.0.0 + marionette-react-basic-hooks: 0.1.1 + marked: 0.1.0 + matrices: 5.0.1 + matryoshka: 1.0.0 + maybe: 6.0.0 + media-types: 6.0.0 + meowclient: 1.0.0 + midi: 4.0.0 + milkis: 9.0.0 + minibench: 4.0.1 + mmorph: 7.0.0 + monad-control: 5.0.0 + monad-logger: 1.3.1 + monad-loops: 0.5.0 + monad-unlift: 1.0.1 + monoid-extras: 0.0.1 + monoidal: 0.16.0 + morello: 0.4.0 + mote: 3.0.0 + motsunabe: 2.0.0 + mvc: 0.0.1 + mysql: 6.0.1 + n3: 0.1.0 + nano-id: 1.1.0 + nanoid: 0.1.0 + naturals: 3.0.0 + nested-functor: 0.2.1 + newtype: 5.0.0 + nextjs: 0.1.1 + nextui: 0.2.0 + node-buffer: 9.0.0 + node-child-process: 11.1.0 + node-event-emitter: 3.0.0 + node-execa: 5.0.0 + node-fs: 9.1.0 + node-glob-basic: 1.3.0 + node-http: 9.1.0 + node-http2: 1.1.1 + node-human-signals: 1.0.0 + node-net: 5.1.0 + node-os: 5.1.0 + node-path: 5.0.0 + node-process: 11.2.0 + node-readline: 8.1.0 + node-sqlite3: 8.0.0 + node-streams: 9.0.0 + node-tls: 0.3.1 + node-url: 7.0.1 + node-zlib: 0.4.0 + nonempty: 7.0.0 + now: 6.0.0 + npm-package-json: 2.0.0 + nullable: 6.0.0 + numberfield: 0.1.0 + numbers: 9.0.1 + oak: 3.1.1 + oak-debug: 1.2.2 + object-maps: 0.3.0 + ocarina: 1.5.4 + open-folds: 6.3.0 + open-memoize: 6.1.0 + open-pairing: 6.1.0 + options: 7.0.0 + optparse: 5.0.1 + ordered-collections: 3.1.1 + ordered-set: 0.4.0 + orders: 6.0.0 + owoify: 1.2.0 + pairs: 9.0.1 + parallel: 7.0.0 + parsing: 10.2.0 + parsing-dataview: 3.2.4 + partial: 4.0.0 + pathy: 9.0.0 + pha: 0.13.0 + phaser: 0.7.0 + phylio: 1.1.2 + pipes: 8.0.0 + pirates-charm: 0.0.1 + pmock: 0.9.0 + point-free: 1.0.0 + pointed-list: 0.5.1 + polymorphic-vectors: 4.0.0 + posix-types: 6.0.0 + precise: 6.0.0 + precise-datetime: 7.0.0 + prelude: 6.0.1 + prettier-printer: 3.0.0 + profunctor: 6.0.0 + profunctor-lenses: 8.0.0 + protobuf: 4.3.0 + psa-utils: 8.0.0 + psci-support: 6.0.0 + punycode: 1.0.0 + qualified-do: 2.2.0 + quantities: 12.2.0 + quickcheck: 8.0.1 + quickcheck-combinators: 0.1.3 + quickcheck-laws: 7.0.0 + quickcheck-utf8: 0.0.0 + random: 6.0.0 + rationals: 6.0.0 + rdf: 0.1.0 + react: 11.0.0 + react-aria: 0.2.0 + react-basic: 17.0.0 + react-basic-classic: 3.0.0 + react-basic-dnd: 10.1.0 + react-basic-dom: 6.1.0 + react-basic-emotion: 7.1.0 + react-basic-hooks: 8.2.0 + react-basic-storybook: 2.0.0 + react-dom: 8.0.0 + react-halo: 3.0.0 + react-icons: 1.1.4 + react-markdown: 0.1.0 + react-testing-library: 4.0.1 + react-virtuoso: 1.0.0 + read: 1.0.1 + recharts: 1.1.0 + record: 4.0.0 + record-extra: 5.0.1 + record-ptional-fields: 0.1.2 + record-studio: 1.0.4 + refs: 6.0.0 + remotedata: 5.0.0 + resize-observer: 1.0.0 + resource: 2.0.1 + resourcet: 1.0.0 + result: 1.0.3 + return: 0.2.0 + ring-modules: 5.0.1 + rito: 0.3.4 + rough-notation: 1.0.0 + routing: 11.0.0 + routing-duplex: 0.7.0 + run: 5.0.0 + safe-coerce: 2.0.0 + safely: 4.0.1 + school-of-music: 1.3.0 + selection-foldable: 0.2.0 + selective-functors: 1.0.1 + semirings: 7.0.0 + signal: 13.0.0 + simple-emitter: 3.0.1 + simple-i18n: 2.0.1 + simple-json: 9.0.0 + simple-ulid: 3.0.0 + sized-matrices: 1.0.0 + sized-vectors: 5.0.2 + slug: 3.0.8 + small-ffi: 4.0.1 + soundfonts: 4.1.0 + sparse-matrices: 1.3.0 + sparse-polynomials: 2.0.5 + spec: 7.6.0 + spec-mocha: 5.1.0 + spec-quickcheck: 5.0.0 + splitmix: 2.1.0 + ssrs: 1.0.0 + st: 6.2.0 + statistics: 0.3.2 + strictlypositiveint: 1.0.1 + string-parsers: 8.0.0 + strings: 6.0.1 + strings-extra: 4.0.0 + stringutils: 0.0.12 + substitute: 0.2.3 + supply: 0.2.0 + svg-parser: 3.0.0 + systemd-journald: 0.3.0 + tagged: 4.0.2 + tailrec: 6.1.0 + tecton: 0.2.1 + tecton-halogen: 0.2.0 + test-unit: 17.0.0 + thermite: 6.3.1 + thermite-dom: 0.3.1 + these: 6.0.0 + transformation-matrix: 1.0.1 + transformers: 6.0.0 + tree-rose: 4.0.2 + ts-bridge: 4.0.0 + tuples: 7.0.0 + two-or-more: 1.0.0 + type-equality: 4.0.1 + typedenv: 2.0.1 + typelevel: 6.0.0 + typelevel-lists: 2.1.0 + typelevel-peano: 1.0.1 + typelevel-prelude: 7.0.0 + typelevel-regex: 0.0.3 + typelevel-rows: 0.1.0 + uint: 7.0.0 + ulid: 3.0.1 + uncurried-transformers: 1.1.0 + undefined: 2.0.0 + undefined-is-not-a-problem: 1.1.0 + unfoldable: 6.0.0 + unicode: 6.0.0 + unique: 0.6.1 + unlift: 1.0.1 + unordered-collections: 3.0.1 + unsafe-coerce: 6.0.0 + unsafe-reference: 5.0.0 + untagged-to-tagged: 0.1.4 + untagged-union: 1.0.0 + uri: 9.0.0 + uuid: 9.0.0 + uuidv4: 1.0.0 + validation: 6.0.0 + variant: 8.0.0 + variant-encodings: 2.0.0 + vectorfield: 1.0.1 + vectors: 2.1.0 + versions: 7.0.0 + visx: 0.0.2 + web-clipboard: 5.0.0 + web-cssom: 2.0.0 + web-cssom-view: 0.1.0 + web-dom: 6.0.0 + web-dom-parser: 8.0.0 + web-dom-xpath: 3.0.0 + web-encoding: 3.0.0 + web-events: 4.0.0 + web-fetch: 4.0.1 + web-file: 4.0.0 + web-geometry: 0.1.0 + web-html: 4.1.0 + web-pointerevents: 2.0.0 + web-proletarian: 1.0.0 + web-promise: 3.2.0 + web-resize-observer: 2.1.0 + web-router: 1.0.0 + web-socket: 4.0.0 + web-storage: 5.0.0 + web-streams: 4.0.0 + web-touchevents: 4.0.0 + web-uievents: 5.0.0 + web-url: 2.0.0 + web-workers: 1.1.0 + web-xhr: 5.0.1 + webextension-polyfill: 0.1.0 + webgpu: 0.0.1 + which: 2.0.0 + xterm: 1.0.0 + yoga-fetch: 1.0.1 + yoga-json: 5.1.0 + yoga-om: 0.1.0 + yoga-postgres: 6.0.0 + yoga-tree: 1.0.0 + z3: 0.0.2 + zipperarray: 2.0.0 + extra_packages: + argonaut-aeson-generic: + git: https://github.com/coot/purescript-argonaut-aeson-generic.git + ref: v0.4.1 + dependencies: + - argonaut + - argonaut-codecs + - argonaut-generic + - console + - effect + - foreign-object + - test-unit + argonaut-codecs: + git: https://github.com/peterbecich/purescript-argonaut-codecs.git + ref: 04abb3eb24a4deafe125be0eb23e2786c642e66b + dependencies: + - console + foreign-generic: + git: https://github.com/jsparkes/purescript-foreign-generic.git + ref: 844f2ababa2c7a0482bf871e1e6bf970b7e51313 + dependencies: + - effect + - exceptions + - foreign + - foreign-object + - identity + - ordered-collections + - record + json-helpers: + git: https://github.com/input-output-hk/purescript-bridge-json-helpers.git + ref: 486db9ee62882baa42cca24f556848c5f6bec565 + dependencies: + - aff + - argonaut-codecs + - argonaut-core + - arrays + - bifunctors + - contravariant + - control + - effect + - either + - enums + - foldable-traversable + - foreign-object + - maybe + - newtype + - ordered-collections + - prelude + - profunctor + - psci-support + - quickcheck + - record + - spec + - spec-quickcheck + - transformers + - tuples + - typelevel-prelude +packages: + aff: + type: registry + version: 7.1.0 + integrity: sha256-7hOC6uQO9XBAI5FD8F33ChLjFAiZVfd4BJMqlMh7TNU= + dependencies: + - arrays + - bifunctors + - control + - datetime + - effect + - either + - exceptions + - foldable-traversable + - functions + - maybe + - newtype + - parallel + - prelude + - refs + - tailrec + - transformers + - unsafe-coerce + affjax: + type: registry + version: 13.0.0 + integrity: sha256-blYfaoW4FYIrIdvmT4sB7nN7BathFaEfZuiVLPmHJOo= + dependencies: + - aff + - argonaut-core + - arraybuffer-types + - foreign + - form-urlencoded + - http-methods + - integers + - media-types + - nullable + - refs + - unsafe-coerce + - web-xhr + affjax-web: + type: registry + version: 1.0.0 + integrity: sha256-n/yJUk1wMxMN7fJ2TJ+fELgieomy29N617yOshAnrc0= + dependencies: + - aff + - affjax + - either + - maybe + - prelude + ansi: + type: registry + version: 7.0.0 + integrity: sha256-ZMB6HD+q9CXvn9fRCmJ8dvuDrOVHcjombL3oNOerVnE= + dependencies: + - foldable-traversable + - lists + - strings + argonaut: + type: registry + version: 9.0.0 + integrity: sha256-9sHzkzcFkaMUa9+3FjIybJDYnHtY4Jp4zHOJ84qPTXo= + dependencies: + - argonaut-codecs + - argonaut-core + - argonaut-traversals + argonaut-aeson-generic: + type: git + url: https://github.com/coot/purescript-argonaut-aeson-generic.git + rev: 4cee717e3e0003b76e699550f5fc35976901078c + dependencies: + - argonaut + - argonaut-codecs + - argonaut-generic + - console + - effect + - foreign-object + - test-unit + argonaut-codecs: + type: git + url: https://github.com/peterbecich/purescript-argonaut-codecs.git + rev: 04abb3eb24a4deafe125be0eb23e2786c642e66b + dependencies: + - console + argonaut-core: + type: registry + version: 7.0.0 + integrity: sha256-RC82GfAjItydxrO24cdX373KHVZiLqybu19b5X8u7B4= + dependencies: + - arrays + - control + - either + - foreign-object + - functions + - gen + - maybe + - nonempty + - prelude + - strings + - tailrec + argonaut-generic: + type: registry + version: 8.0.0 + integrity: sha256-WCqRWoomRKg5BFZnGBS4k4SqBX84fy/X1aJzMyaIeP0= + dependencies: + - argonaut-codecs + - argonaut-core + - prelude + - record + argonaut-traversals: + type: registry + version: 10.0.0 + integrity: sha256-9nSfqR70rjiNWVVsCoK+jrm9dmyZTx89IKNYO6uNUIk= + dependencies: + - argonaut-codecs + - argonaut-core + - profunctor-lenses + arraybuffer-types: + type: registry + version: 3.0.2 + integrity: sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA= + dependencies: [] + arrays: + type: registry + version: 7.3.0 + integrity: sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc= + dependencies: + - bifunctors + - control + - foldable-traversable + - functions + - maybe + - nonempty + - partial + - prelude + - safe-coerce + - st + - tailrec + - tuples + - unfoldable + - unsafe-coerce + avar: + type: registry + version: 5.0.0 + integrity: sha256-e7hf0x4hEpcygXP0LtvfvAQ49Bbj2aWtZT3gqM///0A= + dependencies: + - aff + - effect + - either + - exceptions + - functions + - maybe + bifunctors: + type: registry + version: 6.0.0 + integrity: sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw= + dependencies: + - const + - either + - newtype + - prelude + - tuples + catenable-lists: + type: registry + version: 7.0.0 + integrity: sha256-76vYENhwF4BWTBsjeLuErCH2jqVT4M3R1HX+4RwSftA= + dependencies: + - control + - foldable-traversable + - lists + - maybe + - prelude + - tuples + - unfoldable + console: + type: registry + version: 6.1.0 + integrity: sha256-CxmAzjgyuGDmt9FZW51VhV6rBPwR6o0YeKUzA9rSzcM= + dependencies: + - effect + - prelude + const: + type: registry + version: 6.0.0 + integrity: sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc= + dependencies: + - invariant + - newtype + - prelude + contravariant: + type: registry + version: 6.0.0 + integrity: sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c= + dependencies: + - const + - either + - newtype + - prelude + - tuples + control: + type: registry + version: 6.0.0 + integrity: sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk= + dependencies: + - newtype + - prelude + datetime: + type: registry + version: 6.1.0 + integrity: sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI= + dependencies: + - bifunctors + - control + - either + - enums + - foldable-traversable + - functions + - gen + - integers + - lists + - maybe + - newtype + - numbers + - ordered-collections + - partial + - prelude + - tuples + distributive: + type: registry + version: 6.0.0 + integrity: sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ= + dependencies: + - identity + - newtype + - prelude + - tuples + - type-equality + effect: + type: registry + version: 4.0.0 + integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M= + dependencies: + - prelude + either: + type: registry + version: 6.1.0 + integrity: sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY= + dependencies: + - control + - invariant + - maybe + - prelude + enums: + type: registry + version: 6.0.1 + integrity: sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8= + dependencies: + - control + - either + - gen + - maybe + - newtype + - nonempty + - partial + - prelude + - tuples + - unfoldable + exceptions: + type: registry + version: 6.0.0 + integrity: sha256-y/xTAEIZIARCE+50/u1di0ncebJ+CIwNOLswyOWzMTw= + dependencies: + - effect + - either + - maybe + - prelude + exists: + type: registry + version: 6.0.0 + integrity: sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8= + dependencies: + - unsafe-coerce + foldable-traversable: + type: registry + version: 6.0.0 + integrity: sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM= + dependencies: + - bifunctors + - const + - control + - either + - functors + - identity + - maybe + - newtype + - orders + - prelude + - tuples + foreign: + type: registry + version: 7.0.0 + integrity: sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA= + dependencies: + - either + - functions + - identity + - integers + - lists + - maybe + - prelude + - strings + - transformers + foreign-generic: + type: git + url: https://github.com/jsparkes/purescript-foreign-generic.git + rev: 844f2ababa2c7a0482bf871e1e6bf970b7e51313 + dependencies: + - effect + - exceptions + - foreign + - foreign-object + - identity + - ordered-collections + - record + foreign-object: + type: registry + version: 4.1.0 + integrity: sha256-q24okj6mT+yGHYQ+ei/pYPj5ih6sTbu7eDv/WU56JVo= + dependencies: + - arrays + - foldable-traversable + - functions + - gen + - lists + - maybe + - prelude + - st + - tailrec + - tuples + - typelevel-prelude + - unfoldable + fork: + type: registry + version: 6.0.0 + integrity: sha256-X7u0SuCvFbLbzuNEKLBNuWjmcroqMqit4xEzpQwAP7E= + dependencies: + - aff + form-urlencoded: + type: registry + version: 7.0.0 + integrity: sha256-WUzk8DTjrbPVHKZ5w7XpPBO6ci6xFhvYguHp6RvX+18= + dependencies: + - foldable-traversable + - js-uri + - maybe + - newtype + - prelude + - strings + - tuples + free: + type: registry + version: 7.1.0 + integrity: sha256-JAumgEsGSzJCNLD8AaFvuX7CpqS5yruCngi6yI7+V5k= + dependencies: + - catenable-lists + - control + - distributive + - either + - exists + - foldable-traversable + - invariant + - lazy + - maybe + - prelude + - tailrec + - transformers + - tuples + - unsafe-coerce + functions: + type: registry + version: 6.0.0 + integrity: sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI= + dependencies: + - prelude + functors: + type: registry + version: 5.0.0 + integrity: sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU= + dependencies: + - bifunctors + - const + - contravariant + - control + - distributive + - either + - invariant + - maybe + - newtype + - prelude + - profunctor + - tuples + - unsafe-coerce + gen: + type: registry + version: 4.0.0 + integrity: sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI= + dependencies: + - either + - foldable-traversable + - identity + - maybe + - newtype + - nonempty + - prelude + - tailrec + - tuples + - unfoldable + http-methods: + type: registry + version: 6.0.0 + integrity: sha256-Orr7rbDGcp7qoqmUMXPRMjBx+C4jqOQcFe9+gE3nMgU= + dependencies: + - either + - prelude + - strings + identity: + type: registry + version: 6.0.0 + integrity: sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY= + dependencies: + - control + - invariant + - newtype + - prelude + integers: + type: registry + version: 6.0.0 + integrity: sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158= + dependencies: + - maybe + - numbers + - prelude + invariant: + type: registry + version: 6.0.0 + integrity: sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo= + dependencies: + - control + - prelude + js-date: + type: registry + version: 8.0.0 + integrity: sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo= + dependencies: + - datetime + - effect + - exceptions + - foreign + - integers + - now + js-timers: + type: registry + version: 6.1.0 + integrity: sha256-znHWLSSOYw15P5DTcsAdal2lf7nGA2yayLdOZ2t5r7o= + dependencies: + - effect + js-uri: + type: registry + version: 3.1.0 + integrity: sha256-3p0ynHveCJmC2CXze+eMBdW/2l5e953Q8XMAKz+jxUo= + dependencies: + - functions + - maybe + json-helpers: + type: git + url: https://github.com/input-output-hk/purescript-bridge-json-helpers.git + rev: 486db9ee62882baa42cca24f556848c5f6bec565 + dependencies: + - aff + - argonaut-codecs + - argonaut-core + - arrays + - bifunctors + - contravariant + - control + - effect + - either + - enums + - foldable-traversable + - foreign-object + - maybe + - newtype + - ordered-collections + - prelude + - profunctor + - psci-support + - quickcheck + - record + - spec + - spec-quickcheck + - transformers + - tuples + - typelevel-prelude + lazy: + type: registry + version: 6.0.0 + integrity: sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU= + dependencies: + - control + - foldable-traversable + - invariant + - prelude + lcg: + type: registry + version: 4.0.0 + integrity: sha256-h7ME5cthLfbgJOJdsZcSfFpwXsx4rf8YmhebU+3iSYg= + dependencies: + - effect + - integers + - maybe + - partial + - prelude + - random + lists: + type: registry + version: 7.0.0 + integrity: sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI= + dependencies: + - bifunctors + - control + - foldable-traversable + - lazy + - maybe + - newtype + - nonempty + - partial + - prelude + - tailrec + - tuples + - unfoldable + maybe: + type: registry + version: 6.0.0 + integrity: sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q= + dependencies: + - control + - invariant + - newtype + - prelude + media-types: + type: registry + version: 6.0.0 + integrity: sha256-n/4FoGBasbVSYscGVRSyBunQ6CZbL3jsYL+Lp01mc9k= + dependencies: + - newtype + - prelude + mmorph: + type: registry + version: 7.0.0 + integrity: sha256-urZlZNNqGeQFe5D/ClHlR8QgGBNHTMFPtJ5S5IpflTQ= + dependencies: + - free + - functors + - transformers + newtype: + type: registry + version: 5.0.0 + integrity: sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw= + dependencies: + - prelude + - safe-coerce + nonempty: + type: registry + version: 7.0.0 + integrity: sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs= + dependencies: + - control + - foldable-traversable + - maybe + - prelude + - tuples + - unfoldable + now: + type: registry + version: 6.0.0 + integrity: sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY= + dependencies: + - datetime + - effect + nullable: + type: registry + version: 6.0.0 + integrity: sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o= + dependencies: + - effect + - functions + - maybe + numbers: + type: registry + version: 9.0.1 + integrity: sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk= + dependencies: + - functions + - maybe + ordered-collections: + type: registry + version: 3.1.1 + integrity: sha256-boSYHmlz4aSbwsNN4VxiwCStc0t+y1F7BXmBS+1JNtI= + dependencies: + - arrays + - foldable-traversable + - gen + - lists + - maybe + - partial + - prelude + - st + - tailrec + - tuples + - unfoldable + orders: + type: registry + version: 6.0.0 + integrity: sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink= + dependencies: + - newtype + - prelude + parallel: + type: registry + version: 7.0.0 + integrity: sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o= + dependencies: + - control + - effect + - either + - foldable-traversable + - functors + - maybe + - newtype + - prelude + - profunctor + - refs + - transformers + partial: + type: registry + version: 4.0.0 + integrity: sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4= + dependencies: [] + pipes: + type: registry + version: 8.0.0 + integrity: sha256-kvfqGM4cPA/wCcBHbp5psouFw5dZGvku2462x7ZBwSY= + dependencies: + - aff + - lists + - mmorph + - prelude + - tailrec + - transformers + - tuples + prelude: + type: registry + version: 6.0.1 + integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0= + dependencies: [] + profunctor: + type: registry + version: 6.0.0 + integrity: sha256-99NzxFgTr4CGlCSRYG1kShL+JhYbihhHtbOk1/0R5zI= + dependencies: + - control + - distributive + - either + - exists + - invariant + - newtype + - prelude + - tuples + profunctor-lenses: + type: registry + version: 8.0.0 + integrity: sha256-K7f29rHRHgVSb2Y/PaSKtfYPriP6n87BJNO7EhsZHas= + dependencies: + - arrays + - bifunctors + - const + - control + - distributive + - either + - foldable-traversable + - foreign-object + - functors + - identity + - lists + - maybe + - newtype + - ordered-collections + - partial + - prelude + - profunctor + - record + - transformers + - tuples + psci-support: + type: registry + version: 6.0.0 + integrity: sha256-C6ql4P9TEP06hft/1Z5QumPA4yARR4VIxDdhmL1EO+Y= + dependencies: + - console + - effect + - prelude + quickcheck: + type: registry + version: 8.0.1 + integrity: sha256-ZvpccKQCvgslTXZCNmpYW4bUsFzhZd/kQUr2WmxFTGY= + dependencies: + - arrays + - console + - control + - effect + - either + - enums + - exceptions + - foldable-traversable + - gen + - identity + - integers + - lazy + - lcg + - lists + - maybe + - newtype + - nonempty + - numbers + - partial + - prelude + - record + - st + - strings + - tailrec + - transformers + - tuples + - unfoldable + random: + type: registry + version: 6.0.0 + integrity: sha256-CJ611a35MPCE7XQMp0rdC6MCn76znlhisiCRgboAG+Q= + dependencies: + - effect + - integers + record: + type: registry + version: 4.0.0 + integrity: sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg= + dependencies: + - functions + - prelude + - unsafe-coerce + refs: + type: registry + version: 6.0.0 + integrity: sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s= + dependencies: + - effect + - prelude + safe-coerce: + type: registry + version: 2.0.0 + integrity: sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU= + dependencies: + - unsafe-coerce + spec: + type: registry + version: 7.6.0 + integrity: sha256-+merGdQbL9zWONbnt8S8J9afGJ59MQqGtS0qSd3yu4I= + dependencies: + - aff + - ansi + - arrays + - avar + - bifunctors + - control + - datetime + - effect + - either + - exceptions + - foldable-traversable + - fork + - identity + - integers + - lists + - maybe + - newtype + - now + - ordered-collections + - parallel + - pipes + - prelude + - refs + - strings + - tailrec + - transformers + - tuples + spec-quickcheck: + type: registry + version: 5.0.0 + integrity: sha256-iE0iThqZCuDGe3pwg5RvqcL8E5cRQ4txDuloCclOsCs= + dependencies: + - aff + - prelude + - quickcheck + - random + - spec + st: + type: registry + version: 6.2.0 + integrity: sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY= + dependencies: + - partial + - prelude + - tailrec + - unsafe-coerce + strings: + type: registry + version: 6.0.1 + integrity: sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k= + dependencies: + - arrays + - control + - either + - enums + - foldable-traversable + - gen + - integers + - maybe + - newtype + - nonempty + - partial + - prelude + - tailrec + - tuples + - unfoldable + - unsafe-coerce + tailrec: + type: registry + version: 6.1.0 + integrity: sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk= + dependencies: + - bifunctors + - effect + - either + - identity + - maybe + - partial + - prelude + - refs + test-unit: + type: registry + version: 17.0.0 + integrity: sha256-aITJ2KngFFjASmG0JjnjybaKWl9dn7Hf2B3Wk4engNs= + dependencies: + - aff + - avar + - effect + - either + - free + - js-timers + - lists + - prelude + - quickcheck + - strings + transformers: + type: registry + version: 6.0.0 + integrity: sha256-Pzw40HjthX77tdPAYzjx43LK3X5Bb7ZspYAp27wksFA= + dependencies: + - control + - distributive + - effect + - either + - exceptions + - foldable-traversable + - identity + - lazy + - maybe + - newtype + - prelude + - tailrec + - tuples + - unfoldable + tuples: + type: registry + version: 7.0.0 + integrity: sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M= + dependencies: + - control + - invariant + - prelude + type-equality: + type: registry + version: 4.0.1 + integrity: sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw= + dependencies: [] + typelevel-prelude: + type: registry + version: 7.0.0 + integrity: sha256-uFF2ph+vHcQpfPuPf2a3ukJDFmLhApmkpTMviHIWgJM= + dependencies: + - prelude + - type-equality + unfoldable: + type: registry + version: 6.0.0 + integrity: sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg= + dependencies: + - foldable-traversable + - maybe + - partial + - prelude + - tuples + unsafe-coerce: + type: registry + version: 6.0.0 + integrity: sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0= + dependencies: [] + web-dom: + type: registry + version: 6.0.0 + integrity: sha256-1kSKWFDI4LupdmpjK01b1MMxDFW7jvatEgPgVmCmSBQ= + dependencies: + - web-events + web-events: + type: registry + version: 4.0.0 + integrity: sha256-YDt8b6u1tzGtnWyNRodne57iO8FNSGPaTCVzBUyUn4k= + dependencies: + - datetime + - enums + - foreign + - nullable + web-file: + type: registry + version: 4.0.0 + integrity: sha256-1h5jPBkvjY71jLEdwVadXCx86/2inNoMBO//Rd3eCSU= + dependencies: + - foreign + - media-types + - web-dom + web-html: + type: registry + version: 4.1.0 + integrity: sha256-ByqS/h1/yG+hjCOnOQp7L1QpIWzQENNKB1kaHtpEhlE= + dependencies: + - js-date + - web-dom + - web-file + - web-storage + web-storage: + type: registry + version: 5.0.0 + integrity: sha256-q+6lxcnfWxus0/nDeFVtF1V+tLehZvvXQ0cduYPLksY= + dependencies: + - nullable + - web-events + web-xhr: + type: registry + version: 5.0.1 + integrity: sha256-3dbIPVG66S+hPrgEVnpD78hrGjE7qlBbsReWOz89Ios= + dependencies: + - arraybuffer-types + - datetime + - http-methods + - web-dom + - web-file + - web-html diff --git a/example/spago.yaml b/example/spago.yaml new file mode 100644 index 00000000..80e706e9 --- /dev/null +++ b/example/spago.yaml @@ -0,0 +1,24 @@ +package: + name: example + dependencies: + - aff + - affjax + - affjax-web + - argonaut + - argonaut-aeson-generic + - argonaut-codecs + - argonaut-generic + - console + - control + - effect + - either + - foldable-traversable + - foreign-generic + - foreign-object + - json-helpers + - maybe + - newtype + - ordered-collections + - prelude + - profunctor-lenses + - tuples diff --git a/example/src/Argonaut/Types.purs b/example/src/Argonaut/Types.purs new file mode 100644 index 00000000..33f5837c --- /dev/null +++ b/example/src/Argonaut/Types.purs @@ -0,0 +1,316 @@ +-- File auto generated by purescript-bridge! -- +module Argonaut.Types where + +import Prelude + +import Control.Lazy (defer) +import Data.Argonaut.Aeson.Decode.Generic (genericDecodeAeson) +import Data.Argonaut.Aeson.Encode.Generic (genericEncodeAeson) +import Data.Argonaut.Aeson.Options (defaultOptions) as Argonaut +import Data.Argonaut.Decode (class DecodeJson) +import Data.Argonaut.Decode.Class (class DecodeJson, class DecodeJsonField, decodeJson) +import Data.Argonaut.Decode.Class as Argonaut +import Data.Argonaut.Encode (class EncodeJson) +import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson) +import Data.Argonaut.Encode.Class as Argonaut +import Data.Either (Either) +import Data.Generic.Rep (class Generic) +import Data.Lens (Iso', Lens', Prism', iso, lens, prism') +import Data.Lens.Iso.Newtype (_Newtype) +import Data.Lens.Record (prop) +import Data.Maybe (Maybe(..)) +import Data.Newtype (class Newtype) +import Data.Show.Generic (genericShow) +import Data.Tuple (Tuple) +import Foreign.Object (Object) +import Type.Proxy (Proxy(Proxy)) + +newtype Baz = Baz { _bazMessage :: String } + +instance EncodeJson Baz where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance DecodeJson Baz where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance Eq Baz + +derive instance Ord Baz + + + +instance Show Baz where + show a = genericShow a + +derive instance Generic Baz _ + +derive instance Newtype Baz _ + +-------------------------------------------------------------------------------- + +_Baz :: Iso' Baz {_bazMessage :: String} +_Baz = _Newtype + +bazMessage :: Lens' Baz String +bazMessage = _Newtype <<< prop (Proxy :: _"_bazMessage") + +-------------------------------------------------------------------------------- + +newtype ID a = ID a + +instance (EncodeJson a) => EncodeJson (ID a) where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance (DecodeJson a, DecodeJsonField a) => DecodeJson (ID a) where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance (Eq a) => Eq (ID a) + +derive instance (Ord a) => Ord (ID a) + + + +instance (Show a) => Show (ID a) where + show a = genericShow a + +derive instance Generic (ID a) _ + +derive instance Newtype (ID a) _ + +-------------------------------------------------------------------------------- + +_ID :: forall a. Iso' (ID a) a +_ID = _Newtype + +-------------------------------------------------------------------------------- + +newtype ID2 a = ID2 { getID :: Int } + +instance (EncodeJson a) => EncodeJson (ID2 a) where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance (DecodeJson a, DecodeJsonField a) => DecodeJson (ID2 a) where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance (Eq a) => Eq (ID2 a) + +derive instance (Ord a) => Ord (ID2 a) + + + +instance Show (ID2 a) where + show a = genericShow a + +derive instance Generic (ID2 a) _ + +derive instance Newtype (ID2 a) _ + +-------------------------------------------------------------------------------- + +_ID2 :: forall a. Iso' (ID2 a) {getID :: Int} +_ID2 = _Newtype + +-------------------------------------------------------------------------------- + +newtype Foo = Foo + { _fooMessage :: String + , _fooE :: Either String Int + , _fooNumber :: Int + , _fooList :: Array Int + , _fooMap :: Object Int + , _fooBaz :: Baz + , _fooTestSum :: TestSum + , _fooTestData :: TestData + } + +instance EncodeJson Foo where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance DecodeJson Foo where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance Eq Foo + +derive instance Ord Foo + + + +instance Show Foo where + show a = genericShow a + +derive instance Generic Foo _ + +derive instance Newtype Foo _ + +-------------------------------------------------------------------------------- + +_Foo :: Iso' Foo {_fooMessage :: String, _fooE :: Either String Int, _fooNumber :: Int, _fooList :: Array Int, _fooMap :: Object Int, _fooBaz :: Baz, _fooTestSum :: TestSum, _fooTestData :: TestData} +_Foo = _Newtype + +fooMessage :: Lens' Foo String +fooMessage = _Newtype <<< prop (Proxy :: _"_fooMessage") + +fooE :: Lens' Foo (Either String Int) +fooE = _Newtype <<< prop (Proxy :: _"_fooE") + +fooNumber :: Lens' Foo Int +fooNumber = _Newtype <<< prop (Proxy :: _"_fooNumber") + +fooList :: Lens' Foo (Array Int) +fooList = _Newtype <<< prop (Proxy :: _"_fooList") + +fooMap :: Lens' Foo (Object Int) +fooMap = _Newtype <<< prop (Proxy :: _"_fooMap") + +fooBaz :: Lens' Foo Baz +fooBaz = _Newtype <<< prop (Proxy :: _"_fooBaz") + +fooTestSum :: Lens' Foo TestSum +fooTestSum = _Newtype <<< prop (Proxy :: _"_fooTestSum") + +fooTestData :: Lens' Foo TestData +fooTestData = _Newtype <<< prop (Proxy :: _"_fooTestData") + +-------------------------------------------------------------------------------- + +newtype FooList = FooList (Array Int) + +instance EncodeJson FooList where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance DecodeJson FooList where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance Eq FooList + +derive instance Ord FooList + + + +instance Show FooList where + show a = genericShow a + +derive instance Generic FooList _ + +derive instance Newtype FooList _ + +-------------------------------------------------------------------------------- + +_FooList :: Iso' FooList (Array Int) +_FooList = _Newtype + +-------------------------------------------------------------------------------- + +newtype Bar a = Bar a + +instance (EncodeJson a) => EncodeJson (Bar a) where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance (DecodeJson a, DecodeJsonField a) => DecodeJson (Bar a) where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance (Eq a) => Eq (Bar a) + +derive instance (Ord a) => Ord (Bar a) + + + +instance (Show a) => Show (Bar a) where + show a = genericShow a + +derive instance Generic (Bar a) _ + +derive instance Newtype (Bar a) _ + +-------------------------------------------------------------------------------- + +_Bar :: forall a. Iso' (Bar a) a +_Bar = _Newtype + +-------------------------------------------------------------------------------- + +data TestSum + = Nullary + | Bool Boolean + | Int Int + | Number Number + | FooTuple (Tuple Int Int) + +instance EncodeJson TestSum where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance DecodeJson TestSum where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance Eq TestSum + +derive instance Ord TestSum + + + +instance Show TestSum where + show a = genericShow a + +derive instance Generic TestSum _ + +-------------------------------------------------------------------------------- + +_Nullary :: Prism' TestSum Unit +_Nullary = prism' (const Nullary) case _ of + Nullary -> Just unit + _ -> Nothing + +_Bool :: Prism' TestSum Boolean +_Bool = prism' Bool case _ of + (Bool a) -> Just a + _ -> Nothing + +_Int :: Prism' TestSum Int +_Int = prism' Int case _ of + (Int a) -> Just a + _ -> Nothing + +_Number :: Prism' TestSum Number +_Number = prism' Number case _ of + (Number a) -> Just a + _ -> Nothing + +_FooTuple :: Prism' TestSum (Tuple Int Int) +_FooTuple = prism' FooTuple case _ of + (FooTuple a) -> Just a + _ -> Nothing + +-------------------------------------------------------------------------------- + +data TestData + = TMaybe (Maybe TestSum) + | TEither String + +instance EncodeJson TestData where + encodeJson = defer \_ -> genericEncodeAeson Argonaut.defaultOptions + +instance DecodeJson TestData where + decodeJson = defer \_ -> genericDecodeAeson Argonaut.defaultOptions + +derive instance Eq TestData + +derive instance Ord TestData + + + +instance Show TestData where + show a = genericShow a + +derive instance Generic TestData _ + +-------------------------------------------------------------------------------- + +_TMaybe :: Prism' TestData (Maybe TestSum) +_TMaybe = prism' TMaybe case _ of + (TMaybe a) -> Just a + _ -> Nothing + +_TEither :: Prism' TestData String +_TEither = prism' TEither case _ of + (TEither a) -> Just a + _ -> Nothing diff --git a/example/src/ArgonautTypes.hs b/example/src/ArgonautTypes.hs new file mode 100644 index 00000000..4c4d0bb5 --- /dev/null +++ b/example/src/ArgonautTypes.hs @@ -0,0 +1,24 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE TypeApplications #-} + +module ArgonautTypes where + +import Language.PureScript.Bridge (Language (Haskell), + argonautAesonGeneric, mkSumType) +import Language.PureScript.Bridge.SumType (SumType) +import Language.PureScript.Bridge.TypeParameters (A) +import Types + +myArgonautTypes :: [SumType 'Haskell] +myArgonautTypes = + [ argonautAesonGeneric . additionalInstances $ mkSumType @Baz + , argonautAesonGeneric . additionalInstances $ mkSumType @(ID A) + , argonautAesonGeneric . additionalInstances $ mkSumType @(ID2 A) + , argonautAesonGeneric . additionalInstances $ mkSumType @Foo + , argonautAesonGeneric . additionalInstances $ mkSumType @FooList + , argonautAesonGeneric . additionalInstances $ mkSumType @(Bar A) + , argonautAesonGeneric . additionalInstances $ mkSumType @TestSum + , argonautAesonGeneric . additionalInstances $ mkSumType @TestData + ] diff --git a/example/src/JsonHelpers/Types.purs b/example/src/JsonHelpers/Types.purs new file mode 100644 index 00000000..8c7147f8 --- /dev/null +++ b/example/src/JsonHelpers/Types.purs @@ -0,0 +1,360 @@ +-- File auto generated by purescript-bridge! -- +module JsonHelpers.Types where + +import Prelude + +import Control.Lazy (defer) +import Data.Argonaut (encodeJson, jsonNull) +import Data.Argonaut.Aeson.Decode.Generic (genericDecodeAeson) +import Data.Argonaut.Aeson.Encode.Generic (genericEncodeAeson) +import Data.Argonaut.Aeson.Options (defaultOptions) as Argonaut +import Data.Argonaut.Decode.Aeson (($\>), (*\>), (\>)) +import Data.Argonaut.Decode.Aeson as D +import Data.Argonaut.Decode.Class (class DecodeJson, class DecodeJsonField, decodeJson) +import Data.Argonaut.Decode.Class as Argonaut +import Data.Argonaut.Encode.Aeson ((>$<), (>/\<)) +import Data.Argonaut.Encode.Aeson as E +import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson) +import Data.Argonaut.Encode.Class as Argonaut +import Data.Either (Either) +import Data.Generic.Rep (class Generic) +import Data.Lens (Iso', Lens', Prism', iso, lens, prism') +import Data.Lens.Iso.Newtype (_Newtype) +import Data.Lens.Record (prop) +import Data.Map +import Data.Map as Map +import Data.Maybe (Maybe(..)) +import Data.Newtype (class Newtype, unwrap) +import Data.Show.Generic (genericShow) +import Data.Tuple (Tuple) +import Data.Tuple.Nested ((/\)) +import Foreign.Object (Object) +import Type.Proxy (Proxy(Proxy)) + +newtype Baz = Baz { _bazMessage :: String } + +instance EncodeJson Baz where + encodeJson = defer \_ -> E.encode $ unwrap >$< (E.record + { _bazMessage: E.value :: _ String }) + +instance DecodeJson Baz where + decodeJson = defer \_ -> D.decode $ (Baz <$> D.record "Baz" { _bazMessage: D.value :: _ String }) + +derive instance Eq Baz + +derive instance Ord Baz + + + +instance Show Baz where + show a = genericShow a + +derive instance Generic Baz _ + +derive instance Newtype Baz _ + +-------------------------------------------------------------------------------- + +_Baz :: Iso' Baz {_bazMessage :: String} +_Baz = _Newtype + +bazMessage :: Lens' Baz String +bazMessage = _Newtype <<< prop (Proxy :: _"_bazMessage") + +-------------------------------------------------------------------------------- + +newtype ID a = ID a + +instance (EncodeJson a) => EncodeJson (ID a) where + encodeJson = defer \_ -> E.encode $ unwrap >$< E.value + +instance (DecodeJson a, DecodeJsonField a) => DecodeJson (ID a) where + decodeJson = defer \_ -> D.decode $ (ID <$> D.value) + +derive instance (Eq a) => Eq (ID a) + +derive instance (Ord a) => Ord (ID a) + + + +instance (Show a) => Show (ID a) where + show a = genericShow a + +derive instance Generic (ID a) _ + +derive instance Newtype (ID a) _ + +-------------------------------------------------------------------------------- + +_ID :: forall a. Iso' (ID a) a +_ID = _Newtype + +-------------------------------------------------------------------------------- + +newtype ID2 a = ID2 { getID :: Int } + +instance (EncodeJson a) => EncodeJson (ID2 a) where + encodeJson = defer \_ -> E.encode $ unwrap >$< (E.record + { getID: E.value :: _ Int }) + +instance (DecodeJson a, DecodeJsonField a) => DecodeJson (ID2 a) where + decodeJson = defer \_ -> D.decode $ (ID2 <$> D.record "ID2" { getID: D.value :: _ Int }) + +derive instance (Eq a) => Eq (ID2 a) + +derive instance (Ord a) => Ord (ID2 a) + + + +instance Show (ID2 a) where + show a = genericShow a + +derive instance Generic (ID2 a) _ + +derive instance Newtype (ID2 a) _ + +-------------------------------------------------------------------------------- + +_ID2 :: forall a. Iso' (ID2 a) {getID :: Int} +_ID2 = _Newtype + +-------------------------------------------------------------------------------- + +newtype Foo = Foo + { _fooMessage :: String + , _fooE :: Either String Int + , _fooNumber :: Int + , _fooList :: Array Int + , _fooMap :: Object Int + , _fooBaz :: Baz + , _fooTestSum :: TestSum + , _fooTestData :: TestData + } + +instance EncodeJson Foo where + encodeJson = defer \_ -> E.encode $ unwrap >$< (E.record + { _fooMessage: E.value :: _ String + , _fooE: (E.either E.value E.value) :: _ (Either String Int) + , _fooNumber: E.value :: _ Int + , _fooList: E.value :: _ (Array Int) + , _fooMap: E.value :: _ (Object Int) + , _fooBaz: E.value :: _ Baz + , _fooTestSum: E.value :: _ TestSum + , _fooTestData: E.value :: _ TestData + }) + +instance DecodeJson Foo where + decodeJson = defer \_ -> D.decode $ (Foo <$> D.record "Foo" + { _fooMessage: D.value :: _ String + , _fooE: (D.either D.value D.value) :: _ (Either String Int) + , _fooNumber: D.value :: _ Int + , _fooList: D.value :: _ (Array Int) + , _fooMap: D.value :: _ (Object Int) + , _fooBaz: D.value :: _ Baz + , _fooTestSum: D.value :: _ TestSum + , _fooTestData: D.value :: _ TestData + }) + +derive instance Eq Foo + +derive instance Ord Foo + + + +instance Show Foo where + show a = genericShow a + +derive instance Generic Foo _ + +derive instance Newtype Foo _ + +-------------------------------------------------------------------------------- + +_Foo :: Iso' Foo {_fooMessage :: String, _fooE :: Either String Int, _fooNumber :: Int, _fooList :: Array Int, _fooMap :: Object Int, _fooBaz :: Baz, _fooTestSum :: TestSum, _fooTestData :: TestData} +_Foo = _Newtype + +fooMessage :: Lens' Foo String +fooMessage = _Newtype <<< prop (Proxy :: _"_fooMessage") + +fooE :: Lens' Foo (Either String Int) +fooE = _Newtype <<< prop (Proxy :: _"_fooE") + +fooNumber :: Lens' Foo Int +fooNumber = _Newtype <<< prop (Proxy :: _"_fooNumber") + +fooList :: Lens' Foo (Array Int) +fooList = _Newtype <<< prop (Proxy :: _"_fooList") + +fooMap :: Lens' Foo (Object Int) +fooMap = _Newtype <<< prop (Proxy :: _"_fooMap") + +fooBaz :: Lens' Foo Baz +fooBaz = _Newtype <<< prop (Proxy :: _"_fooBaz") + +fooTestSum :: Lens' Foo TestSum +fooTestSum = _Newtype <<< prop (Proxy :: _"_fooTestSum") + +fooTestData :: Lens' Foo TestData +fooTestData = _Newtype <<< prop (Proxy :: _"_fooTestData") + +-------------------------------------------------------------------------------- + +newtype FooList = FooList (Array Int) + +instance EncodeJson FooList where + encodeJson = defer \_ -> E.encode $ unwrap >$< E.value + +instance DecodeJson FooList where + decodeJson = defer \_ -> D.decode $ (FooList <$> D.value) + +derive instance Eq FooList + +derive instance Ord FooList + + + +instance Show FooList where + show a = genericShow a + +derive instance Generic FooList _ + +derive instance Newtype FooList _ + +-------------------------------------------------------------------------------- + +_FooList :: Iso' FooList (Array Int) +_FooList = _Newtype + +-------------------------------------------------------------------------------- + +newtype Bar a = Bar a + +instance (EncodeJson a) => EncodeJson (Bar a) where + encodeJson = defer \_ -> E.encode $ unwrap >$< E.value + +instance (DecodeJson a, DecodeJsonField a) => DecodeJson (Bar a) where + decodeJson = defer \_ -> D.decode $ (Bar <$> D.value) + +derive instance (Eq a) => Eq (Bar a) + +derive instance (Ord a) => Ord (Bar a) + + + +instance (Show a) => Show (Bar a) where + show a = genericShow a + +derive instance Generic (Bar a) _ + +derive instance Newtype (Bar a) _ + +-------------------------------------------------------------------------------- + +_Bar :: forall a. Iso' (Bar a) a +_Bar = _Newtype + +-------------------------------------------------------------------------------- + +data TestSum + = Nullary + | Bool Boolean + | Int Int + | Number Number + | FooTuple (Tuple Int Int) + +instance EncodeJson TestSum where + encodeJson = defer \_ -> case _ of + Nullary -> encodeJson { tag: "Nullary", contents: jsonNull } + Bool a -> E.encodeTagged "Bool" a E.value + Int a -> E.encodeTagged "Int" a E.value + Number a -> E.encodeTagged "Number" a E.value + FooTuple a -> E.encodeTagged "FooTuple" a (E.tuple (E.value >/\< E.value)) + +instance DecodeJson TestSum where + decodeJson = defer \_ -> D.decode + $ D.sumType "TestSum" $ Map.fromFoldable + [ "Nullary" /\ pure Nullary + , "Bool" /\ D.content (Bool <$> D.value) + , "Int" /\ D.content (Int <$> D.value) + , "Number" /\ D.content (Number <$> D.value) + , "FooTuple" /\ D.content (FooTuple <$> (D.tuple (D.value \> D.value))) + ] + +derive instance Eq TestSum + +derive instance Ord TestSum + + + +instance Show TestSum where + show a = genericShow a + +derive instance Generic TestSum _ + +-------------------------------------------------------------------------------- + +_Nullary :: Prism' TestSum Unit +_Nullary = prism' (const Nullary) case _ of + Nullary -> Just unit + _ -> Nothing + +_Bool :: Prism' TestSum Boolean +_Bool = prism' Bool case _ of + (Bool a) -> Just a + _ -> Nothing + +_Int :: Prism' TestSum Int +_Int = prism' Int case _ of + (Int a) -> Just a + _ -> Nothing + +_Number :: Prism' TestSum Number +_Number = prism' Number case _ of + (Number a) -> Just a + _ -> Nothing + +_FooTuple :: Prism' TestSum (Tuple Int Int) +_FooTuple = prism' FooTuple case _ of + (FooTuple a) -> Just a + _ -> Nothing + +-------------------------------------------------------------------------------- + +data TestData + = TMaybe (Maybe TestSum) + | TEither String + +instance EncodeJson TestData where + encodeJson = defer \_ -> case _ of + TMaybe a -> E.encodeTagged "TMaybe" a (E.maybe E.value) + TEither a -> E.encodeTagged "TEither" a E.value + +instance DecodeJson TestData where + decodeJson = defer \_ -> D.decode + $ D.sumType "TestData" $ Map.fromFoldable + [ "TMaybe" /\ D.content (TMaybe <$> (D.maybe D.value)) + , "TEither" /\ D.content (TEither <$> D.value) + ] + +derive instance Eq TestData + +derive instance Ord TestData + + + +instance Show TestData where + show a = genericShow a + +derive instance Generic TestData _ + +-------------------------------------------------------------------------------- + +_TMaybe :: Prism' TestData (Maybe TestSum) +_TMaybe = prism' TMaybe case _ of + (TMaybe a) -> Just a + _ -> Nothing + +_TEither :: Prism' TestData String +_TEither = prism' TEither case _ of + (TEither a) -> Just a + _ -> Nothing diff --git a/example/src/JsonHelpersTypes.hs b/example/src/JsonHelpersTypes.hs new file mode 100644 index 00000000..c6badb2f --- /dev/null +++ b/example/src/JsonHelpersTypes.hs @@ -0,0 +1,24 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE TypeApplications #-} + +module JsonHelpersTypes where + +import Language.PureScript.Bridge (Language (Haskell), jsonHelpers, + mkSumType, order) +import Language.PureScript.Bridge.SumType (SumType) +import Language.PureScript.Bridge.TypeParameters (A) +import Types + +myJsonHelpersTypes :: [SumType 'Haskell] +myJsonHelpersTypes = + [ jsonHelpers . additionalInstances $ mkSumType @Baz + , jsonHelpers . additionalInstances $ mkSumType @(ID A) + , jsonHelpers . additionalInstances $ mkSumType @(ID2 A) + , jsonHelpers . additionalInstances $ mkSumType @Foo + , jsonHelpers . additionalInstances $ mkSumType @FooList + , jsonHelpers . additionalInstances $ mkSumType @(Bar A) + , jsonHelpers . additionalInstances $ mkSumType @TestSum + , jsonHelpers . additionalInstances $ mkSumType @TestData + ] diff --git a/example/src/Main.purs b/example/src/Main.purs index 1f1d71f0..532ab6c9 100644 --- a/example/src/Main.purs +++ b/example/src/Main.purs @@ -1,60 +1,94 @@ -module Main where +module ExampleMain where import Prelude -import Data.Argonaut.Decode.Error (JsonDecodeError, printJsonDecodeError) +import Affjax.RequestBody as RequestBody +import Affjax.ResponseFormat (json) +import Affjax.Web (get, post_) import Data.Argonaut.Aeson.Decode.Generic (genericDecodeAeson) import Data.Argonaut.Aeson.Encode.Generic (genericEncodeAeson) +import Data.Argonaut.Decode (JsonDecodeError, decodeJson, parseJson, printJsonDecodeError) +import Data.Argonaut.Encode (encodeJson) import Data.Argonaut.Aeson.Options (defaultOptions) +import Data.Argonaut.Decode.Error (JsonDecodeError, printJsonDecodeError) import Data.Either (Either(Left, Right)) -import Data.Maybe (Maybe(Just)) -import Data.Lens (over, view, set) import Data.Foldable (length) +import Data.Lens (over, view, set) +import Data.Maybe (Maybe(Just)) import Data.Traversable (for_) import Effect (Effect) -import Effect.Console (log) -import Effect.Class (liftEffect) import Effect.Aff (launchAff_) -import Affjax.Web (get, post_) -import Affjax.ResponseFormat (json) -import Affjax.RequestBody as RequestBody -import Types (Foo, fooMessage, fooNumber, fooList) -import Data.Argonaut.Decode.Error (JsonDecodeError) -import Data.Argonaut.Decode.Generic (genericDecodeJson) -import Data.Argonaut.Encode.Generic (genericEncodeJson) -import Types (Foo, fooMessage, fooNumber, fooList, fooMap) -import Data.Map as Map - +import Effect.Class (liftEffect) +import Effect.Console (log) +import Foreign.Object (empty) import Foreign.Object as Object +import Argonaut.Types (Baz(Baz), Foo(Foo), TestData(..), TestSum(..), fooMessage, fooNumber, fooList, fooMap, fooTestSum, fooTestData) + +testFoo = Foo + { _fooMessage: "foo" + , _fooE: Left "foo" + , _fooNumber: 1 + , _fooList: [1,2,3] + , _fooMap: empty + , _fooBaz: Baz { _bazMessage: "baz" } + , _fooTestSum: Nullary + , _fooTestData: TEither "foo" + } main :: Effect Unit -main = log "Hello, Purescript!" *> launchAff_ do - -- "Foo" tests untagged JSON, i.e.: - -- { "_fooMessage": "Hello", "_fooNumber": 123 } +main = log "Hello, PureScript!" *> launchAff_ do + -- request a Foo; decode with ArgonautAesonGeneric + fooResponse <- get json "/foo" + for_ fooResponse \fooPayload -> do + liftEffect $ log $ "Decode and Encode with ArgonautAesoGeneric" + let + eArgonautDecodedFoo :: Either JsonDecodeError Foo + eArgonautDecodedFoo = genericDecodeAeson defaultOptions fooPayload.body + case eArgonautDecodedFoo of + Left e -> liftEffect $ log $ "Error decoding Foo: " <> printJsonDecodeError e + Right _ -> pure unit + for_ eArgonautDecodedFoo \argonautDecodedFoo -> do + liftEffect do + log $ "Foo message: " <> (view fooMessage argonautDecodedFoo) + log $ "Foo number: " <> (show $ view fooNumber argonautDecodedFoo) + log $ "Foo list length: " <> (show (length $ view fooList argonautDecodedFoo :: Int)) + log $ "Foo map size: " <> (show (Object.size $ view fooMap argonautDecodedFoo :: Int)) + log $ "Foo test sum: " <> show (view fooTestSum argonautDecodedFoo) + log $ "Foo test data: " <> show (view fooTestData argonautDecodedFoo) + let + -- modify the Foo received and send it back + modifiedFoo = set fooMessage "Hello from ArgonautAesonGeneric" + $ over fooNumber (_+1) + $ over fooList (\l -> l <> l) + $ over fooMap (\o -> Object.insert "abc" 123 o) + $ argonautDecodedFoo + response = Just $ RequestBody.json $ genericEncodeAeson defaultOptions modifiedFoo + post_ "/foo" response - -- request a Foo + -- request a Foo; decode with JsonHelpers fooResponse <- get json "/foo" for_ fooResponse \fooPayload -> do + liftEffect $ log $ "Decode and Encode with JsonHelpers" let - efoo :: Either JsonDecodeError Foo - efoo = genericDecodeAeson defaultOptions fooPayload.body - case efoo of + eJsonHelpersDecodedFoo :: Either JsonDecodeError Foo + eJsonHelpersDecodedFoo = decodeJson fooPayload.body + case eJsonHelpersDecodedFoo of Left e -> liftEffect $ log $ "Error decoding Foo: " <> printJsonDecodeError e Right _ -> pure unit - for_ efoo \foo -> do + for_ eJsonHelpersDecodedFoo \jsonHelpersFoo -> do liftEffect do - log $ "Foo message: " <> (view fooMessage foo) - <> "\t Foo number: " <> (show $ view fooNumber foo) - <> "\t Foo list length: " - <> (show (length $ view fooList foo :: Int)) - <> "\t Foo map size: " - <> (show (Object.size $ view fooMap foo :: Int)) + log $ "Foo message: " <> (view fooMessage jsonHelpersFoo) + log $ "Foo number: " <> (show $ view fooNumber jsonHelpersFoo) + log $ "Foo list length: " <> (show (length $ view fooList jsonHelpersFoo :: Int)) + log $ "Foo map size: " <> (show (Object.size $ view fooMap jsonHelpersFoo :: Int)) + log $ "Foo test sum: " <> show (view fooTestSum jsonHelpersFoo) + log $ "Foo test data: " <> show (view fooTestData jsonHelpersFoo) let -- modify the Foo received and send it back - foo' = set fooMessage "Hola" + modifiedFoo = set fooMessage "Hello from JsonHelpers" $ over fooNumber (_+1) $ over fooList (\l -> l <> l) $ over fooMap (\o -> Object.insert "abc" 123 o) - $ foo - response = Just $ RequestBody.json $ genericEncodeAeson defaultOptions foo' + $ jsonHelpersFoo + response = Just $ RequestBody.json $ encodeJson modifiedFoo post_ "/foo" response diff --git a/example/src/MyLib.hs b/example/src/MyLib.hs index 7efc91db..d74da2dc 100644 --- a/example/src/MyLib.hs +++ b/example/src/MyLib.hs @@ -1,5 +1,6 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeOperators #-} module MyLib (main) where @@ -8,43 +9,65 @@ import Prelude import Control.Lens (view) import Control.Monad.IO.Class (liftIO) -import Data.Aeson +import Data.Aeson () import qualified Data.Aeson.Encode.Pretty as AP import qualified Data.ByteString.Lazy.Char8 as Char8 import qualified Data.Map.Lazy as Map import Data.Text (pack, unpack) -import GHC.Generics -import GHC.TypeLits -import Network.Wai.Handler.Warp -import Servant +import qualified Data.Text as T +import GHC.Generics () +import GHC.TypeLits () +import Network.Wai.Handler.Warp (run) +import Servant (Get, JSON, NoContent (..), Post, Proxy (..), Raw, + ReqBody, Server, serve, serveDirectoryWebApp, + type (:<|>) (..), type (:>)) import System.Environment (lookupEnv) +import Test.QuickCheck (Arbitrary (..), chooseEnum, generate, oneof, + resize, sized) -import Types (Baz (Baz), Foo (Foo), fooList, fooMap, fooMessage, - fooNumber) +import qualified Types +import Types (Baz (Baz), Foo (Foo), TestData (..), TestSum (..), + fooList, fooMap, fooMessage, fooNumber) type FooServer = "foo" :> (Get '[JSON] Foo :<|> ReqBody '[JSON] Foo :> Post '[JSON] NoContent ) -foo :: Foo -foo = Foo - (pack "Hello") - 123 - [10..20] - (Map.fromList [(pack "foo", 2), (pack "bar", 3), (pack "baz", 3)]) - (Baz $ pack "hello") +foo :: IO Foo +foo = do + testEither :: Either T.Text Int <- generate arbitrary + testData :: TestData <- generate arbitrary + testSum :: TestSum <- generate arbitrary + return $ Foo + (pack "Hello") + testEither + 123 + [10..13] + (Map.fromList [(pack "foo", 2), (pack "bar", 3), (pack "baz", 3)]) + (Baz $ pack "hello") + testSum + testData fooServer :: Server FooServer fooServer = getFoo :<|> postFoo where - getFoo = return foo + getFoo = do + fooValue <- liftIO foo + liftIO $ putStrLn "-----------------" + liftIO $ putStrLn "Foo:" + liftIO $ putStrLn $ show fooValue + liftIO $ putStrLn "Serving JSON:" + liftIO $ Char8.putStrLn $ AP.encodePretty fooValue + return fooValue + postFoo foo = do let logMsg = "Foo message: " <> (unpack $ view fooMessage foo) <> "\t Foo number: " <> (show (view fooNumber foo)) <> "\t Foo list length: " <> (show . length $ view fooList foo) <> "\t Foo Map length: " <> (show . length $ view fooMap foo) + liftIO . putStrLn $ "Received from client:" liftIO . putStrLn $ logMsg return NoContent @@ -58,7 +81,5 @@ api = Proxy main :: IO () main = do - putStrLn "Serving Foo:" - Char8.putStrLn $ AP.encodePretty foo - + putStrLn "Running at port 8080..." run 8080 . serve api $ fooServer :<|> staticServer diff --git a/example/src/Types.hs b/example/src/Types.hs index 75994a49..a35e68a2 100644 --- a/example/src/Types.hs +++ b/example/src/Types.hs @@ -1,62 +1,138 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE KindSignatures #-} -{-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeOperators #-} module Types where import Control.Lens.TH (makeLenses) -import Data.Aeson +import Data.Aeson (FromJSON, SumEncoding (..), ToJSON (toEncoding), + defaultOptions, defaultTaggedObject, + genericToEncoding, sumEncoding, + tagSingleConstructors, unwrapUnaryRecords) import qualified Data.Map.Lazy as Map -import Data.Proxy -import Data.Text -import Data.Typeable -import GHC.Generics -import Language.PureScript.Bridge -import Language.PureScript.Bridge.PSTypes +import GHC.Types (List) +import Data.Proxy () +import Data.Text (Text, pack) +import Data.Typeable (Typeable) +import GHC.Generics (Generic) +import Language.PureScript.Bridge (BridgePart, Language (Haskell), + argonautAesonGeneric, + defaultBridge, genericShow, order, + jsonHelpers, lenses, mkSumType) +import Language.PureScript.Bridge.PSTypes () +import Language.PureScript.Bridge.SumType (SumType) import Language.PureScript.Bridge.TypeParameters (A) +import Test.QuickCheck (Arbitrary (..), chooseEnum, oneof, resize, + sized) data Baz = Baz { _bazMessage :: Text } - deriving (FromJSON, Generic, ToJSON) + deriving (FromJSON, Generic, Show) + +instance ToJSON Baz where + toEncoding = genericToEncoding + ( + defaultOptions + { tagSingleConstructors = True + , unwrapUnaryRecords = True + } + ) makeLenses ''Baz -bazProxy :: Proxy Baz -bazProxy = Proxy +-- https://github.com/eskimor/purescript-bridge/pull/89#issuecomment-1890994859 +data ID a = ID a + deriving (Generic, Show) + +deriving instance Eq a => Eq (ID a) +deriving instance Ord a => Ord (ID a) + +newtype ID2 a + = ID2 { getID :: Int } + deriving (Generic, Show) + +deriving instance Eq a => Eq (ID2 a) +deriving instance Ord a => Ord (ID2 a) + +data TestSum + = Nullary + | Bool Bool + | Int Int + | Number Double + | FooTuple (Int, Int) + deriving (Eq, FromJSON, Generic, Ord, Show, ToJSON) + +instance Arbitrary Text where + arbitrary = pure $ pack "foooo" + +instance Arbitrary TestSum where + arbitrary = + oneof + [ pure Nullary + , Bool <$> arbitrary + , Int <$> arbitrary + , Number <$> arbitrary + ] + +data TestData + = TMaybe (Maybe TestSum) + | TEither Text -- (Either Int Text) -- (Either (Maybe Int) (Maybe Bool)) + deriving (Eq, FromJSON, Generic, Ord, Show, ToJSON) + +instance Arbitrary TestData where + arbitrary = + oneof + [ -- Maybe <$> arbitrary + -- , + TEither <$> arbitrary + ] + data Foo = Foo - { _fooMessage :: Text - , _fooNumber :: Int - , _fooList :: [Int] - , _fooMap :: Map.Map Text Int - , _fooBaz :: Baz + { _fooMessage :: Text + , _fooE :: Either Text Int + , _fooNumber :: Int + , _fooList :: List Int + , _fooMap :: Map.Map Text Int + , _fooBaz :: Baz + , _fooTestSum :: TestSum + , _fooTestData :: TestData } - deriving (FromJSON, Generic, ToJSON) + deriving (FromJSON, Generic, Show, ToJSON) -makeLenses ''Foo +-- TODO newtype +data FooList = FooList (List Int) + deriving (FromJSON, Generic, Show, ToJSON) -fooProxy :: Proxy Foo -fooProxy = Proxy +instance {-# OVERLAPPING #-} ToJSON (Either Text Int) where + toEncoding = genericToEncoding + ( + defaultOptions + { tagSingleConstructors = True + , unwrapUnaryRecords = True + -- , sumEncoding = TaggedObject "foo" "bar" -- defaultTaggedObject { contentsFieldName = "value" } + } + ) + +instance {-# OVERLAPPING #-} FromJSON (Either Text Int) + +makeLenses ''Foo -- TODO newtype data Bar a = Bar a - deriving (Generic, Show, Typeable, FromJSON, ToJSON) + deriving (FromJSON, Generic, Show, ToJSON, Typeable) makeLenses ''Bar -barProxy :: Proxy Bar -barProxy = Proxy +additionalInstances = order . lenses . genericShow myBridge :: BridgePart myBridge = defaultBridge - -myTypes :: [SumType 'Haskell] -myTypes = - [ mkSumType (Proxy :: Proxy Baz) - , mkSumType (Proxy :: Proxy Foo) - , mkSumType (Proxy :: Proxy (Bar A)) - ] diff --git a/example/src/Types.purs b/example/src/Types.purs deleted file mode 100644 index 37731274..00000000 --- a/example/src/Types.purs +++ /dev/null @@ -1,98 +0,0 @@ --- File auto generated by purescript-bridge! -- -module Types where - -import Data.Argonaut.Aeson.Decode.Generic (genericDecodeAeson) -import Data.Argonaut.Aeson.Encode.Generic (genericEncodeAeson) -import Data.Argonaut.Aeson.Options as Argonaut -import Data.Argonaut.Decode.Class (class DecodeJson, class DecodeJsonField, decodeJson) -import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson) -import Data.Generic.Rep (class Generic) -import Data.Lens (Iso', Lens', Prism', lens, prism') -import Data.Lens.Iso.Newtype (_Newtype) -import Data.Lens.Record (prop) -import Data.Maybe (Maybe(..)) -import Data.Newtype (class Newtype) -import Foreign.Class (class Decode, class Encode) -import Foreign.Generic (defaultOptions, genericDecode, genericEncode) -import Foreign.Object (Object) -import Prim (Array, Int, String) -import Type.Proxy (Proxy(Proxy)) - -import Prelude - -newtype Baz = - Baz { - _bazMessage :: String - } - - - -instance encodeJsonBaz :: EncodeJson Baz where - encodeJson = genericEncodeAeson Argonaut.defaultOptions -instance decodeJsonBaz :: DecodeJson Baz where - decodeJson = genericDecodeAeson Argonaut.defaultOptions -derive instance genericBaz :: Generic Baz _ -derive instance newtypeBaz :: Newtype Baz _ - --------------------------------------------------------------------------------- -_Baz :: Iso' Baz { _bazMessage :: String} -_Baz = _Newtype - -bazMessage :: Lens' Baz String -bazMessage = _Newtype <<< prop (Proxy :: Proxy "_bazMessage") - --------------------------------------------------------------------------------- -newtype Foo = - Foo { - _fooMessage :: String - , _fooNumber :: Int - , _fooList :: Array Int - , _fooMap :: Object Int - , _fooBaz :: Baz - } - - - -instance encodeJsonFoo :: EncodeJson Foo where - encodeJson = genericEncodeAeson Argonaut.defaultOptions -instance decodeJsonFoo :: DecodeJson Foo where - decodeJson = genericDecodeAeson Argonaut.defaultOptions -derive instance genericFoo :: Generic Foo _ -derive instance newtypeFoo :: Newtype Foo _ - --------------------------------------------------------------------------------- -_Foo :: Iso' Foo { _fooMessage :: String, _fooNumber :: Int, _fooList :: Array Int, _fooMap :: Object Int, _fooBaz :: Baz} -_Foo = _Newtype - -fooMessage :: Lens' Foo String -fooMessage = _Newtype <<< prop (Proxy :: Proxy "_fooMessage") - -fooNumber :: Lens' Foo Int -fooNumber = _Newtype <<< prop (Proxy :: Proxy "_fooNumber") - -fooList :: Lens' Foo (Array Int) -fooList = _Newtype <<< prop (Proxy :: Proxy "_fooList") - -fooMap :: Lens' Foo (Object Int) -fooMap = _Newtype <<< prop (Proxy :: Proxy "_fooMap") - -fooBaz :: Lens' Foo Baz -fooBaz = _Newtype <<< prop (Proxy :: Proxy "_fooBaz") - --------------------------------------------------------------------------------- -newtype Bar a = - Bar a - - - -instance encodeJsonBar :: (Generic a ra, EncodeJson a) => EncodeJson (Bar a) where - encodeJson = genericEncodeAeson Argonaut.defaultOptions -instance decodeJsonBar :: (Generic a ra, DecodeJson a, DecodeJsonField a) => DecodeJson (Bar a) where - decodeJson = genericDecodeAeson Argonaut.defaultOptions -derive instance genericBar :: Generic a ra => Generic (Bar a) _ -derive instance newtypeBar :: Newtype (Bar a) _ - --------------------------------------------------------------------------------- -_Bar :: forall a. Iso' (Bar a) a -_Bar = _Newtype --------------------------------------------------------------------------------- diff --git a/example/static/index.html b/example/static/index.html index 7601961f..68fe7ba7 100644 --- a/example/static/index.html +++ b/example/static/index.html @@ -1,16 +1,17 @@
-