From 626ef9749470bd461954d9c46c9416602cdf1bd8 Mon Sep 17 00:00:00 2001 From: "Thomas R. Honeyman" Date: Mon, 31 Aug 2020 18:54:51 -0700 Subject: [PATCH 1/4] Update for library guidelines --- .editorconfig | 13 + .eslintrc.json | 47 +- .github/CONTRIBUTING.md | 5 + .github/ISSUE_TEMPLATE/bug-report.md | 19 + .github/ISSUE_TEMPLATE/change-request.md | 21 + .github/ISSUE_TEMPLATE/config.yml | 8 + .github/PULL_REQUEST_TEMPLATE.md | 11 + .github/contributing.md | 51 -- .github/issue_template.md | 22 - .github/pull_request_template.md | 15 - .github/workflows/ci.yml | 51 ++ .github/workflows/stale.yml | 23 + .gitignore | 22 +- .purs-repl | 1 + .travis.yml | 23 - README.md | 221 +----- docs/README.md | 157 ++++ package-lock.json | 897 +++++++++++++++++++++++ package.json | 10 +- packages.dhall | 4 + spago.dhall | 21 + src/Data/Argonaut/Core.js | 3 +- 22 files changed, 1290 insertions(+), 355 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/change-request.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 .github/contributing.md delete mode 100644 .github/issue_template.md delete mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/stale.yml create mode 100644 .purs-repl delete mode 100644 .travis.yml create mode 100644 docs/README.md create mode 100644 package-lock.json create mode 100644 packages.dhall create mode 100644 spago.dhall diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e717f5e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc.json b/.eslintrc.json index 84cef4f..17f167d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,28 +1,29 @@ { - "parserOptions": { - "ecmaVersion": 5 - }, + "env": { "browser": true, "commonjs": true }, "extends": "eslint:recommended", - "env": { - "commonjs": true - }, + "parserOptions": { "ecmaVersion": 5 }, "rules": { - "strict": [2, "global"], - "block-scoped-var": 2, - "consistent-return": 2, - "eqeqeq": [2, "smart"], - "guard-for-in": 2, - "no-caller": 2, - "no-extend-native": 2, - "no-loop-func": 2, - "no-new": 2, - "no-param-reassign": 2, - "no-return-assign": 2, - "no-unused-expressions": 2, - "no-use-before-define": 2, - "radix": [2, "always"], - "indent": [2, 2], - "quotes": [2, "double"], - "semi": [2, "always"] + "block-scoped-var": "error", + "consistent-return": "error", + "eqeqeq": "error", + "guard-for-in": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-extra-parens": "off", + "no-extend-native": "error", + "no-loop-func": "error", + "no-new": "error", + "no-param-reassign": "error", + "no-return-assign": "error", + "no-sequences": "error", + "no-unused-expressions": "error", + "no-use-before-define": "error", + "no-undef": "error", + "no-eq-null": "error", + "radix": ["error", "always"], + "indent": ["error", 2, { "SwitchCase": 1 }], + "quotes": ["error", "double"], + "semi": ["error", "always"], + "strict": ["error", "global"] } } diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..7709724 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,5 @@ +# Contributing to Argonaut Core + +Thanks for your interest in contributing to `argonaut-core`! We welcome new contributions regardless of your level of experience or familiarity with PureScript. + +Every library in the Contributors organization shares a simple handbook that helps new contributors get started. With that in mind, please [read the short contributing guide on purescript-contrib/governance](https://github.com/purescript-contrib/governance/blob/main/contributing.md) before contributing to this library. diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..b79b995 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,19 @@ +--- +name: Bug report +about: Report an issue +title: "" +labels: bug +assignees: "" +--- + +**Describe the bug** +A clear and concise description of the bug. + +**To Reproduce** +A minimal code example (preferably a runnable example on [Try PureScript](https://try.purescript.org)!) or steps to reproduce the issue. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/change-request.md b/.github/ISSUE_TEMPLATE/change-request.md new file mode 100644 index 0000000..a2ee685 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/change-request.md @@ -0,0 +1,21 @@ +--- +name: Change request +about: Propose an improvement to this library +title: "" +labels: "" +assignees: "" +--- + +**Is your change request related to a problem? Please describe.** +A clear and concise description of the problem. + +Examples: + +- It's frustrating to have to [...] +- I was looking for a function to [...] + +**Describe the solution you'd like** +A clear and concise description of what a good solution to you looks like, including any solutions you've already considered. + +**Additional context** +Add any other context about the change request here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..c47a263 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: PureScript Discourse + url: https://discourse.purescript.org/ + about: Ask and answer questions here. + - name: Functional Programming Slack + url: https://functionalprogramming.slack.com + about: For casual chat and questions (use https://fpchat-invite.herokuapp.com to join). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..d8780f7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ +**Description of the change** +Clearly and concisely describe the purpose of the pull request. If this PR relates to an existing issue or change proposal, please link to it. Include any other background context that would help reviewers understand the motivation for this PR. + +--- + +**Checklist:** + +- [ ] Added the change to the changelog's "Unreleased" section with a link to this PR and your username +- [ ] Linked any existing issues or proposals that this pull request should close +- [ ] Updated or added relevant documentation in the README and/or documentation directory +- [ ] Added a test for the contribution (if applicable) diff --git a/.github/contributing.md b/.github/contributing.md deleted file mode 100644 index f172ebc..0000000 --- a/.github/contributing.md +++ /dev/null @@ -1,51 +0,0 @@ -# Contribution - -Thank you for contributing to `purescript-argonaut-core`! - -Following these guidelines helps ensure we're able to carefully consider your contribution and help you finalize your pull request. Your time (like ours) is valuable, and we try to at least provide constructive feedback on every contribution. - -### Contributions we love -`purescript-argonaut-core` is an open-source library and we love to receive contributions. There are many ways you can contribute: - -* Help expand our test coverage -* Help fix open issues, even if that simply means adding a helpful comment -* Help push along open pull requests that need more work to be complete -* Improve or add new usage examples to better demonstrate how to use the library in real-world scenarios -* Update documentation and tutorials to be easier to understand, more comprehensive, and above all -- up to date! - -### Contributions we should discuss -Some contributions will take some discussion before we accept an update to the project. If your contribution includes one of the below examples (or seems to be reasonably similar), please consider reaching out to us before putting in a lot of work to build the feature. We're active on the [PureScript user forum](https://discourse.purescript.org/) and the [functional programming Slack](https://functionalprogramming.slack.com/) community (new? [use this link to join](https://fpchat-invite.herokuapp.com/)!). For feature requests, feel free to open an issue with a tag. - -* New features and functions that will change the library's public API -* New tutorials (while we love seeing new tutorials, we won't always be able to feature them in the readme) - -# Ground Rules - -We have a small set of quality-of-life guidelines for contributing to `purescript-argonaut-core`. These include: - -* All pull requests must pass continuous integration. -* If you are adding new functionality, you should provide tests and documentation for your code. If you're fixing an existing bug, please provide a failing test case your patch solves. -* If possible, please avoid requiring new dependencies. - -### Filing issues -If you have a general question about the project, it's best to ask on the [PureScript user forum](https://discourse.purescript.org/) or the [functional programming Slack](https://functionalprogramming.slack.com/) than to open a new issue. If you have run into a bug in the project, then please do open an issue! When you do, we ask that you follow a few steps which are outlined in our issues template. The gist of it is here: - -* Verify the problem is indeed with `purescript-argonaut-core` (not with Pulp, Bower, or PureScript); -* Record what versions you are using for PureScript and `purescript-argonaut-core` -* Describe the issue with steps to reproduce (as much as you are able). A minimal reproducible example is the absolute best case scenario. - -We promise to address the issue as soon as we can. - -### Suggesting features or enhancements -We love to hear about ways we could make better. If you're wishing for a feature that doesn't exist in `purescript-argonaut-core`, you're probably not alone; there are bound to be others with similar needs. Please feel free to open an issue on GitHub that describes: - -* the feature you would like to see -* why you need it -* how it should work - -We promise to review your issue, but we aren't always able to accommodate all requests. It helps if you're able to contribute to the implementation, too! - -### Code reviews -The core team looks at pull requests weekly, at which point we will review your code, ensure it meets our ground rules and fits with the philosophy of the project, and -- if necessary -- provide constructive feedback. As soon as at least one member of the team has signed off on your pull request, we will merge your contribution. - -If you opened a pull request and we need to ask a few questions, we expect responses within a month. After that we may close the pull request if it isn't showing any activity to keep things manageable. diff --git a/.github/issue_template.md b/.github/issue_template.md deleted file mode 100644 index a45db77..0000000 --- a/.github/issue_template.md +++ /dev/null @@ -1,22 +0,0 @@ -## Pre-check - -* For help and support, try the [PureScript user forum](https://discourse.purescript.org/) or the [functional programming Slack](https://functionalprogramming.slack.com) before opening an issue in the repository. -* For bug reports, do a quick search to ensure the bug has not yet been reported. -* For new feature requests, please remember to describe the feature you would like to see, why you need it, and how it might be implemented. -* Finally -- be nice and have fun! - ---- - -## Environment - -* PureScript **[version]** -* Pulp **[version]** -* `purescript-argonaut-core` **[version]** - -## Current behavior - -Please include code samples, errors, steps to reproduce, and compiler output if appropriate. - -If possible, provide a sample minimal app or test case that reproduces the error. For visual bugs that are difficult to demonstrate in text, consider including a .gif using an app like [Recordit](http://www.recordit.co/). - -## Expected behavior diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 7c16360..0000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,15 +0,0 @@ -## What does this pull request do? - -Please describe the purpose of the pull request, including any background context and links to related issues. If this introduces a large change to the project, please describe what you have implemented. - -## Where should the reviewer start? - -Help save the reviewer time by highlighting the most important sections of code. - -## How should this be manually tested? - -If this is a new feature, you should provide new test coverage. If it fixes an existing bug, you should provide a failing test case this change fixes. Other than automated testing, what manual tests can the reviewer perform to verify your work? - -## Other Notes: - -Does the project documentation need to be updated? Should we introduce a new example, or update any existing examples? Does this PR require any other follow-up tasks? diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..599d7c5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up PureScript toolchain + uses: purescript-contrib/setup-purescript@main + + - name: Cache PureScript dependencies + uses: actions/cache@v2 + with: + key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }} + path: | + .spago + output + + - name: Set up Node toolchain + uses: actions/setup-node@v1 + with: + node-version: "12.x" + + - name: Cache NPM dependencies + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install NPM dependencies + run: npm ci + + - name: Build the project + run: npm run build + + - name: Run tests + run: npm run test diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..002dae8 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,23 @@ +name: "Stale" + +on: + schedule: + - cron: "0 0 * * *" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v3 + env: + days-until-stale: 60 + days-until-close: 14 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: "This issue is stale because it has been open for ${{ env.days-until-stale }} days with no activity. Remove the stale label or comment to keep this issue open. Otherwise, this issue will be closed in ${{ env.days-until-close }} days." + stale-pr-message: "This pull request is stale because it has been open for ${{ env.days-until-stale }} days with no activity. Remove the stale label or comment to keep this pull request open. Otherwise, this pull request will be closed in ${{ env.days-until-close }} days." + days-before-stale: ${{ env.days-until-stale }} + days-before-close: ${{ env.days-until-close }} + stale-issue-label: "stale" + stale-pr-label: "stale" + exempt-pr-labels: "breaking change" diff --git a/.gitignore b/.gitignore index aac6732..83ca70d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,12 @@ -/.* -!/.gitignore -!/.github -!/.travis.yml +.* +!.gitignore +!.github +!.editorconfig +!.eslintrc.json -# Dependencies -bower_components -node_modules - -# Generated files output -dce-output generated-docs +bower_components -# Lockfiles -package-lock.json +node_modules *.lock - -# Extra files -!/.eslintrc.json diff --git a/.purs-repl b/.purs-repl new file mode 100644 index 0000000..6802fc7 --- /dev/null +++ b/.purs-repl @@ -0,0 +1 @@ +import Prelude diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6da455e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: node_js -dist: trusty -sudo: required -node_js: stable -env: - - PATH=$HOME/purescript:$PATH -install: - - TAG=$(basename $(curl --location --silent --output /dev/null -w %{url_effective} https://github.com/purescript/purescript/releases/latest)) - - curl --location --output $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz - - tar -xvf $HOME/purescript.tar.gz -C $HOME/ - - chmod a+x $HOME/purescript - - npm install -g bower - - npm install - - bower install --production -script: - - npm run -s build - - bower install - - npm run -s test -after_success: - - >- - test $TRAVIS_TAG && - echo $GITHUB_TOKEN | pulp login && - echo y | pulp publish --no-push diff --git a/README.md b/README.md index fcbd3fb..bc6049c 100644 --- a/README.md +++ b/README.md @@ -1,219 +1,44 @@ -# purescript-argonaut-core +# Argonaut Core -[![Latest release](http://img.shields.io/github/release/purescript-contrib/purescript-argonaut-core.svg)](https://github.com/purescript-contrib/purescript-argonaut-core/releases) -[![Build status](https://travis-ci.org/purescript-contrib/purescript-argonaut-core.svg?branch=master)](https://travis-ci.org/purescript-contrib/purescript-argonaut-core) -[![Pursuit](http://pursuit.purescript.org/packages/purescript-argonaut-core/badge)](http://pursuit.purescript.org/packages/purescript-argonaut-core/) -[![Maintainer: garyb](https://img.shields.io/badge/maintainer-garyb-lightgrey.svg)](http://github.com/garyb) -[![Maintainer: thomashoneyman](https://img.shields.io/badge/maintainer-thomashoneyman-lightgrey.svg)](http://github.com/thomashoneyman) +[![CI](https://github.com/purescript-contrib/purescript-argonaut-core/workflows/CI/badge.svg?branch=main)](https://github.com/purescript-contrib/purescript-argonaut-core/actions?query=workflow%3ACI+branch%3Amain) +[![Release](http://img.shields.io/github/release/purescript-contrib/purescript-argonaut-core.svg)](https://github.com/purescript-contrib/purescript-argonaut-core/releases) +[![Pursuit](http://pursuit.purescript.org/packages/purescript-argonaut-core/badge)](http://pursuit.purescript.org/packages/purescript-argonaut-core) +[![Maintainer: garyb](https://img.shields.io/badge/maintainer-garyb-teal.svg)](http://github.com/garyb) +[![Maintainer: thomashoneyman](https://img.shields.io/badge/maintainer-thomashoneyman-teal.svg)](http://github.com/thomashoneyman) -[Argonaut](https://github.com/purescript-contrib/purescript-argonaut) is a collection of libraries for working with JSON in PureScript. `argonaut-core` defines the core `Json` type, along with basic parsing, printing, and folding functions which operate on it. +The library summary hasn't been written yet (contributions are welcome!). The library summary describes the library's purpose in one to three sentences. ## Installation -This library is bundled as part of [Argonaut](https://github.com/purescript-contrib/purescript-argonaut) and can be installed via that library. To install just `argonaut-core`: +Install `argonaut-core` with [Spago](https://github.com/purescript/spago): ```sh -# with Spago spago install argonaut-core - -# with Bower -bower install purescript-argonaut-core -``` - -## Documentation - -Module documentation is [published on Pursuit](https://pursuit.purescript.org/packages/purescript-argonaut-core). You may also be interested in other libraries in the Argonaut ecosystem: - -- [purescript-argonaut-codecs](https://github.com/purescript-contrib/purescript-argonaut-codecs) provides codecs based on `EncodeJson` and `DecodeJson` type classes, along with instances for common data types and combinators for encoding and decoding `Json` values. -- [purescript-codec-argonaut](https://github.com/garyb/purescript-codec-argonaut) supports an alternative approach for codecs, which are based on profunctors instead of type classes. -- [purescript-argonaut-traversals](https://github.com/purescript-contrib/purescript-argonaut-traversals) defines prisms, traversals, and zippers for the `Json` type. -- [purescript-argonaut-generic](https://github.com/purescript-contrib/purescript-argonaut-generic) supports generic encoding and decoding for any type with a `Generic` instance. - -## Tutorial - -Some of Argonaut's functions might seem a bit arcane at first, so it can help -to understand the underlying design decisions which make it the way it is. - -One approach for modelling JSON values would be to define an algebraic data -type, like this: - -```purescript -data Json - = JNull - | JString String - | JNumber Number - | JBoolean Boolean - | JArray (Array Json) - | JObject (Object Json) ``` -And indeed, some might even say this is the obvious approach. +## Quick start -Because Argonaut is written with the compilation target of JavaScript in mind, -it takes a slightly different approach, which is to reuse the existing data -types which JavaScript already provides. This way, the result of JavaScript's -`JSON.parse` function is already a `Json` value, and no extra processing is -needed before you can start operating on it. This ought to help your program -both in terms of speed and memory churn. +The quick start hasn't been written yet (contributions are welcome!). The quick start covers a common, minimal use case for the library, whereas longer examples and tutorials are kept in the [docs directory](./docs.) -Much of the design of Argonaut follows naturally from this design decision. - -### Introducing Json values - -(Or, where do `Json` values come from?) - -If your program is receiving JSON data as a string, you probably want the -`jsonParser` function in `Data.Argonaut.Parser`, which is a very simple wrapper -around JavaScript's `JSON.parse`. - -Otherwise, `Json` values can be introduced into your program via the FFI or via -the construction functions in `Data.Argonaut.Core`. Here are some examples: - -```javascript -// In an FFI module. -exports.someNumber = 23.6; -exports.someBoolean = false; -exports.someObject = {people: [{name: "john"}, {name: "jane"}], common_interests: []}; -``` - -```purescript -foreign import someNumber :: Json -foreign import someBoolean :: Json -foreign import someObject :: Json -``` - -Generally, if a JavaScript value could be returned from a call to `JSON.parse`, -it's fine to import it from the FFI as `Json`. So, for example, objects, -booleans, numbers, strings, and arrays are all fine, but functions are not. - -The construction functions (that is, `fromX`, or `jsonX`) can be used as -follows: - -```purescript -import Data.Tuple (Tuple(..)) -import Foreign.Object as StrMap -import Data.Argonaut.Core as A - -someNumber = A.fromNumber 23.6 -someBoolean = A.fromBoolean false -someObject = A.fromObject (StrMap.fromFoldable [ - Tuple "people" (A.fromArray [ - A.jsonSingletonObject "name" (A.fromString "john"), - A.jsonSingletonObject "name" (A.fromString "jane") - ]), - Tuple "common_interests" A.jsonEmptyArray - ]) -``` - -### Eliminating/matching on `Json` values - -We can perform case analysis for `Json` values using the `caseJson` function. -This function is necessary because `Json` is not an algebraic data type. If -`Json` were an algebraic data type, we would not have as much need for this -function, because we could perform pattern matching with a `case ... of` -expression instead. - -The type of `caseJson` is: - -```purescript -caseJson - :: forall a - . (Unit -> a) - -> (Boolean -> a) - -> (Number -> a) - -> (String -> a) - -> (Array Json -> a) - -> (Object Json -> a) - -> Json - -> a -``` - -That is, `caseJson` takes six functions, which all must return values of some -particular type `a`, together with one `Json` value. `caseJson` itself also -returns a value of the same type `a`. - -A use of `caseJson` is very similar to a `case ... of` expression, as it allows -you to handle each of the six possibilities for the `Json` value you passed in. Thinking of it this way, each of the six function arguments is like one of the -case alternatives. - -The function that takes `Unit` as an argument is for matching `null` values. As there is only one possible `null` value, we use the PureScript `Unit` type, as correspondingly there is only one possible `Unit` value. - -Just like in a `case ... of` expression, the final value -that the whole expression evaluates to comes from evaluating exactly one of the -'alternatives' (functions) that you pass in. In fact, you can tell that this -is the case just by looking at the type signature of `caseJson`, because of a -property called *parametricity* (although a deeper explanation of parametricity -is outside the scope of this tutorial). - -For example, imagine we had the following values defined in JavaScript and -imported via the FFI: - -```javascript -exports.anotherNumber = 0.0; -exports.anotherArray = [0.0, {foo: 'bar'}, false]; -exports.anotherObject = {foo: 1, bar: [2,2]}; -``` - -Then we can match on them in PureScript using `caseJson`: - -```purescript -foreign import anotherNumber :: Json -foreign import anotherArray :: Json -foreign import anotherObject :: Json - -basicInfo :: Json -> String -basicInfo = caseJson - (const "It was null") - (\b -> "Got a boolean: " <> - if b then "it was true!" else "It was false.") - (\x -> "Got a number: " <> show x) - (\s -> "Got a string, which was " <> Data.String.length s <> - " characters long.") - (\xs -> "Got an array, which had " <> Data.Array.length xs <> - " items.") - (\obj -> "Got an object, which had " <> Foreign.Object.size obj <> - " items.") -``` - -```purescript -basicInfo anotherNumber -- => "Got a number: 0.0" -basicInfo anotherArray -- => "Got an array, which had 3 items." -basicInfo anotherObject -- => "Got an object, which had 2 items." -``` +## Documentation -`caseJson` is the fundamental function for pattern matching on `Json` values; -any kind of pattern matching you might want to do can be done with `caseJson`. +`argonaut-core` documentation is stored in a few places: -However, `caseJson` is not always comfortable to use, so Argonaut provides a -few other simpler versions for convenience. For example, the `caseJsonX` -functions can be used to match on a specific type. The first argument acts as a -default value, to be used if the `Json` value turned out not to be that type. -For example, we can write a function which tests whether a JSON value is the -string "lol" like this: +1. Module documentation is [published on Pursuit](https://pursuit.purescript.org/packages/purescript-argonaut-core). +2. Written documentation and [the changelog](./docs/CHANGELOG.md) are kept in [the docs directory](./docs). +3. Usage examples can be found in [the test suite](./test). -```purescript -caseJsonString :: forall a. a -> (String -> a) -> Json -> a +If you get stuck, there are several ways to get help: -isJsonLol = caseJsonString false (_ == "lol") -``` +- [Open an issue](https://github.com/purescript-contrib/purescript-argonaut-core/issues) if you have encountered a bug or problem. +- [Search or start a thread on the PureScript Discourse](https://discourse.purescript.org) if you have general questions. You can also ask questions in the `#purescript` and `#purescript-beginners` channels on the [Functional Programming Slack](https://functionalprogramming.slack.com) ([invite link](https://fpchat-invite.herokuapp.com/)). -If the `Json` value is not a string, the default `false` is used. Otherwise, -we test whether the string is equal to "lol". - -The `toX` functions also occupy a similar role: they attempt to convert `Json` -values into a specific type. If the json value you provide is of the right -type, you'll get a `Just` value. Otherwise, you'll get `Nothing`. For example, -we could have written `isJsonLol` like this, too: +## Contributing -```purescript -toString :: Json -> Maybe String +You can contribute to `argonaut-core` in several ways: -isJsonLol json = - case toString json of - Just str -> str == "lol" - Nothing -> false -``` +1. If you encounter a problem or have a question, please [open an issue](https://github.com/purescript-contrib/purescript-argonaut-core/issues). We'll do our best to work with you to resolve or answer it. -## Contributing +2. If you would like to contribute code, tests, or documentation, please [read the contributor guide](./.github/CONTRIBUTING.md). It's a short, helpful introduction to contributing to this library, including development instructions. -Read the [contribution guidelines](https://github.com/purescript-contrib/purescript-argonaut-core/blob/master/.github/contributing.md) to get started and see helpful related resources. +3. If you have written a library, tutorial, guide, or other resource based on this package, please share it on the [PureScript Discourse](https://discourse.purescript.org)! Writing libraries and learning resources are a great way to help this library succeed. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..09721ff --- /dev/null +++ b/docs/README.md @@ -0,0 +1,157 @@ +# Argonaut Core Documentation + +This directory contains documentation for `argonaut-core`. If you are interested in contributing new documentation, please read the [contributor guidelines](../.github/CONTRIBUTING.md) and [What Nobody Tells You About Documentation](https://documentation.divio.com) for help getting started. + +## Tutorial + +Some of Argonaut's functions might seem a bit arcane at first, so it can help to understand the underlying design decisions which make it the way it is. + +One approach for modelling JSON values would be to define an algebraic data type, like this: + +```purs +data Json + = JNull + | JString String + | JNumber Number + | JBoolean Boolean + | JArray (Array Json) + | JObject (Object Json) +``` + +And indeed, some might even say this is the obvious approach. + +Because Argonaut is written with the compilation target of JavaScript in mind, it takes a slightly different approach, which is to reuse the existing data types which JavaScript already provides. This way, the result of JavaScript's `JSON.parse` function is already a `Json` value, and no extra processing is needed before you can start operating on it. This ought to help your program both in terms of speed and memory churn. + +Much of the design of Argonaut follows naturally from this design decision. + +### Introducing Json values + +(Or, where do `Json` values come from?) + +If your program is receiving JSON data as a string, you probably want the `jsonParser` function in `Data.Argonaut.Parser`, which is a very simple wrapper around JavaScript's `JSON.parse`. + +Otherwise, `Json` values can be introduced into your program via the FFI or via the construction functions in `Data.Argonaut.Core`. Here are some examples: + +```js +// In an FFI module. +exports.someNumber = 23.6; +exports.someBoolean = false; +exports.someObject = { + people: [{ name: "john" }, { name: "jane" }], + common_interests: [], +}; +``` + +```purs +foreign import someNumber :: Json +foreign import someBoolean :: Json +foreign import someObject :: Json +``` + +Generally, if a JavaScript value could be returned from a call to `JSON.parse`, it's fine to import it from the FFI as `Json`. So, for example, objects, booleans, numbers, strings, and arrays are all fine, but functions are not. + +The construction functions (that is, `fromX`, or `jsonX`) can be used as follows: + +```purs +import Data.Tuple (Tuple(..)) +import Foreign.Object as Object +import Data.Argonaut.Core as A + +someNumber = A.fromNumber 23.6 + +someBoolean = A.fromBoolean false + +someObject = + A.fromObject + ( Object.fromFoldable + [ Tuple "people" + ( A.fromArray + [ A.jsonSingletonObject "name" (A.fromString "john") + , A.jsonSingletonObject "name" (A.fromString "jane") + ] + ) + , Tuple "common_interests" A.jsonEmptyArray + ] + ) +``` + +### Eliminating/matching on `Json` values + +We can perform case analysis for `Json` values using the `caseJson` function. This function is necessary because `Json` is not an algebraic data type. If `Json` were an algebraic data type, we would not have as much need for this function, because we could perform pattern matching with a `case ... of` expression instead. + +The type of `caseJson` is: + +```purs +caseJson + :: forall a + . (Unit -> a) + -> (Boolean -> a) + -> (Number -> a) + -> (String -> a) + -> (Array Json -> a) + -> (Object Json -> a) + -> Json + -> a +``` + +That is, `caseJson` takes six functions, which all must return values of some particular type `a`, together with one `Json` value. `caseJson` itself also returns a value of the same type `a`. + +A use of `caseJson` is very similar to a `case ... of` expression, as it allows you to handle each of the six possibilities for the `Json` value you passed in. Thinking of it this way, each of the six function arguments is like one of the case alternatives. + +The function that takes `Unit` as an argument is for matching `null` values. As there is only one possible `null` value, we use the PureScript `Unit` type, as correspondingly there is only one possible `Unit` value. + +Just like in a `case ... of` expression, the final value that the whole expression evaluates to comes from evaluating exactly one of the 'alternatives' (functions) that you pass in. In fact, you can tell that this is the case just by looking at the type signature of `caseJson`, because of a property called _parametricity_ (although a deeper explanation of parametricity is outside the scope of this tutorial). + +For example, imagine we had the following values defined in JavaScript and imported via the FFI: + +```js +exports.anotherNumber = 0.0; +exports.anotherArray = [0.0, { foo: "bar" }, false]; +exports.anotherObject = { foo: 1, bar: [2, 2] }; +``` + +Then we can match on them in PureScript using `caseJson`: + +```purs +foreign import anotherNumber :: Json +foreign import anotherArray :: Json +foreign import anotherObject :: Json + +basicInfo :: Json -> String +basicInfo = caseJson + (const "It was null") + (\b -> "Got a boolean: " <> if b then "it was true!" else "It was false.") + (\x -> "Got a number: " <> show x) + (\s -> "Got a string, which was " <> Data.String.length s <> " characters long.") + (\xs -> "Got an array, which had " <> Data.Array.length xs <> " items.") + (\obj -> "Got an object, which had " <> Foreign.Object.size obj <> " items.") +``` + +```purs +basicInfo anotherNumber -- => "Got a number: 0.0" +basicInfo anotherArray -- => "Got an array, which had 3 items." +basicInfo anotherObject -- => "Got an object, which had 2 items." +``` + +`caseJson` is the fundamental function for pattern matching on `Json` values; any kind of pattern matching you might want to do can be done with `caseJson`. + +However, `caseJson` is not always comfortable to use, so Argonaut provides a few other simpler versions for convenience. For example, the `caseJsonX` functions can be used to match on a specific type. The first argument acts as a default value, to be used if the `Json` value turned out not to be that type. For example, we can write a function which tests whether a JSON value is the string "lol" like this: + +```purs +caseJsonString :: forall a. a -> (String -> a) -> Json -> a + +isJsonLol = caseJsonString false (_ == "lol") +``` + +If the `Json` value is not a string, the default `false` is used. Otherwise, we test whether the string is equal to "lol". + +The `toX` functions also occupy a similar role: they attempt to convert `Json` values into a specific type. If the json value you provide is of the right type, you'll get a `Just` value. Otherwise, you'll get `Nothing`. For example, we could have written `isJsonLol` like this, too: + +```purs +toString :: Json -> Maybe String + +isJsonLol json = + case toString json of + Just str -> str == "lol" + Nothing -> false +``` diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d07be4b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,897 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@eslint/eslintrc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.0.tgz", + "integrity": "sha512-bfL5365QSCmH6cPeFT7Ywclj8C7LiF7sO6mUGzZhtAMV7iID1Euq6740u/SRi4C80NOnVz/CEfK8/HO+nCAPJg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "import-fresh": "^3.2.1", + "strip-json-comments": "^3.1.1" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, + "ajv": { + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.8.0.tgz", + "integrity": "sha512-qgtVyLZqKd2ZXWnLQA4NtVbOyH56zivOAdBFWE54RFkSZjokzNrcP4Z0eVWsZ+84ByXv+jL9k/wE1ENYe8xRFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.1.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } + } +} diff --git a/package.json b/package.json index b89c012..ad3ecca 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,10 @@ { "private": true, "scripts": { - "clean": "rimraf output && rimraf .pulp-cache", - "build": "eslint src && pulp build -- --censor-lib --strict", - "test": "pulp test" + "build": "eslint src && spago build --purs-args '--censor-lib --strict'", + "test": "spago test --no-install" }, "devDependencies": { - "eslint": "^6.8.0", - "pulp": "^14.0.0", - "purescript-psa": "^0.7.3", - "rimraf": "^3.0.2" + "eslint": "^7.6.0" } } diff --git a/packages.dhall b/packages.dhall new file mode 100644 index 0000000..6413e8d --- /dev/null +++ b/packages.dhall @@ -0,0 +1,4 @@ +let upstream = + https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20200831/packages.dhall sha256:cdb3529cac2cd8dd780f07c80fd907d5faceae7decfcaa11a12037df68812c83 + +in upstream diff --git a/spago.dhall b/spago.dhall new file mode 100644 index 0000000..1797f0f --- /dev/null +++ b/spago.dhall @@ -0,0 +1,21 @@ +{ name = "argonaut-core" +, dependencies = + [ "arrays" + , "console" + , "control" + , "effect" + , "either" + , "foreign-object" + , "functions" + , "gen" + , "maybe" + , "nonempty" + , "prelude" + , "psci-support" + , "quickcheck" + , "strings" + , "tailrec" + ] +, packages = ./packages.dhall +, sources = [ "src/**/*.purs", "test/**/*.purs" ] +} diff --git a/src/Data/Argonaut/Core.js b/src/Data/Argonaut/Core.js index 3f8f010..7a2d14f 100644 --- a/src/Data/Argonaut/Core.js +++ b/src/Data/Argonaut/Core.js @@ -1,3 +1,4 @@ +/* eslint-disable no-eq-null, eqeqeq */ "use strict"; function id(x) { @@ -30,7 +31,7 @@ exports._caseJson = function (isNull, isBool, isNum, isStr, isArr, isObj, j) { else return isObj(j); }; -exports._compare = function _compare (EQ, GT, LT, a, b) { +exports._compare = function _compare(EQ, GT, LT, a, b) { if (a == null) { if (b == null) return EQ; else return LT; From e8e48a5cd194d54cc671caedc53d25a2f532932f Mon Sep 17 00:00:00 2001 From: "Thomas R. Honeyman" Date: Mon, 31 Aug 2020 18:56:39 -0700 Subject: [PATCH 2/4] How did purs-repl slip in there? --- .purs-repl | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .purs-repl diff --git a/.purs-repl b/.purs-repl deleted file mode 100644 index 6802fc7..0000000 --- a/.purs-repl +++ /dev/null @@ -1 +0,0 @@ -import Prelude From 4aa144dd0e23296df3a8d82e7002532b932c3a32 Mon Sep 17 00:00:00 2001 From: "Thomas R. Honeyman" Date: Mon, 31 Aug 2020 19:19:14 -0700 Subject: [PATCH 3/4] Update README --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc6049c..005bb0f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Maintainer: garyb](https://img.shields.io/badge/maintainer-garyb-teal.svg)](http://github.com/garyb) [![Maintainer: thomashoneyman](https://img.shields.io/badge/maintainer-thomashoneyman-teal.svg)](http://github.com/thomashoneyman) -The library summary hasn't been written yet (contributions are welcome!). The library summary describes the library's purpose in one to three sentences. +The core `Json` type for the [Argonaut](https://github.com/purescript-contrib/purescript-argonaut) libraries, along with basic parsing, printing, and folding functions which operate on it. ## Installation @@ -16,9 +16,69 @@ Install `argonaut-core` with [Spago](https://github.com/purescript/spago): spago install argonaut-core ``` +or install it as part of the [Argonaut](https://github.com/purescript-contrib/purescript-argonaut) bundle: + +```sh +spago install argonaut +``` + ## Quick start -The quick start hasn't been written yet (contributions are welcome!). The quick start covers a common, minimal use case for the library, whereas longer examples and tutorials are kept in the [docs directory](./docs.) +Use the `Json` type to represent JSON data in PureScript. You can produce a value of `Json` via the FFI or by functions from `Data.Argonaut.Core`. + +For example, via the FFI: + +```js +// In an FFI module +exports.someNumber = 23.6; +exports.someObject = { people: [{ name: "John" }, { name: "Jane" }] }; +``` + +```purs +foreign import someNumber :: Json +foreign import someObject :: Json +``` + +In general, if a JavaScript value could be returned from a call to `JSON.parse` then you can import it via the FFI as `Json`. That includes objects, booleans, numbers, strings, and arrays (but not things like functions). + +You can also use the construction functions which follow the naming convention `fromX` or `jsonX`: + +```purs +import Data.Tuple (Tuple(..)) +import Foreign.Object as Object +import Data.Argonaut.Core as A + +someNumber :: Json +someNumber = A.fromNumber 23.6 + +someObject :: Json +someObject = + A.fromObject + ( Object.fromFoldable + [ Tuple "people" + ( A.fromArray + [ A.jsonSingletonObject "name" (A.fromString "John") + , A.jsonSingletonObject "name" (A.fromString "Jane") + ] + ) + ] + ) +``` + +Finally, you can parse JSON from a string using the `jsonParser` function. However, this isn't guaranteed to produce a correct value, so it returns a `Maybe` value. + +```purs +import Data.Argonaut.Core (jsonParser) +import Data.Maybe (Maybe(..)) + +someObject :: Maybe Json +someObject = jsonParser + """ + { people: [{ name: "John" }, { name: "Jane" }] }; + """ +``` + +See the [docs](./docs) for an in-depth overview of the rest of the Argonaut Core library. ## Documentation From 3dae38570258a380cf12329e0bd306a7f386d156 Mon Sep 17 00:00:00 2001 From: "Thomas R. Honeyman" Date: Mon, 31 Aug 2020 19:25:17 -0700 Subject: [PATCH 4/4] Add references to other Argonaut libraries --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 005bb0f..f5f7bf4 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,12 @@ someObject = jsonParser """ ``` -See the [docs](./docs) for an in-depth overview of the rest of the Argonaut Core library. +See the [docs](./docs) for an in-depth overview of the rest of the Argonaut Core library. You may also be interested in other libraries in the Argonaut ecosystem: + +- [purescript-argonaut-codecs](https://github.com/purescript-contrib/purescript-argonaut-codecs) provides codecs based on `EncodeJson` and `DecodeJson` type classes, along with instances for common data types and combinators for encoding and decoding `Json` values. +- [purescript-codec-argonaut](https://github.com/garyb/purescript-codec-argonaut) supports an alternative approach for codecs, which are based on profunctors instead of type classes. +- [purescript-argonaut-traversals](https://github.com/purescript-contrib/purescript-argonaut-traversals) defines prisms, traversals, and zippers for the `Json` type. +- [purescript-argonaut-generic](https://github.com/purescript-contrib/purescript-argonaut-generic) supports generic encoding and decoding for any type with a `Generic` instance. ## Documentation